From 7394e7e735f39eb42ef7ac2e2ed6de268202e807 Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Mon, 12 May 2025 15:51:02 +0200 Subject: [PATCH 01/17] wip --- hyle-wallet/.env | 6 + hyle-wallet/.gitignore | 24 + hyle-wallet/bun.lockb | Bin 0 -> 133892 bytes hyle-wallet/index.css | 23 + hyle-wallet/index.html | 12 + hyle-wallet/package-lock.json | 91 ++++ hyle-wallet/package.json | 50 ++ hyle-wallet/src/components/HyleWallet.css | 452 ++++++++++++++++++ hyle-wallet/src/components/HyleWallet.tsx | 196 ++++++++ hyle-wallet/src/components/auth/AuthForm.tsx | 117 +++++ hyle-wallet/src/hooks/useConfig.ts | 27 ++ hyle-wallet/src/index.ts | 25 + .../src/providers/AuthProviderManager.ts | 33 ++ hyle-wallet/src/providers/BaseAuthProvider.ts | 19 + .../src/providers/GoogleAuthProvider.ts | 24 + .../src/providers/PasswordAuthProvider.ts | 153 ++++++ hyle-wallet/src/services/IndexerService.ts | 80 ++++ hyle-wallet/src/services/NodeService.ts | 11 + hyle-wallet/src/services/SessionKeyService.ts | 92 ++++ hyle-wallet/src/services/WebSocketService.ts | 128 +++++ hyle-wallet/src/services/config.ts | 13 + hyle-wallet/src/types/auth.ts | 13 + hyle-wallet/src/types/wallet.ts | 190 ++++++++ hyle-wallet/src/vite-env.d.ts | 14 + hyle-wallet/tsconfig.app.json | 26 + hyle-wallet/tsconfig.json | 7 + hyle-wallet/tsconfig.node.json | 24 + hyle-wallet/vite.config.ts | 11 + 28 files changed, 1861 insertions(+) create mode 100644 hyle-wallet/.env create mode 100644 hyle-wallet/.gitignore create mode 100755 hyle-wallet/bun.lockb create mode 100644 hyle-wallet/index.css create mode 100644 hyle-wallet/index.html create mode 100644 hyle-wallet/package-lock.json create mode 100644 hyle-wallet/package.json create mode 100644 hyle-wallet/src/components/HyleWallet.css create mode 100644 hyle-wallet/src/components/HyleWallet.tsx create mode 100644 hyle-wallet/src/components/auth/AuthForm.tsx create mode 100644 hyle-wallet/src/hooks/useConfig.ts create mode 100644 hyle-wallet/src/index.ts create mode 100644 hyle-wallet/src/providers/AuthProviderManager.ts create mode 100644 hyle-wallet/src/providers/BaseAuthProvider.ts create mode 100644 hyle-wallet/src/providers/GoogleAuthProvider.ts create mode 100644 hyle-wallet/src/providers/PasswordAuthProvider.ts create mode 100644 hyle-wallet/src/services/IndexerService.ts create mode 100644 hyle-wallet/src/services/NodeService.ts create mode 100644 hyle-wallet/src/services/SessionKeyService.ts create mode 100644 hyle-wallet/src/services/WebSocketService.ts create mode 100644 hyle-wallet/src/services/config.ts create mode 100644 hyle-wallet/src/types/auth.ts create mode 100644 hyle-wallet/src/types/wallet.ts create mode 100644 hyle-wallet/src/vite-env.d.ts create mode 100644 hyle-wallet/tsconfig.app.json create mode 100644 hyle-wallet/tsconfig.json create mode 100644 hyle-wallet/tsconfig.node.json create mode 100644 hyle-wallet/vite.config.ts diff --git a/hyle-wallet/.env b/hyle-wallet/.env new file mode 100644 index 0000000..d305c2d --- /dev/null +++ b/hyle-wallet/.env @@ -0,0 +1,6 @@ +VITE_SERVER_BASE_URL=http://localhost:4000 +VITE_WS_URL=ws://localhost:8081/ws +VITE_NODE_BASE_URL=http://localhost:4321 +VITE_INDEXER_BASE_URL=http://localhost:4321 +VITE_TX_EXPLORER_URL=http://localhost:8000 +VITE_FAUCET_URL=http://localhost:5173 diff --git a/hyle-wallet/.gitignore b/hyle-wallet/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/hyle-wallet/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/hyle-wallet/bun.lockb b/hyle-wallet/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..a797b68094d523e70cf5d9fad41dfca5c77c9f55 GIT binary patch literal 133892 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 literal 0 HcmV?d00001 diff --git a/hyle-wallet/index.css b/hyle-wallet/index.css new file mode 100644 index 0000000..4d938d5 --- /dev/null +++ b/hyle-wallet/index.css @@ -0,0 +1,23 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + min-width: 320px; + min-height: 100vh; + background-color: #ffffff; +} diff --git a/hyle-wallet/index.html b/hyle-wallet/index.html new file mode 100644 index 0000000..1121644 --- /dev/null +++ b/hyle-wallet/index.html @@ -0,0 +1,12 @@ + + + + + + HyleWallet Demo + + + + + + \ No newline at end of file diff --git a/hyle-wallet/package-lock.json b/hyle-wallet/package-lock.json new file mode 100644 index 0000000..feca975 --- /dev/null +++ b/hyle-wallet/package-lock.json @@ -0,0 +1,91 @@ +{ + "name": "hyle-wallet", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "hyle-wallet", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@types/node": "^22.15.17", + "@types/react": "^19.1.3", + "@types/react-dom": "^19.1.3", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "typescript": "^5.8.3" + } + }, + "node_modules/@types/node": { + "version": "22.15.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz", + "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/react": { + "version": "19.1.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.3.tgz", + "integrity": "sha512-dLWQ+Z0CkIvK1J8+wrDPwGxEYFA4RAyHoZPxHVGspYmFVnwGSNT24cGIhFJrtfRnWVuW8X7NO52gCXmhkVUWGQ==", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.1.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.3.tgz", + "integrity": "sha512-rJXC08OG0h3W6wDMFxQrZF00Kq6qQvw0djHRdzl3U5DnIERz0MRce3WVc7IS6JYBwtaP/DwYtRRjVlvivNveKg==", + "peerDependencies": { + "@types/react": "^19.0.0" + } + }, + "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/react": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", + "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", + "dependencies": { + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.0" + } + }, + "node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==" + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==" + } + } +} diff --git a/hyle-wallet/package.json b/hyle-wallet/package.json new file mode 100644 index 0000000..bf5b93f --- /dev/null +++ b/hyle-wallet/package.json @@ -0,0 +1,50 @@ +{ + "name": "hyle-wallet", + "version": "1.0.0", + "type": "module", + "description": "A reusable wallet component for React applications", + "main": "dist/index.js", + "module": "dist/index.mjs", + "types": "dist/index.d.ts", + "files": [ + "dist" + ], + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@types/crypto-js": "^4.2.2", + "@types/elliptic": "^6.4.18", + "@types/react-router-dom": "^5.3.3", + "crypto-js": "^4.2.0", + "elliptic": "^6.6.1", + "hyle": "^0.2.5", + "hyle-check-secret": "^0.3.2", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-router-dom": "^7.5.0" + }, + "devDependencies": { + "@eslint/js": "^9.24.0", + "@types/react": "^19.1.2", + "@types/react-dom": "^19.1.2", + "@vitejs/plugin-react": "^4.4.0", + "autoprefixer": "^10.4.21", + "eslint": "^9.24.0", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.19", + "globals": "^15.15.0", + "postcss": "^8.5.3", + "tailwindcss": "^4.1.4", + "typescript": "~5.7.3", + "typescript-eslint": "^8.30.1", + "vite": "^6.2.6" + } +} diff --git a/hyle-wallet/src/components/HyleWallet.css b/hyle-wallet/src/components/HyleWallet.css new file mode 100644 index 0000000..163f2d2 --- /dev/null +++ b/hyle-wallet/src/components/HyleWallet.css @@ -0,0 +1,452 @@ +/* === Design tokens & motion === */ +:root { + --color-primary: #FF594B; + --color-secondary: #FF9660; + --color-primary-emphasis: rgba(255, 89, 75, 0.2); + --radius-l: 24px; + --shadow-xl: 0 12px 32px rgba(0, 0, 0, 0.12); + --overlay-bg: rgba(0, 0, 0, 0.5); + --modal-bg: rgba(255, 255, 255, 0.75); + --anim-ease: cubic-bezier(.16,1,.3,1); + --anim-fast: 120ms; + --anim-normal: 220ms; + } + + @keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } + } + + @keyframes slideUp { + from { transform: translateY(24px) scale(0.98); opacity: 0; } + to { transform: translateY(0) scale(1); opacity: 1; } + } + + .hyle-wallet-btn { + padding: 12px 24px; + background: linear-gradient(90deg, var(--color-primary) 0%, var(--color-secondary) 100%); + color: #fff; + border: none; + border-radius: var(--radius-l); + cursor: pointer; + font-size: 16px; + font-weight: 600; + box-shadow: var(--shadow-xl); + transition: transform var(--anim-fast) var(--anim-ease), opacity var(--anim-fast) var(--anim-ease); + } + + .hyle-wallet-btn:hover { + opacity: 0.9; + transform: scale(0.98); + } + + /* Overlay */ + .hyle-wallet-overlay { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background: var(--overlay-bg); + backdrop-filter: blur(8px) saturate(120%); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + animation: fadeIn var(--anim-normal) var(--anim-ease); + } + + /* Modal */ + .hyle-wallet-modal { + background: var(--modal-bg); + backdrop-filter: blur(16px) saturate(180%); + border: 1px solid rgba(255, 255, 255, 0.3); + border-radius: var(--radius-l); + box-shadow: var(--shadow-xl); + width: min(90%, 420px); + min-height: min-content; + max-height: 90vh; + overflow-y: auto; + overflow-x: hidden; + padding: 0 24px 28px; + position: relative; + animation: slideUp 0.3s var(--anim-ease); + margin: 16px; + display: flex; + flex-direction: column; + } + + /* Modal header with brand gradient */ + .modal-header { + height: 56px; + background: linear-gradient(90deg, var(--color-primary) 0%, var(--color-secondary) 100%); + border-top-left-radius: var(--radius-l); + border-top-right-radius: var(--radius-l); + display: flex; + align-items: center; + justify-content: center; + position: relative; + margin: 0 -24px 24px; /* stretch full width, then push content */ + } + + .modal-logo { + margin: 0; + display: flex; + justify-content: center; + } + + .hyle-modal-close { + position: absolute; + right: 12px; + top: 50%; + transform: translateY(-50%); + background: transparent; + border: none; + color: #fff; + font-size: 24px; + cursor: pointer; + transition: transform var(--anim-fast) var(--anim-ease); + } + + .hyle-modal-close:hover { + transform: translateY(-50%) rotate(45deg); + } + + .provider-selection h2 { + margin-top: 0; + text-align: center; + font-size: 24px; + color: #333; + } + + .password-provider-flow .auth-title { + margin: 0 0 20px 0; + text-align: center; + font-size: 24px; + color: #333; + } + + .provider-selection .subtitle { + text-align: center; + color: #666; + margin: 8px 0 24px; + font-size: 14px; + } + + .provider-grid { + display: flex; + flex-wrap: wrap; + gap: 12px; + justify-content: center; + margin-top: 16px; + } + + .hyle-provider-btn { + flex: 1 1 40%; + padding: 12px 8px; + border: 1px solid #ccc; + border-radius: 4px; + background: #f9f9f9; + cursor: pointer; + font-size: 14px; + } + + .hyle-provider-btn:disabled { + opacity: 0.6; + cursor: not-allowed; + } + + .coming-soon { + font-size: 12px; + color: #999; + } + + .password-provider-flow .switch-auth-button, + .provider-coming-soon .back-to-providers { + margin-top: 16px; + width: 100%; + padding: 8px; + border: none; + background: #eee; + cursor: pointer; + border-radius: 4px; + } + + /* Sleek link-style button for toggling between login and sign-up */ + .password-provider-flow .switch-auth-button { + /* link style button */ + background: none; + color: var(--color-primary); + font-size: 14px; + width: auto; + padding: 0; + } + + .password-provider-flow .switch-auth-button:hover { + opacity: 0.8; + text-decoration: none; + } + + /* Provider vertical list */ + .provider-list { + display: flex; + flex-direction: column; + gap: 12px; + margin-top: 16px; + } + + .provider-row { + width: 100%; + padding: 12px 16px; + border: 1px solid #e5e5e5; + border-radius: 8px; + background: #fff; + display: flex; + align-items: center; + justify-content: space-between; + font-size: 16px; + cursor: pointer; + transition: background 0.15s ease; + } + + .provider-row:hover:not(.disabled) { + background: #f2f2f2; + } + + .provider-row.disabled { + opacity: 0.6; + cursor: not-allowed; + } + + .provider-icon { + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border-radius: 50%; + background-color: #f5f5f5; + color: #333; + } + + .provider-row .provider-icon svg { + display: block; + } + + /* Email field styling */ + .provider-row:first-child { + position: relative; + background-color: white; + border-radius: 8px; + overflow: hidden; + } + + .label { + display: flex; + align-items: center; + gap: 12px; + } + + .row-arrow { + font-size: 20px; + } + + .password-provider-flow .wallet-login-container h1, + .password-provider-flow .wallet-creation-container h1 { + display: none; + } + + .password-provider-flow .wallet-creation-form p { + display: none; + } + + /* === Auth Components Styling === */ + .password-provider-flow .wallet-login-container, + .password-provider-flow .wallet-creation-container { + /* Already hides h1 */ + } + + .password-provider-flow .form-group { + margin-bottom: 10px; + } + + .password-provider-flow .form-group label { + display: block; + margin-bottom: 4px; + font-size: 14px; + font-weight: 500; + color: #333; + } + + .password-provider-flow input { + width: 100%; + height: 42px; + background: rgba(255, 255, 255, 0.8); + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 12px; + font-size: 15px; + transition: border-color var(--anim-fast) ease; + position: relative; + } + + .password-provider-flow .form-group { + position: relative; + } + + /* + .password-provider-flow .form-group::before { + content: ""; + position: absolute; + left: 12px; + top: 34px; + width: 16px; + height: 16px; + background-repeat: no-repeat; + background-position: center; + opacity: 0.5; + } + + .password-provider-flow .form-group:nth-of-type(1)::before { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2'%3E%3C/path%3E%3Ccircle cx='12' cy='7' r='4'%3E%3C/circle%3E%3C/svg%3E"); + } + + .password-provider-flow .form-group:nth-of-type(2)::before, + .password-provider-flow .form-group:nth-of-type(3)::before { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2' ry='2'%3E%3C/rect%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'%3E%3C/path%3E%3C/svg%3E"); + } + */ + + .password-provider-flow input:focus { + outline: none; + border-color: var(--color-primary); + box-shadow: 0 0 0 3px var(--color-primary-emphasis); + } + + .password-provider-flow .login-wallet-button, + .password-provider-flow .create-wallet-button { + width: 100%; + height: 48px; + background: linear-gradient(90deg, var(--color-primary) 0%, var(--color-secondary) 100%); + color: #fff; + border: none; + border-radius: 24px; + font-size: 16px; + font-weight: 600; + cursor: pointer; + transition: transform var(--anim-fast) var(--anim-ease), opacity var(--anim-fast) var(--anim-ease); + margin: 0; + padding: 0; + } + + .password-provider-flow .login-wallet-button:hover, + .password-provider-flow .create-wallet-button:hover { + opacity: 0.9; + transform: translateY(-1px); + } + + .password-provider-flow .login-wallet-button:active, + .password-provider-flow .create-wallet-button:active { + transform: translateY(1px); + } + + .password-provider-flow .login-wallet-button:disabled, + .password-provider-flow .create-wallet-button:disabled { + opacity: 0.7; + cursor: not-allowed; + background: linear-gradient(90deg, #ccc 0%, #ddd 100%); + } + + .password-provider-flow .error-message { + color: #e53935; + margin: 8px 0; + padding: 8px 12px; + background-color: rgba(229, 57, 53, 0.1); + border-radius: 8px; + font-size: 14px; + } + + .password-provider-flow .status-message { + color: #2196F3; + margin: 8px 0; + padding: 8px 12px; + background-color: rgba(33, 150, 243, 0.1); + border-radius: 8px; + font-size: 14px; + } + + .password-provider-flow .transaction-hash { + margin-top: 16px; + font-size: 13px; + text-align: center; + opacity: 0.7; + } + + .password-provider-flow .transaction-hash a { + color: var(--color-primary); + text-decoration: none; + } + + .password-provider-flow .transaction-hash a:hover { + text-decoration: underline; + } + + /* Animation for form fields */ + @keyframes formFieldAppear { + from { opacity: 0; transform: translateY(10px); } + to { opacity: 1; transform: translateY(0); } + } + + .password-provider-flow .form-group:nth-child(1) { animation: formFieldAppear 0.3s var(--anim-ease) 0.1s backwards; } + .password-provider-flow .form-group:nth-child(2) { animation: formFieldAppear 0.3s var(--anim-ease) 0.2s backwards; } + .password-provider-flow .form-group:nth-child(3) { animation: formFieldAppear 0.3s var(--anim-ease) 0.3s backwards; } + .password-provider-flow button { animation: formFieldAppear 0.3s var(--anim-ease) 0.4s backwards; } + +.password-provider-flow { + flex: 1; + display: flex; + flex-direction: column; + width: 100%; + min-height: 0; +} + +.password-provider-flow .wallet-login-container, +.password-provider-flow .wallet-creation-container { + flex: 1; + display: flex; + flex-direction: column; + gap: 16px; + padding: 16px 0; +} + +.provider-selection { + flex: 1; + display: flex; + flex-direction: column; + gap: 16px; +} + +.provider-list { + flex: 1; + min-height: 0; + overflow-y: auto; + padding-right: 4px; + margin-right: -4px; +} + +.provider-row.disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.coming-soon { + font-size: 12px; + color: #666; + padding: 2px 8px; + border-radius: 4px; + background-color: #f0f0f0; +} + +.transaction-hash { + color: #2196f3; + text-decoration: none; +} \ No newline at end of file diff --git a/hyle-wallet/src/components/HyleWallet.tsx b/hyle-wallet/src/components/HyleWallet.tsx new file mode 100644 index 0000000..2c59ad7 --- /dev/null +++ b/hyle-wallet/src/components/HyleWallet.tsx @@ -0,0 +1,196 @@ +import { useState } from 'react'; +import { Wallet } from '../types/wallet'; +import { authProviderManager } from '../providers/AuthProviderManager'; +import { AuthForm } from './auth/AuthForm'; +import './HyleWallet.css'; +import { useConfig } from '../hooks/useConfig'; + +export type ProviderOption = 'password' | 'google' | 'github' | 'x'; + +// SVG Icons for providers +const ProviderIcons = { + password: ( + + + + + + ), + google: ( + + + + + + + + ), + github: ( + + + + ), + x: ( + + + + ) +}; + +interface HyleWalletProps { + /** + * List of providers to display in the selector. "password" will always be shown if omitted. + */ + providers?: ProviderOption[]; + /** + * Optional render prop that gives full control over the connect button UI. + * If not supplied, a simple default button will be rendered. + */ + button?: (props: { onClick: () => void }) => React.ReactNode; + /** + * Callback invoked when the user successfully connects (creates or logs-in) a wallet. + */ + onWalletConnected?: (wallet: Wallet) => void; +} + +export const HyleWallet = ({ + providers = [], + button, + onWalletConnected, +}: HyleWalletProps) => { + const [isOpen, setIsOpen] = useState(false); + const [selectedProvider, setSelectedProvider] = useState(null); + const [showLogin, setShowLogin] = useState(true); // true = login (default), false = create/sign-up + const { isLoading: isLoadingConfig, error: configError } = useConfig(); + + const openModal = () => setIsOpen(true); + + const closeModal = () => { + setIsOpen(false); + setSelectedProvider(null); + setShowLogin(true); + }; + + const handleWalletConnected = (wallet: Wallet) => { + onWalletConnected?.(wallet); + closeModal(); + }; + + if (isLoadingConfig) { + return
Loading configuration...
; + } + + if (configError) { + return
Error loading configuration: {configError}
; + } + + + const renderProviderButton = (providerType: ProviderOption) => { + const provider = authProviderManager.getProvider(providerType); + const disabled = !provider?.isEnabled(); + + const config: Record = { + password: { label: 'Password', icon: ProviderIcons.password }, + google: { label: 'Google', icon: ProviderIcons.google }, + github: { label: 'GitHub', icon: ProviderIcons.github }, + x: { label: 'X', icon: ProviderIcons.x }, + }; + + const { label, icon } = config[providerType]; + + return ( + + ); + }; + + return ( + <> + {button ? ( + button({ onClick: openModal }) + ) : ( + + )} + + {isOpen && ( +
+
e.stopPropagation()}> +
+
+ + + + + + +
+ +
+ + {selectedProvider === null && ( +
+

Sign in

+
+ {providers.map(renderProviderButton)} +
+
+ )} + + {selectedProvider && ( +
+ {showLogin ? ( + <> +

Log in

+ + + + ) : ( + <> +

Create account

+ + + + )} +
+ )} +
+
+ )} + + ); +}; \ No newline at end of file diff --git a/hyle-wallet/src/components/auth/AuthForm.tsx b/hyle-wallet/src/components/auth/AuthForm.tsx new file mode 100644 index 0000000..563c1ca --- /dev/null +++ b/hyle-wallet/src/components/auth/AuthForm.tsx @@ -0,0 +1,117 @@ +import React, { useState } from 'react'; +import { Wallet } from '../../types/wallet'; +import { AuthCredentials, AuthProvider, AuthResult } from '../../providers/BaseAuthProvider'; + +interface AuthFormProps { + provider: AuthProvider; + mode: 'login' | 'register'; + onSuccess: (wallet: Wallet) => void; + onError?: (error: string) => void; +} + +export const AuthForm: React.FC = ({ + provider, + mode, + onSuccess, + onError +}) => { + const [credentials, setCredentials] = useState({ + username: 'bob', + password: 'password123', + confirmPassword: 'password123' + }); + const [error, setError] = useState(''); + const [isLoading, setIsLoading] = useState(false); + const [status, setStatus] = useState(''); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setError(''); + setIsLoading(true); + setStatus('Processing...'); + + try { + const result: AuthResult = await (mode === 'login' + ? provider.login(credentials) + : provider.register(credentials)); + + if (result.success && result.wallet) { + onSuccess(result.wallet); + } else { + setError(result.error || 'An unknown error occurred'); + onError?.(result.error || 'An unknown error occurred'); + } + } catch (err) { + const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred'; + setError(errorMessage); + onError?.(errorMessage); + } finally { + setIsLoading(false); + setStatus(''); + } + }; + + const handleInputChange = (e: React.ChangeEvent) => { + const { name, value } = e.target; + setCredentials(prev => ({ + ...prev, + [name]: value + })); + }; + + return ( +
+
+ + +
+ +
+ + +
+ + {mode === 'register' && ( +
+ + +
+ )} + + {error &&
{error}
} + {status &&
{status}
} + + +
+ ); +}; \ No newline at end of file diff --git a/hyle-wallet/src/hooks/useConfig.ts b/hyle-wallet/src/hooks/useConfig.ts new file mode 100644 index 0000000..1696dfc --- /dev/null +++ b/hyle-wallet/src/hooks/useConfig.ts @@ -0,0 +1,27 @@ +import { useEffect, useState } from "react"; +import { fetchConfig } from "../services/config"; +import { setWalletContractName } from "../types/wallet"; + +export function useConfig() { + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const loadConfig = async () => { + try { + const config = await fetchConfig(); + setWalletContractName(config.contract_name); + setIsLoading(false); + } catch (err) { + setError( + err instanceof Error ? err.message : "Failed to load configuration", + ); + setIsLoading(false); + } + }; + + loadConfig(); + }, []); + + return { isLoading, error }; +} diff --git a/hyle-wallet/src/index.ts b/hyle-wallet/src/index.ts new file mode 100644 index 0000000..b6d8c52 --- /dev/null +++ b/hyle-wallet/src/index.ts @@ -0,0 +1,25 @@ +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import { HyleWallet, ProviderOption } from './components/HyleWallet'; + +// Export the React component directly +export { HyleWallet } from './components/HyleWallet'; +export { PasswordAuthProvider } from './providers/PasswordAuthProvider'; +export type { AuthProvider, AuthCredentials } from './types/auth'; +export type { Wallet, Transaction } from './types/wallet'; +export type { ProviderOption }; + +// Register the Web Component +class HyleWalletElement extends HTMLElement { + connectedCallback() { + const mountPoint = document.createElement('div'); + this.appendChild(mountPoint); + + const providersAttr = this.getAttribute('providers'); + const providers = providersAttr ? providersAttr.split(',') as ProviderOption[] : ["password" as ProviderOption]; + + createRoot(mountPoint).render(React.createElement(HyleWallet, { providers })); + } +} + +customElements.define('hyle-wallet', HyleWalletElement); diff --git a/hyle-wallet/src/providers/AuthProviderManager.ts b/hyle-wallet/src/providers/AuthProviderManager.ts new file mode 100644 index 0000000..da21f15 --- /dev/null +++ b/hyle-wallet/src/providers/AuthProviderManager.ts @@ -0,0 +1,33 @@ +import { AuthProvider } from './BaseAuthProvider'; +import { PasswordAuthProvider } from './PasswordAuthProvider'; +import { GoogleAuthProvider } from './GoogleAuthProvider'; + +export class AuthProviderManager { + private providers: Map; + + constructor() { + this.providers = new Map(); + this.registerDefaultProviders(); + } + + private registerDefaultProviders() { + this.registerProvider(new PasswordAuthProvider()); + this.registerProvider(new GoogleAuthProvider()); + } + + registerProvider(provider: AuthProvider) { + this.providers.set(provider.type, provider); + } + + getProvider(type: string): AuthProvider | undefined { + return this.providers.get(type); + } + + getAvailableProviders(): string[] { + return Array.from(this.providers.keys()).filter(type => + this.providers.get(type)?.isEnabled() ?? false + ); + } +} + +export const authProviderManager = new AuthProviderManager(); \ No newline at end of file diff --git a/hyle-wallet/src/providers/BaseAuthProvider.ts b/hyle-wallet/src/providers/BaseAuthProvider.ts new file mode 100644 index 0000000..301b109 --- /dev/null +++ b/hyle-wallet/src/providers/BaseAuthProvider.ts @@ -0,0 +1,19 @@ +import { Wallet } from '../types/wallet'; + +export interface AuthCredentials { + username: string; + [key: string]: any; +} + +export interface AuthResult { + success: boolean; + wallet?: Wallet; + error?: string; +} + +export interface AuthProvider { + type: string; + login(credentials: AuthCredentials): Promise; + register(credentials: AuthCredentials): Promise; + isEnabled(): boolean; +} \ No newline at end of file diff --git a/hyle-wallet/src/providers/GoogleAuthProvider.ts b/hyle-wallet/src/providers/GoogleAuthProvider.ts new file mode 100644 index 0000000..8844fac --- /dev/null +++ b/hyle-wallet/src/providers/GoogleAuthProvider.ts @@ -0,0 +1,24 @@ +import { AuthProvider, AuthCredentials, AuthResult } from './BaseAuthProvider'; +// import { Wallet } from '../types/wallet'; + +export interface GoogleAuthCredentials extends AuthCredentials { + googleToken: string; +} + +export class GoogleAuthProvider implements AuthProvider { + type = 'google'; + + isEnabled(): boolean { + return false; + } + + async login(_credentials: GoogleAuthCredentials): Promise { + // À implémenter avec l'authentification Google + throw new Error('Google authentication not implemented yet'); + } + + async register(_credentials: GoogleAuthCredentials): Promise { + // À implémenter avec l'authentification Google + throw new Error('Google authentication not implemented yet'); + } +} \ No newline at end of file diff --git a/hyle-wallet/src/providers/PasswordAuthProvider.ts b/hyle-wallet/src/providers/PasswordAuthProvider.ts new file mode 100644 index 0000000..b850a49 --- /dev/null +++ b/hyle-wallet/src/providers/PasswordAuthProvider.ts @@ -0,0 +1,153 @@ +import { Buffer } from 'buffer'; +import { AuthProvider, AuthCredentials, AuthResult } from './BaseAuthProvider'; +import { Wallet, register, verifyIdentity, walletContractName } from '../types/wallet'; +import { nodeService } from '../services/NodeService'; +import { webSocketService } from '../services/WebSocketService'; +import { build_proof_transaction, build_blob as check_secret_blob, register_contract } from 'hyle-check-secret'; +import { BlobTransaction } from 'hyle'; + +export interface PasswordAuthCredentials extends AuthCredentials { + password: string; + confirmPassword?: string; +} + +export class PasswordAuthProvider implements AuthProvider { + type = 'password'; + + isEnabled(): boolean { + return true; + } + + async login(credentials: PasswordAuthCredentials): Promise { + try { + const { username, password } = credentials; + + if (!username || !password) { + return { success: false, error: 'Please fill in all fields' }; + } + + const identity = `${username}@${walletContractName}`; + const blob0 = await check_secret_blob(identity, password); + const blob1 = verifyIdentity(username, Date.now()); + + const blobTx: BlobTransaction = { + identity, + blobs: [blob0, blob1], + }; + + console.log('Blob transaction:', blobTx); + + const tx_hash = await nodeService.client.sendBlobTx(blobTx); + const proofTx = await build_proof_transaction( + identity, + password, + tx_hash, + 0, + blobTx.blobs.length, + ); + + await nodeService.client.sendProofTx(proofTx); + + await new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + webSocketService.unsubscribeFromWalletEvents(); + reject(new Error('Identity verification timed out')); + }, 30000); + + webSocketService.connect(identity); + const unsubscribeWalletEvents = webSocketService.subscribeToWalletEvents((event) => { + if (event.event === 'Identity verified') { + clearTimeout(timeout); + unsubscribeWalletEvents(); + webSocketService.disconnect(); + resolve(event); + } + }); + }); + + const wallet: Wallet = { + username, + address: identity + }; + + return { success: true, wallet }; + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : 'Invalid credentials or wallet does not exist' + }; + } + } + + async register(credentials: PasswordAuthCredentials): Promise { + try { + const { username, password, confirmPassword } = credentials; + + if (!username || !password || !confirmPassword) { + return { success: false, error: 'Please fill in all fields' }; + } + + if (password !== confirmPassword) { + return { success: false, error: 'Passwords do not match' }; + } + + if (password.length < 8) { + return { success: false, error: 'Password must be at least 8 characters long' }; + } + + const identity = `${username}@${walletContractName}`; + const blob0 = await check_secret_blob(identity, password); + const hash = Buffer.from(blob0.data).toString('hex'); + const blob1 = register(username, Date.now(), hash); + + const blobTx: BlobTransaction = { + identity, + blobs: [blob0, blob1], + }; + + console.log('Blob transaction:', blobTx); + + await register_contract(nodeService.client as any); + const tx_hash = await nodeService.client.sendBlobTx(blobTx); + + const proofTx = await build_proof_transaction( + identity, + password, + tx_hash, + 0, + blobTx.blobs.length, + ); + + await nodeService.client.sendProofTx(proofTx); + + await new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + webSocketService.unsubscribeFromWalletEvents(); + reject(new Error('Wallet creation timed out')); + }, 60000); + + webSocketService.connect(identity); + const unsubscribeWalletEvents = webSocketService.subscribeToWalletEvents((event) => { + if (event.event.startsWith('Successfully registered identity for account')) { + clearTimeout(timeout); + unsubscribeWalletEvents(); + webSocketService.disconnect(); + resolve(event); + } + }); + }); + + const wallet: Wallet = { + username, + address: identity + }; + + return { success: true, wallet }; + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : 'Failed to create wallet' + }; + } + } +} \ No newline at end of file diff --git a/hyle-wallet/src/services/IndexerService.ts b/hyle-wallet/src/services/IndexerService.ts new file mode 100644 index 0000000..89fab26 --- /dev/null +++ b/hyle-wallet/src/services/IndexerService.ts @@ -0,0 +1,80 @@ +import { IndexerApiHttpClient } from "hyle"; +import { Transaction, AuthMethod, walletContractName } from "../types/wallet"; + +interface BalanceResponse { + account: string; + balance: number; +} + +interface TransactionHistoryResponse { + account: string; + history: Transaction[]; +} + +interface SessionKey { + key: string; + expiration_date: number; + nonce: number; +} + +interface AccountInfo { + account: string; + auth_method: AuthMethod; + session_keys: SessionKey[]; + nonce: number; +} + +class IndexerService { + client: IndexerApiHttpClient; + server: IndexerApiHttpClient; + + constructor() { + this.client = new IndexerApiHttpClient( + import.meta.env.VITE_INDEXER_BASE_URL, + ); + this.server = new IndexerApiHttpClient( + import.meta.env.VITE_SERVER_BASE_URL, + ); + } + + async getBalance(address: string): Promise { + try { + const response = await this.client.get( + `v1/indexer/contract/hyllar/balance/${address}`, + "Fetching balance", + ); + return response.balance; + } catch (error) { + console.error("Error while fetching the balance:", error); + return 0; + } + } + + async getTransactionHistory(address: string): Promise { + try { + const response = await this.server.get( + `v1/indexer/contract/hyllar/history/${address}`, + "Fetching transaction history", + ); + return response.history; + } catch (error) { + console.error("Error while fetching the transaction history:", error); + return []; + } + } + + async getAccountInfo(address: string): Promise { + try { + const response = await this.server.get( + `v1/indexer/contract/${walletContractName}/account/${address}`, + "Fetching account info", + ); + return response; + } catch (error) { + console.error("Error while fetching the account info:", error); + throw new Error('Failed to fetch account info'); + } + } +} + +export const indexerService = new IndexerService(); diff --git a/hyle-wallet/src/services/NodeService.ts b/hyle-wallet/src/services/NodeService.ts new file mode 100644 index 0000000..08cc9da --- /dev/null +++ b/hyle-wallet/src/services/NodeService.ts @@ -0,0 +1,11 @@ +import { NodeApiHttpClient } from 'hyle'; + +class NodeService { + client: NodeApiHttpClient; + + constructor() { + this.client = new NodeApiHttpClient(import.meta.env.VITE_NODE_BASE_URL); + } +} + +export const nodeService = new NodeService(); diff --git a/hyle-wallet/src/services/SessionKeyService.ts b/hyle-wallet/src/services/SessionKeyService.ts new file mode 100644 index 0000000..a6b15b5 --- /dev/null +++ b/hyle-wallet/src/services/SessionKeyService.ts @@ -0,0 +1,92 @@ +import EC from 'elliptic'; +import { SHA256 } from 'crypto-js'; +import { Secp256k1Blob, serializeIdentityAction, serializeSecp256k1Blob, WalletAction, walletContractName } from '../types/wallet'; +import { Buffer } from 'buffer'; +import { Blob } from "hyle"; + +class SessionKeyService { + private ec: EC.ec; + + constructor() { + this.ec = new EC.ec('secp256k1'); + } + + + generateSessionKey(): string { + // Génère une paire de clés ECDSA + const keyPair = this.ec.genKeyPair(); + + const privateKey = keyPair.getPrivate('hex'); + if (!privateKey) { + throw new Error('Failed to generate private key'); + } + + const publicKey = keyPair.getPublic(true, 'hex'); + if (!publicKey) { + throw new Error('Failed to generate public key'); + } + + localStorage.setItem(publicKey, privateKey); + + return publicKey; + } + + getSignedBlob(identity: string, message: string, publicKey: string): Secp256k1Blob { + const privateKey = localStorage.getItem(publicKey); + if (!privateKey) { + throw new Error('No session key or provided private key available'); + } + const hash = SHA256(message); + const hashBytes = Buffer.from(hash.toString(), 'hex'); + + if (hashBytes.length !== 32) { + throw new Error('Hash length is not 32 bytes'); + } + + const keyPair = this.ec.keyFromPrivate(privateKey); + const signature = keyPair.sign(hash.toString()); + + // Normaliser s en utilisant min(s, n-s) + const n = this.ec.curve.n; + var s = signature.s; + if (s.gt(n.shrn(1))) { + signature.s = n.sub(s); + } + + const signatureBytes = new Uint8Array([...signature.r.toArray('be', 32), ...signature.s.toArray('be', 32)]); + + const secp256k1Blob: Secp256k1Blob = { + identity: identity, + data: hashBytes, + public_key: new Uint8Array(Buffer.from(publicKey, 'hex')), + signature: signatureBytes, + }; + console.log('secp256k1Blob', secp256k1Blob); + return secp256k1Blob; + } + + useSessionKey(account: string, key: string, message: string): [Blob, Blob] { + const action: WalletAction = { + UseSessionKey: { account, key, message } + }; + + const identity = `${account}@${walletContractName}`; + const secp256k1Blob: Secp256k1Blob = this.getSignedBlob(identity, message, key); + const blob0: Blob = { + contract_name: "secp256k1", + data: serializeSecp256k1Blob(secp256k1Blob), + }; + + const blob1: Blob = { + contract_name: walletContractName, + data: serializeIdentityAction(action), + }; + return [blob0, blob1]; + } + + clear(publicKey: string): void { + localStorage.removeItem(publicKey); + } +} + +export const sessionKeyService = new SessionKeyService(); diff --git a/hyle-wallet/src/services/WebSocketService.ts b/hyle-wallet/src/services/WebSocketService.ts new file mode 100644 index 0000000..1c3a0f7 --- /dev/null +++ b/hyle-wallet/src/services/WebSocketService.ts @@ -0,0 +1,128 @@ +import { Transaction } from "../types/wallet"; + +export interface AppEvent { + TxEvent: { + account: string; + tx: Transaction + }; + WalletEvent: { + account: string; + event: string; + }; +} + +interface RegisterTopicMessage { + RegisterTopic: string; +} + +type TxEventCallback = (event: AppEvent["TxEvent"]) => void; +type WalletEventCallback = (event: AppEvent["WalletEvent"]) => void; + +export class WebSocketService { + private ws: WebSocket | null = null; + private txEventCallbacks: TxEventCallback[] = []; + private walletEventCallbacks: WalletEventCallback[] = []; + private reconnectAttempts: number = 0; + private maxReconnectAttempts: number = 5; + private reconnectTimeout: number = 1000; + private currentAccount: string | null = null; + + constructor() {} + + connect(account: string) { + if (this.ws) { + console.log("WebSocket already connected"); + if (this.currentAccount != account) { + this.disconnect(); + } else { + return; + } + } + + this.currentAccount = account; + this.ws = new WebSocket(import.meta.env.VITE_WS_URL); + + this.ws.onopen = () => { + console.log("WebSocket connected"); + this.reconnectAttempts = 0; + // Send registration message + const registerMessage: RegisterTopicMessage = { + RegisterTopic: account, + }; + this.ws?.send(JSON.stringify(registerMessage)); + }; + + this.ws.onmessage = (event) => { + try { + const data: AppEvent = JSON.parse(event.data); + if (data.TxEvent) { + this.txEventCallbacks.forEach(callback => callback(data.TxEvent)); + } + if (data.WalletEvent) { + this.walletEventCallbacks.forEach(callback => callback(data.WalletEvent)); + } + } catch (error) { + console.error("Error parsing WebSocket message:", error); + } + }; + + this.ws.onclose = () => { + console.log("WebSocket disconnected"); + this.handleReconnect(); + }; + + this.ws.onerror = (error) => { + console.error("WebSocket error:", error); + }; + } + + private handleReconnect() { + if ( + this.reconnectAttempts < this.maxReconnectAttempts && + this.currentAccount + ) { + this.reconnectAttempts++; + setTimeout(() => { + console.log( + `Attempting to reconnect (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`, + ); + this.connect(this.currentAccount!); + }, this.reconnectTimeout * this.reconnectAttempts); + } + } + + subscribeToTxEvents(callback: TxEventCallback): () => void { + this.txEventCallbacks.push(callback); + return () => { + this.txEventCallbacks = this.txEventCallbacks.filter(cb => cb !== callback); + }; + } + + subscribeToWalletEvents(callback: WalletEventCallback): () => void { + this.walletEventCallbacks.push(callback); + return () => { + this.walletEventCallbacks = this.walletEventCallbacks.filter(cb => cb !== callback); + }; + } + + unsubscribeFromTxEvents() { + this.txEventCallbacks = []; + } + + unsubscribeFromWalletEvents() { + this.walletEventCallbacks = []; + } + + disconnect() { + if (this.ws) { + this.ws.close(); + this.ws = null; + this.currentAccount = null; + this.txEventCallbacks = []; + this.walletEventCallbacks = []; + } + } +} + +export const webSocketService = new WebSocketService(); + diff --git a/hyle-wallet/src/services/config.ts b/hyle-wallet/src/services/config.ts new file mode 100644 index 0000000..959d085 --- /dev/null +++ b/hyle-wallet/src/services/config.ts @@ -0,0 +1,13 @@ +interface Config { + contract_name: string; +} + +export async function fetchConfig(): Promise { + const response = await fetch( + `${import.meta.env.VITE_SERVER_BASE_URL}/api/config`, + ); + if (!response.ok) { + throw new Error("Failed to fetch config"); + } + return response.json(); +} diff --git a/hyle-wallet/src/types/auth.ts b/hyle-wallet/src/types/auth.ts new file mode 100644 index 0000000..ab4e14e --- /dev/null +++ b/hyle-wallet/src/types/auth.ts @@ -0,0 +1,13 @@ +import { Wallet } from './wallet'; + +export interface AuthCredentials { + type: string; + [key: string]: any; +} + +export interface AuthProvider { + type: string; + authenticate(): Promise; + verify(credentials: AuthCredentials): Promise; + disconnect(): void; +} \ No newline at end of file diff --git a/hyle-wallet/src/types/wallet.ts b/hyle-wallet/src/types/wallet.ts new file mode 100644 index 0000000..d2a4aba --- /dev/null +++ b/hyle-wallet/src/types/wallet.ts @@ -0,0 +1,190 @@ +import { Buffer } from 'buffer'; + +export interface Transaction { + id: string; + type: string; + amount: number; + address: string; + status: string; + timestamp: number; +} + +export interface Wallet { + username: string; + address: string; +} + +import { borshSerialize, BorshSchema, borshDeserialize } from "borsher"; +import { Blob } from "hyle"; + +export let walletContractName = "wallet"; // Default value that will be updated + +export const setWalletContractName = (name: string) => { + walletContractName = name; +}; + +// +// Types +// + +export type Secp256k1Blob = { + identity: String; + data: Uint8Array; + public_key: Uint8Array; + signature: Uint8Array; +}; + +export type AuthMethod = { + Password: { + hash: string; + }; +}; + +export type WalletAction = + | { + RegisterIdentity: { + account: string; + nonce: number; + auth_method: AuthMethod; + }; + } + | { + VerifyIdentity: { + nonce: number; + account: string; + }; + } + | { + AddSessionKey: { + account: string; + key: string; + expiration: number; + }; + } + | { + RemoveSessionKey: { + account: string; + key: string; + }; +} +| { + UseSessionKey: { + account: string; + key: string; + message: string; + }; + } + | { + UseSessionKey: { + account: string; + key: string; + message: string; + }; + }; + +// +// Builders +// + +export const register = (account: string, nonce: number, hash: string): Blob => { + const action: WalletAction = { + RegisterIdentity: { + account, + nonce, + auth_method: { Password: { hash } }, + }, + }; + const blob: Blob = { + contract_name: walletContractName, + data: serializeIdentityAction(action), + }; + return blob; +}; + +export const verifyIdentity = (account: string, nonce: number): Blob => { + const action: WalletAction = { + VerifyIdentity: { nonce, account }, + }; + + const blob: Blob = { + contract_name: walletContractName, + data: serializeIdentityAction(action), + }; + return blob; +}; + +export const addSessionKey = (account: string, key: string, expiration: number): Blob => { + const action: WalletAction = { + AddSessionKey: { account, key, expiration } + }; + const blob: Blob = { + contract_name: walletContractName, + data: serializeIdentityAction(action), + }; + return blob; +}; + +export const removeSessionKey = (account: string, key: string): Blob => { + const action: WalletAction = { + RemoveSessionKey: { account, key } + }; + const blob: Blob = { + contract_name: walletContractName, + data: serializeIdentityAction(action), + }; + return blob; +}; + +// Removed the `useSessionKey` function as it has been moved to `SessionKeyService`. + +// +// Serialisation +// + +export const serializeSecp256k1Blob = (blob: Secp256k1Blob): number[] => { + + return Array.from(borshSerialize(secp256k1BlobSchema, blob)); +}; + +export const serializeIdentityAction = (action: WalletAction): number[] => { + return Array.from(borshSerialize(schema, action)); +}; +export const deserializeIdentityAction = (data: number[]): WalletAction => { + return borshDeserialize(schema, Buffer.from(data)); +}; + +const secp256k1BlobSchema = BorshSchema.Struct({ + identity: BorshSchema.String, + data: BorshSchema.Array(BorshSchema.u8, 32), + public_key: BorshSchema.Array(BorshSchema.u8, 33), + signature: BorshSchema.Array(BorshSchema.u8, 64), +}); + +const schema = BorshSchema.Enum({ + RegisterIdentity: BorshSchema.Struct({ + account: BorshSchema.String, + nonce: BorshSchema.u128, + auth_method: BorshSchema.Enum({ + Password: BorshSchema.Struct({ + hash: BorshSchema.String, + }), + }), + }), + VerifyIdentity: BorshSchema.Struct({ + account: BorshSchema.String, + nonce: BorshSchema.u128, + }), + AddSessionKey: BorshSchema.Struct({ + account: BorshSchema.String, + key: BorshSchema.String, + expiration: BorshSchema.u128, + }), + RemoveSessionKey: BorshSchema.Struct({ + account: BorshSchema.String, + key: BorshSchema.String, + }), +UseSessionKey: BorshSchema.Struct({ + account: BorshSchema.String, + message: BorshSchema.String, + }), +}); diff --git a/hyle-wallet/src/vite-env.d.ts b/hyle-wallet/src/vite-env.d.ts new file mode 100644 index 0000000..3cbdabc --- /dev/null +++ b/hyle-wallet/src/vite-env.d.ts @@ -0,0 +1,14 @@ +/// + +interface ImportMetaEnv { + readonly VITE_SERVER_BASE_URL: string; + readonly VITE_WS_URL: string; + readonly VITE_NODE_BASE_URL: string; + readonly VITE_INDEXER_BASE_URL: string; + readonly VITE_TX_EXPLORER_URL: string; + readonly VITE_FAUCET_URL: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} \ No newline at end of file diff --git a/hyle-wallet/tsconfig.app.json b/hyle-wallet/tsconfig.app.json new file mode 100644 index 0000000..358ca9b --- /dev/null +++ b/hyle-wallet/tsconfig.app.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +} diff --git a/hyle-wallet/tsconfig.json b/hyle-wallet/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/hyle-wallet/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/hyle-wallet/tsconfig.node.json b/hyle-wallet/tsconfig.node.json new file mode 100644 index 0000000..db0becc --- /dev/null +++ b/hyle-wallet/tsconfig.node.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2022", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/hyle-wallet/vite.config.ts b/hyle-wallet/vite.config.ts new file mode 100644 index 0000000..445dae1 --- /dev/null +++ b/hyle-wallet/vite.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react()], + optimizeDeps: { + esbuildOptions: { target: "esnext" }, + exclude: ["@noir-lang/noirc_abi", "@noir-lang/acvm_js"], + }, +}); From 2e883cf37d402c276edabf6d63aba50ccc693f91 Mon Sep 17 00:00:00 2001 From: MatteoMer <30910760+MatteoMer@users.noreply.github.com> Date: Mon, 12 May 2025 16:58:16 +0200 Subject: [PATCH 02/17] using hooks + updating front --- front/src/App.tsx | 182 +- front/src/components/WalletShowcase.tsx | 20 + .../components/common/LoadingErrorState.tsx | 23 + .../src/components/connect/ConnectWallet.css | 399 -- .../src/components/connect/ConnectWallet.tsx | 194 - .../connect/ConnectWalletExamples.css | 289 - .../connect/ConnectWalletExamples.tsx | 199 - front/src/hooks/useWalletBalance.ts | 33 + front/src/hooks/useWalletTransactions.ts | 61 + front/src/hooks/useWebSocketConnection.ts | 36 + front/src/routes/routes.tsx | 41 + front/src/types/hyle-wallet-src.d.ts | 3 + front/src/types/hyle-wallet.d.ts | 39 + hyle-wallet/package-lock.json | 4697 ++++++++++++++++- hyle-wallet/package.json | 8 +- hyle-wallet/src/components/HyleWallet.tsx | 37 +- hyle-wallet/src/components/auth/AuthForm.css | 87 + hyle-wallet/src/components/auth/AuthForm.tsx | 22 +- hyle-wallet/src/hooks/useSessionKey.ts | 24 + hyle-wallet/src/hooks/useWallet.tsx | 91 + hyle-wallet/src/index.ts | 2 + 21 files changed, 5219 insertions(+), 1268 deletions(-) create mode 100644 front/src/components/WalletShowcase.tsx create mode 100644 front/src/components/common/LoadingErrorState.tsx delete mode 100644 front/src/components/connect/ConnectWallet.css delete mode 100644 front/src/components/connect/ConnectWallet.tsx delete mode 100644 front/src/components/connect/ConnectWalletExamples.css delete mode 100644 front/src/components/connect/ConnectWalletExamples.tsx create mode 100644 front/src/hooks/useWalletBalance.ts create mode 100644 front/src/hooks/useWalletTransactions.ts create mode 100644 front/src/hooks/useWebSocketConnection.ts create mode 100644 front/src/routes/routes.tsx create mode 100644 front/src/types/hyle-wallet-src.d.ts create mode 100644 front/src/types/hyle-wallet.d.ts create mode 100644 hyle-wallet/src/components/auth/AuthForm.css create mode 100644 hyle-wallet/src/hooks/useSessionKey.ts create mode 100644 hyle-wallet/src/hooks/useWallet.tsx diff --git a/front/src/App.tsx b/front/src/App.tsx index 83e7d3f..4edf894 100644 --- a/front/src/App.tsx +++ b/front/src/App.tsx @@ -1,141 +1,83 @@ -import { useState, useEffect } from 'react'; -import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; +import { useState } from 'react'; +import { BrowserRouter, Routes, Route, useNavigate, useRoutes } from 'react-router-dom'; import './App.css'; -import { Balance } from './components/wallet/Balance'; -import { Send } from './components/wallet/Send'; -import { History } from './components/wallet/History'; -import { SessionKeys } from './components/wallet/SessionKeys'; -import { WalletLayout } from './components/layout/WalletLayout'; -import { Wallet, Transaction } from './types/wallet'; -import { indexerService } from './services/IndexerService'; +import { LoadingErrorState } from './components/common/LoadingErrorState'; +import { WalletShowcase } from './components/WalletShowcase'; import { useConfig } from './hooks/useConfig'; -import { AppEvent, webSocketService } from './services/WebSocketService'; -import { ConnectWallet } from './components/connect/ConnectWallet'; -import { ConnectWalletExamples } from './components/connect/ConnectWalletExamples'; +import { useWalletBalance } from './hooks/useWalletBalance'; +import { useWalletTransactions } from './hooks/useWalletTransactions'; +import { useWebSocketConnection } from './hooks/useWebSocketConnection'; +import { getPublicRoutes, getProtectedRoutes, ROUTES } from './routes/routes'; +import { WalletProvider, useWallet } from '../../hyle-wallet/src'; -function App() { - const [wallet, setWallet] = useState(null); - const [balance, setBalance] = useState(0); - const [transactions, setTransactions] = useState([]); +function AppContent() { const { isLoading: isLoadingConfig, error: configError } = useConfig(); - - // Function to fetch balance - const fetchBalance = async () => { - if (wallet) { - const balance = await indexerService.getBalance(wallet.address); - setBalance(balance); - } - }; - - // Function to fetch transaction history - const fetchTransactions = async () => { - if (wallet) { - const transactions = await indexerService.getTransactionHistory(wallet.address); - setTransactions(transactions); - } - }; - - // Initialize WebSocket connection when wallet is set - useEffect(() => { - if (wallet) { - webSocketService.connect(wallet.address); - - const handleTxEvent = async (event: AppEvent['TxEvent']) => { - console.log('Received transaction event:', event); - if (event.tx.status === 'Success') { - // Update balance - await fetchBalance(); - } - - // Update transactions - const newTransaction: Transaction = event.tx; - - setTransactions(prevTransactions => { - const existingIndex = prevTransactions.findIndex(tx => tx.id === newTransaction.id); - if (existingIndex !== -1) { - console.log('Updating existing transaction'); - // Update existing transaction in-place - const updatedTransactions = [...prevTransactions]; - updatedTransactions[existingIndex] = newTransaction; - return updatedTransactions; - } else { - console.log('Adding new transaction'); - // Add new transaction at the beginning of the list - return [newTransaction, ...prevTransactions]; - } - }); - }; - - const unsubscribeTxEvents = webSocketService.subscribeToTxEvents(handleTxEvent); - - // Initial data fetch + const { wallet, logout } = useWallet(); + const navigate = useNavigate(); + + // Use custom hooks + const { balance, fetchBalance } = useWalletBalance(wallet?.address); + const { + transactions, + handleTxEvent + } = useWalletTransactions(wallet?.address); + + // Setup WebSocket connection + useWebSocketConnection(wallet?.address, event => { + handleTxEvent(event); + // If transaction was successful, update balance + if (event.tx.status === 'Success') { fetchBalance(); - fetchTransactions(); - - return () => { - unsubscribeTxEvents(); - webSocketService.disconnect(); - }; } - }, [wallet]); - - const handleWalletLoggedIn = (loggedInWallet: Wallet) => { - setWallet(loggedInWallet); - localStorage.setItem('wallet', JSON.stringify(loggedInWallet)); - }; + }); const handleLogout = () => { - setWallet(null); - localStorage.removeItem('wallet'); + logout(); + navigate(ROUTES.ROOT); }; - // Check if wallet exists in localStorage on component mount - useEffect(() => { - const storedWallet = localStorage.getItem('wallet'); - if (storedWallet) { - setWallet(JSON.parse(storedWallet)); - } - }, []); - if (isLoadingConfig) { - return
Loading configuration...
; + return ; } if (configError) { - return
Error loading configuration: {configError}
; + return ; } - return ( - - {/* Global connect wallet modal (renders its own button) */} - {!wallet && ( -
-
-

Wallet Integration

-

Connect to your wallet using a fully customizable modal component.

-
- -
- )} - - :
- } /> + // If wallet is not connected, show the showcase screen + if (!wallet) { + return ; + } - {wallet && ( - }> - } /> - } /> - } /> - } /> - } /> - - )} + // Generate routes based on authentication state + const publicRoutes = getPublicRoutes(); + const protectedRoutes = getProtectedRoutes(wallet, balance, transactions, handleLogout); + const allRoutes = [...publicRoutes, ...protectedRoutes]; + + return {allRoutes.map(route => + + {route.children?.map(childRoute => ( + + ))} + + )}; +} - } /> - +export default function App() { + return ( + + + + ); } - -export default App; diff --git a/front/src/components/WalletShowcase.tsx b/front/src/components/WalletShowcase.tsx new file mode 100644 index 0000000..5c80fcf --- /dev/null +++ b/front/src/components/WalletShowcase.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { HyleWallet } from '../../../hyle-wallet/src'; + +type ProviderOption = 'password' | 'google' | 'github'; + +interface WalletShowcaseProps { + providers: ProviderOption[]; +} + +export const WalletShowcase: React.FC = ({ providers }) => { + return ( +
+
+

Wallet Integration

+

Connect to your wallet using the default modal or your own custom UI.

+
+ +
+ ); +}; \ No newline at end of file diff --git a/front/src/components/common/LoadingErrorState.tsx b/front/src/components/common/LoadingErrorState.tsx new file mode 100644 index 0000000..2fec52f --- /dev/null +++ b/front/src/components/common/LoadingErrorState.tsx @@ -0,0 +1,23 @@ +import React from 'react'; + +interface LoadingErrorStateProps { + isLoading: boolean; + error: string | null; + loadingMessage?: string; +} + +export const LoadingErrorState: React.FC = ({ + isLoading, + error, + loadingMessage = 'Loading...' +}) => { + if (isLoading) { + return
{loadingMessage}
; + } + + if (error) { + return
Error: {error}
; + } + + return null; +}; \ No newline at end of file diff --git a/front/src/components/connect/ConnectWallet.css b/front/src/components/connect/ConnectWallet.css deleted file mode 100644 index 8afd855..0000000 --- a/front/src/components/connect/ConnectWallet.css +++ /dev/null @@ -1,399 +0,0 @@ -/* === Design tokens & motion === */ -:root { - --color-primary: #FF594B; - --color-secondary: #FF9660; - --color-primary-emphasis: rgba(255, 89, 75, 0.2); - --radius-l: 24px; - --shadow-xl: 0 12px 32px rgba(0, 0, 0, 0.12); - --overlay-bg: rgba(0, 0, 0, 0.5); - --modal-bg: rgba(255, 255, 255, 0.75); - --anim-ease: cubic-bezier(.16,1,.3,1); - --anim-fast: 120ms; - --anim-normal: 220ms; -} - -@keyframes fadeIn { - from { opacity: 0; } - to { opacity: 1; } -} - -@keyframes slideUp { - from { transform: translateY(24px) scale(0.98); opacity: 0; } - to { transform: translateY(0) scale(1); opacity: 1; } -} - -.connect-wallet-btn { - padding: 12px 24px; - background: linear-gradient(90deg, var(--color-primary) 0%, var(--color-secondary) 100%); - color: #fff; - border: none; - border-radius: var(--radius-l); - cursor: pointer; - font-size: 16px; - font-weight: 600; - box-shadow: var(--shadow-xl); - transition: transform var(--anim-fast) var(--anim-ease), opacity var(--anim-fast) var(--anim-ease); -} - -.connect-wallet-btn:hover { - opacity: 0.9; - transform: scale(0.98); -} - -/* Overlay */ -.connect-wallet-overlay { - position: fixed; - top: 0; - left: 0; - width: 100vw; - height: 100vh; - background: var(--overlay-bg); - backdrop-filter: blur(8px) saturate(120%); - display: flex; - align-items: center; - justify-content: center; - z-index: 1000; - animation: fadeIn var(--anim-normal) var(--anim-ease); -} - -/* Modal */ -.connect-wallet-modal { - background: var(--modal-bg); - backdrop-filter: blur(16px) saturate(180%); - border: 1px solid rgba(255, 255, 255, 0.3); - border-radius: var(--radius-l); - box-shadow: var(--shadow-xl); - width: 90%; - max-width: 420px; - max-height: 90vh; - overflow-y: auto; - padding: 0 24px 28px; /* top padding removed: header owns it */ - position: relative; - animation: slideUp 0.3s var(--anim-ease); -} - -/* Modal header with brand gradient */ -.modal-header { - height: 56px; - background: linear-gradient(90deg, var(--color-primary) 0%, var(--color-secondary) 100%); - border-top-left-radius: var(--radius-l); - border-top-right-radius: var(--radius-l); - display: flex; - align-items: center; - justify-content: center; - position: relative; - margin: 0 -24px 24px; /* stretch full width, then push content */ -} - -.modal-logo { - margin: 0; - display: flex; - justify-content: center; -} - -.connect-modal-close { - position: absolute; - right: 12px; - top: 50%; - transform: translateY(-50%); - background: transparent; - border: none; - color: #fff; - font-size: 24px; - cursor: pointer; - transition: transform var(--anim-fast) var(--anim-ease); -} - -.connect-modal-close:hover { - transform: translateY(-50%) rotate(45deg); -} - -.provider-selection h2 { - margin-top: 0; - text-align: center; - font-size: 24px; - color: #333; -} - -.password-provider-flow .auth-title { - margin: 0 0 20px 0; - text-align: center; - font-size: 24px; - color: #333; -} - -.provider-selection .subtitle { - text-align: center; - color: #666; - margin: 8px 0 24px; - font-size: 14px; -} - -.provider-grid { - display: flex; - flex-wrap: wrap; - gap: 12px; - justify-content: center; - margin-top: 16px; -} - -.connect-provider-btn { - flex: 1 1 40%; - padding: 12px 8px; - border: 1px solid #ccc; - border-radius: 4px; - background: #f9f9f9; - cursor: pointer; - font-size: 14px; -} - -.connect-provider-btn:disabled { - opacity: 0.6; - cursor: not-allowed; -} - -.coming-soon { - font-size: 12px; - color: #999; -} - -.password-provider-flow .switch-auth-button, -.provider-coming-soon .back-to-providers { - margin-top: 16px; - width: 100%; - padding: 8px; - border: none; - background: #eee; - cursor: pointer; - border-radius: 4px; -} - -/* Sleek link-style button for toggling between login and sign-up */ -.password-provider-flow .switch-auth-button { - /* link style button */ - background: none; - color: var(--color-primary); - font-size: 14px; - width: auto; - padding: 0; -} - -.password-provider-flow .switch-auth-button:hover { - opacity: 0.8; - text-decoration: none; -} - -/* Provider vertical list */ -.provider-list { - display: flex; - flex-direction: column; - gap: 12px; - margin-top: 16px; -} - -.provider-row { - width: 100%; - padding: 12px 16px; - border: 1px solid #e5e5e5; - border-radius: 8px; - background: #fff; - display: flex; - align-items: center; - justify-content: space-between; - font-size: 16px; - cursor: pointer; - transition: background 0.15s ease; -} - -.provider-row:hover:not(.disabled) { - background: #f2f2f2; -} - -.provider-row.disabled { - opacity: 0.6; - cursor: default; -} - -.provider-icon { - display: flex; - align-items: center; - justify-content: center; - width: 24px; - height: 24px; - border-radius: 50%; - background-color: #f5f5f5; - color: #333; -} - -.provider-row .provider-icon svg { - display: block; -} - -/* Email field styling */ -.provider-row:first-child { - position: relative; - background-color: white; - border-radius: 8px; - overflow: hidden; -} - -.label { - display: flex; - align-items: center; - gap: 12px; -} - -.row-arrow { - font-size: 20px; -} - -.password-provider-flow .wallet-login-container h1, -.password-provider-flow .wallet-creation-container h1 { - display: none; -} - -.password-provider-flow .wallet-creation-form p { - display: none; -} - -/* === Auth Components Styling === */ -.password-provider-flow .wallet-login-container, -.password-provider-flow .wallet-creation-container { - /* Already hides h1 */ -} - -.password-provider-flow .form-group { - margin-bottom: 10px; -} - -.password-provider-flow .form-group label { - display: block; - margin-bottom: 4px; - font-size: 14px; - font-weight: 500; - color: #333; -} - -.password-provider-flow input { - width: 100%; - height: 42px; - padding: 0 12px; - background: rgba(255, 255, 255, 0.8); - border: 1px solid rgba(0, 0, 0, 0.1); - border-radius: 12px; - font-size: 15px; - transition: border-color var(--anim-fast) ease; - position: relative; -} - -.password-provider-flow .form-group { - position: relative; -} - -/* -.password-provider-flow .form-group::before { - content: ""; - position: absolute; - left: 12px; - top: 34px; - width: 16px; - height: 16px; - background-repeat: no-repeat; - background-position: center; - opacity: 0.5; -} - -.password-provider-flow .form-group:nth-of-type(1)::before { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2'%3E%3C/path%3E%3Ccircle cx='12' cy='7' r='4'%3E%3C/circle%3E%3C/svg%3E"); -} - -.password-provider-flow .form-group:nth-of-type(2)::before, -.password-provider-flow .form-group:nth-of-type(3)::before { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2' ry='2'%3E%3C/rect%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'%3E%3C/path%3E%3C/svg%3E"); -} -*/ - -.password-provider-flow input:focus { - outline: none; - border-color: var(--color-primary); - box-shadow: 0 0 0 3px var(--color-primary-emphasis); -} - -.password-provider-flow .login-wallet-button, -.password-provider-flow .create-wallet-button { - width: 100%; - height: 48px; - background: linear-gradient(90deg, var(--color-primary) 0%, var(--color-secondary) 100%); - color: #fff; - border: none; - border-radius: 24px; - font-size: 16px; - font-weight: 600; - cursor: pointer; - transition: transform var(--anim-fast) var(--anim-ease), opacity var(--anim-fast) var(--anim-ease); - margin: 0; - padding: 0; -} - -.password-provider-flow .login-wallet-button:hover, -.password-provider-flow .create-wallet-button:hover { - opacity: 0.9; - transform: translateY(-1px); -} - -.password-provider-flow .login-wallet-button:active, -.password-provider-flow .create-wallet-button:active { - transform: translateY(1px); -} - -.password-provider-flow .login-wallet-button:disabled, -.password-provider-flow .create-wallet-button:disabled { - opacity: 0.7; - cursor: not-allowed; - background: linear-gradient(90deg, #ccc 0%, #ddd 100%); -} - -.password-provider-flow .error-message { - color: #e53935; - margin: 8px 0; - padding: 8px 12px; - background-color: rgba(229, 57, 53, 0.1); - border-radius: 8px; - font-size: 14px; -} - -.password-provider-flow .status-message { - color: #2196F3; - margin: 8px 0; - padding: 8px 12px; - background-color: rgba(33, 150, 243, 0.1); - border-radius: 8px; - font-size: 14px; -} - -.password-provider-flow .transaction-hash { - margin-top: 16px; - font-size: 13px; - text-align: center; - opacity: 0.7; -} - -.password-provider-flow .transaction-hash a { - color: var(--color-primary); - text-decoration: none; -} - -.password-provider-flow .transaction-hash a:hover { - text-decoration: underline; -} - -/* Animation for form fields */ -@keyframes formFieldAppear { - from { opacity: 0; transform: translateY(10px); } - to { opacity: 1; transform: translateY(0); } -} - -.password-provider-flow .form-group:nth-child(1) { animation: formFieldAppear 0.3s var(--anim-ease) 0.1s backwards; } -.password-provider-flow .form-group:nth-child(2) { animation: formFieldAppear 0.3s var(--anim-ease) 0.2s backwards; } -.password-provider-flow .form-group:nth-child(3) { animation: formFieldAppear 0.3s var(--anim-ease) 0.3s backwards; } -.password-provider-flow button { animation: formFieldAppear 0.3s var(--anim-ease) 0.4s backwards; } \ No newline at end of file diff --git a/front/src/components/connect/ConnectWallet.tsx b/front/src/components/connect/ConnectWallet.tsx deleted file mode 100644 index ff85b05..0000000 --- a/front/src/components/connect/ConnectWallet.tsx +++ /dev/null @@ -1,194 +0,0 @@ -import { useState } from 'react'; -import { Wallet } from '../../types/wallet'; -import { LoginWallet } from '../auth/LoginWallet'; -import { CreateWallet } from '../auth/CreateWallet'; -import './ConnectWallet.css'; - -export type ProviderOption = 'password' | 'google' | 'github' | 'x'; - -// SVG Icons for providers -const ProviderIcons = { - password: ( - - - - - - ), - google: ( - - - - - - - - ), - github: ( - - - - ), - x: ( - - - - ) -}; - -interface ConnectWalletProps { - /** - * List of providers to display in the selector. "password" will always be shown if omitted. - */ - providers?: ProviderOption[]; - /** - * Optional render prop that gives full control over the connect button UI. - * If not supplied, a simple default button will be rendered. - */ - button?: (props: { onClick: () => void }) => React.ReactNode; - /** - * Callback invoked when the user successfully connects (creates or logs-in) a wallet. - */ - onWalletConnected?: (wallet: Wallet) => void; -} - -export const ConnectWallet = ({ - providers = ['password'], - button, - onWalletConnected, -}: ConnectWalletProps) => { - const [isOpen, setIsOpen] = useState(false); - const [selectedProvider, setSelectedProvider] = useState(null); - const [showLogin, setShowLogin] = useState(true); // true = login (default), false = create/sign-up - - const openModal = () => setIsOpen(true); - - const closeModal = () => { - setIsOpen(false); - setSelectedProvider(null); - setShowLogin(true); - }; - - const handleWalletConnected = (wallet: Wallet) => { - onWalletConnected?.(wallet); - closeModal(); - }; - - // Compose the list of providers, ensuring password is included if requested implicitly - const providerList: ProviderOption[] = Array.from( - new Set(['password', ...providers]) - ); - - const renderProviderButton = (provider: ProviderOption) => { - const disabled = provider !== 'password'; - - const config: Record = { - password: { label: 'Password', icon: ProviderIcons.password }, - google: { label: 'Google', icon: ProviderIcons.google }, - github: { label: 'GitHub', icon: ProviderIcons.github }, - x: { label: 'X', icon: ProviderIcons.x }, - }; - - const { label, icon } = config[provider]; - - return ( - - ); - }; - - return ( - <> - {button ? ( - button({ onClick: openModal }) - ) : ( - - )} - - {isOpen && ( -
-
e.stopPropagation()}> -
-
- - - - - - -
- -
- - {/* Provider selection */} - {selectedProvider === null && ( -
-

Sign in

-
- {providerList.map(renderProviderButton)} -
-
- )} - - {/* Password provider flow */} - {selectedProvider === 'password' && ( -
- {showLogin ? ( - <> -

Log in

- - - - ) : ( - <> -

Create account

- - - - )} -
- )} - - {/* Stub for other providers */} - {selectedProvider && selectedProvider !== 'password' && ( -
-

{selectedProvider} provider coming soon!

- -
- )} -
-
- )} - - ); -}; \ No newline at end of file diff --git a/front/src/components/connect/ConnectWalletExamples.css b/front/src/components/connect/ConnectWalletExamples.css deleted file mode 100644 index 9f735b2..0000000 --- a/front/src/components/connect/ConnectWalletExamples.css +++ /dev/null @@ -1,289 +0,0 @@ -.connect-examples-container { - max-width: 1200px; - margin: 0 auto; - padding: 2rem; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', sans-serif; -} - -.connect-examples-container h2 { - font-size: 2rem; - margin-bottom: 0.5rem; - color: #333; -} - -.connect-examples-container h3 { - font-size: 1.5rem; - margin: 2rem 0 1rem; - color: #444; -} - -.connect-examples-container p { - font-size: 1rem; - line-height: 1.5; - color: #666; - margin-bottom: 1.5rem; -} - -.connect-examples-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); - gap: 1.5rem; -} - -.connect-example-card { - border: 1px solid #eaeaea; - border-radius: 8px; - padding: 1.5rem; - background: white; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); -} - -.connect-example-card h4 { - margin-top: 0; - margin-bottom: 1rem; - color: #333; -} - -.connect-example-preview { - display: flex; - justify-content: center; - margin-top: 1rem; - padding: 1rem; - background: #f9f9f9; - border-radius: 6px; -} - -.connect-example-code { - background: #f4f4f4; - padding: 0.75rem; - border-radius: 4px; - font-family: monospace; - font-size: 0.875rem; - overflow-x: auto; -} - -/* Button Variants */ -.connect-example-primary { - background: #4a90e2; - color: white; - border: none; - padding: 10px 16px; - font-size: 14px; - border-radius: 4px; - cursor: pointer; -} - -.connect-example-outline { - background: transparent; - color: #4a90e2; - border: 1px solid #4a90e2; - padding: 10px 16px; - font-size: 14px; - border-radius: 4px; - cursor: pointer; -} - -.connect-example-rounded { - background: #5a67d8; - color: white; - border: none; - padding: 10px 20px; - font-size: 14px; - border-radius: 30px; - cursor: pointer; -} - -.connect-example-with-icon { - display: flex; - align-items: center; - gap: 8px; - background: #38a169; - color: white; - border: none; - padding: 10px 16px; - font-size: 14px; - border-radius: 4px; - cursor: pointer; -} - -.connect-example-text { - background: transparent; - color: #4a5568; - border: none; - padding: 10px 0; - font-size: 14px; - text-decoration: underline; - cursor: pointer; -} - -.connect-example-dark { - background: #2d3748; - color: white; - border: none; - padding: 10px 16px; - font-size: 14px; - border-radius: 4px; - cursor: pointer; -} - -/* Navbar example */ -.connect-example-navbar { - display: flex; - justify-content: space-between; - align-items: center; - padding: 1rem; - background: #f8f9fa; - border-radius: 8px; - margin-top: 1rem; -} - -.connect-example-logo { - font-weight: bold; - font-size: 1.25rem; - color: #333; -} - -.connect-example-nav-items { - display: flex; - align-items: center; - gap: 1.5rem; -} - -.connect-example-nav-link { - color: #4a5568; - text-decoration: none; - font-size: 0.9rem; -} - -.connect-example-nav-button { - background: #4a90e2; - color: white; - border: none; - padding: 8px 16px; - font-size: 0.9rem; - border-radius: 4px; - cursor: pointer; -} - -/* Add these new button styles */ - -.connect-example-gradient { - background: linear-gradient(90deg, #4a90e2 0%, #5a67d8 100%); - color: white; - border: none; - padding: 10px 20px; - font-size: 14px; - border-radius: 6px; - cursor: pointer; - box-shadow: 0 2px 10px rgba(74, 144, 226, 0.3); -} - -.connect-example-minimal-pill { - background: transparent; - color: #444; - border: none; - padding: 8px 16px; - font-size: 14px; - border-radius: 30px; - cursor: pointer; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - transition: all 0.2s ease; -} - -.connect-example-minimal-pill:hover { - background: #f0f0f0; - transform: translateY(-1px); -} - -.connect-example-branded { - display: flex; - align-items: center; - gap: 8px; - background: #2c3e50; - color: white; - border: none; - padding: 10px 18px; - font-size: 14px; - border-radius: 6px; - cursor: pointer; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); -} - -.branded-icon { - font-size: 16px; -} - -/* Mobile mockup */ -.connect-example-mobile { - width: 280px; - height: 500px; - border: 10px solid #222; - border-radius: 36px; - overflow: hidden; - margin: 1rem auto; - position: relative; - background-color: white; - box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); -} - -.mobile-statusbar { - background: #222; - color: white; - display: flex; - justify-content: space-between; - padding: 4px 12px; - font-size: 12px; -} - -.mobile-icons { - display: flex; - gap: 4px; -} - -.mobile-content { - padding: 12px; - height: calc(100% - 20px); - display: flex; - flex-direction: column; -} - -.mobile-app-header { - display: flex; - justify-content: space-between; - align-items: center; - padding-bottom: 12px; - border-bottom: 1px solid #eee; - margin-bottom: 16px; -} - -.mobile-app-title { - font-weight: bold; - font-size: 16px; -} - -.mobile-connect-button { - background: #4a90e2; - color: white; - border: none; - padding: 6px 12px; - font-size: 12px; - border-radius: 4px; - cursor: pointer; -} - -.mobile-app-body { - flex: 1; - display: flex; - flex-direction: column; - gap: 12px; -} - -.mobile-placeholder { - height: 80px; - background: #f5f5f5; - border-radius: 8px; -} - -.mobile-placeholder.short { - height: 40px; -} \ No newline at end of file diff --git a/front/src/components/connect/ConnectWalletExamples.tsx b/front/src/components/connect/ConnectWalletExamples.tsx deleted file mode 100644 index 33d7b6c..0000000 --- a/front/src/components/connect/ConnectWalletExamples.tsx +++ /dev/null @@ -1,199 +0,0 @@ -import React from 'react'; -import { ConnectWallet, ProviderOption } from './ConnectWallet'; -import { Wallet } from '../../types/wallet'; -import './ConnectWalletExamples.css'; - -interface ConnectWalletExamplesProps { - onWalletConnected?: (wallet: Wallet) => void; -} - -export const ConnectWalletExamples: React.FC = ({ - onWalletConnected -}) => { - // Different provider combinations - const providerSets: { title: string; providers: ProviderOption[] }[] = [ - { title: 'All Providers', providers: ['password', 'google', 'github', 'x'] }, - { title: 'Social Only', providers: ['google', 'github', 'x'] }, - { title: 'Password Only', providers: ['password'] }, - { title: 'Google & GitHub', providers: ['google', 'github'] } - ]; - - // Example button render functions - const buttonVariants = [ - { - title: 'Primary Button', - render: ({ onClick }: { onClick: () => void }) => ( - - ) - }, - { - title: 'Outline Button', - render: ({ onClick }: { onClick: () => void }) => ( - - ) - }, - { - title: 'Rounded Button', - render: ({ onClick }: { onClick: () => void }) => ( - - ) - }, - { - title: 'With Icon', - render: ({ onClick }: { onClick: () => void }) => ( - - ) - }, - { - title: 'Text Only', - render: ({ onClick }: { onClick: () => void }) => ( - - ) - }, - { - title: 'Dark Mode', - render: ({ onClick }: { onClick: () => void }) => ( - - ) - }, - { - title: 'Gradient Button', - render: ({ onClick }: { onClick: () => void }) => ( - - ) - }, - { - title: 'Minimal Pill', - render: ({ onClick }: { onClick: () => void }) => ( - - ) - }, - { - title: 'Branded Button', - render: ({ onClick }: { onClick: () => void }) => ( - - ) - } - ]; - - return ( -
-

Connect Account Examples

-

The ConnectWallet component supports customizable buttons and provider lists.

- -

Button Style Variations

-
- {buttonVariants.map((variant, index) => ( -
-

{variant.title}

-
- -
-
- ))} -
- -

Provider Combinations

-
- {providerSets.map((set, index) => ( -
-

{set.title}

-
-              {`providers={${JSON.stringify(set.providers)}}`}
-            
-
- ( - - )} - onWalletConnected={onWalletConnected} - /> -
-
- ))} -
- -

Custom Integration Example

-
-
MyApp
-
- Home - Features - About - ( - - )} - onWalletConnected={onWalletConnected} - /> -
-
- -

Mobile Integration Example

-
-
- 9:41 -
- 📶 - 📡 - 🔋 -
-
-
-
-
Mobile App
- ( - - )} - onWalletConnected={onWalletConnected} - /> -
-
-
-
-
-
-
-
-
-
- ); -}; \ No newline at end of file diff --git a/front/src/hooks/useWalletBalance.ts b/front/src/hooks/useWalletBalance.ts new file mode 100644 index 0000000..36b2794 --- /dev/null +++ b/front/src/hooks/useWalletBalance.ts @@ -0,0 +1,33 @@ +import { useState, useEffect } from 'react'; +import { indexerService } from '../services/IndexerService'; + +export function useWalletBalance(address: string | undefined) { + const [balance, setBalance] = useState(0); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + + const fetchBalance = async () => { + if (!address) return; + + setIsLoading(true); + setError(null); + + try { + const balance = await indexerService.getBalance(address); + setBalance(balance); + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to fetch balance'); + console.error('Error fetching balance:', err); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + if (address) { + fetchBalance(); + } + }, [address]); + + return { balance, isLoading, error, fetchBalance }; +} \ No newline at end of file diff --git a/front/src/hooks/useWalletTransactions.ts b/front/src/hooks/useWalletTransactions.ts new file mode 100644 index 0000000..546b41c --- /dev/null +++ b/front/src/hooks/useWalletTransactions.ts @@ -0,0 +1,61 @@ +import { useState, useEffect, useCallback } from 'react'; +import { Transaction } from '../types/wallet'; +import { indexerService } from '../services/IndexerService'; +import { AppEvent } from '../services/WebSocketService'; + +export function useWalletTransactions(address: string | undefined) { + const [transactions, setTransactions] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + + const fetchTransactions = useCallback(async () => { + if (!address) return; + + setIsLoading(true); + setError(null); + + try { + const txHistory = await indexerService.getTransactionHistory(address); + setTransactions(txHistory); + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to fetch transaction history'); + console.error('Error fetching transactions:', err); + } finally { + setIsLoading(false); + } + }, [address]); + + const handleTxEvent = useCallback((event: AppEvent['TxEvent']) => { + console.log('Received transaction event:', event); + const newTransaction: Transaction = event.tx; + + setTransactions(prevTransactions => { + const existingIndex = prevTransactions.findIndex(tx => tx.id === newTransaction.id); + if (existingIndex !== -1) { + console.log('Updating existing transaction'); + // Update existing transaction in-place + const updatedTransactions = [...prevTransactions]; + updatedTransactions[existingIndex] = newTransaction; + return updatedTransactions; + } else { + console.log('Adding new transaction'); + // Add new transaction at the beginning of the list + return [newTransaction, ...prevTransactions]; + } + }); + }, []); + + useEffect(() => { + if (address) { + fetchTransactions(); + } + }, [address, fetchTransactions]); + + return { + transactions, + isLoading, + error, + fetchTransactions, + handleTxEvent + }; +} \ No newline at end of file diff --git a/front/src/hooks/useWebSocketConnection.ts b/front/src/hooks/useWebSocketConnection.ts new file mode 100644 index 0000000..fd46686 --- /dev/null +++ b/front/src/hooks/useWebSocketConnection.ts @@ -0,0 +1,36 @@ +import { useEffect, useCallback } from 'react'; +import { AppEvent, webSocketService } from '../services/WebSocketService'; + +type EventHandler = (event: AppEvent['TxEvent']) => void; + +export function useWebSocketConnection( + address: string | undefined, + onTxEvent: EventHandler +) { + const connect = useCallback(() => { + if (!address) return; + webSocketService.connect(address); + }, [address]); + + const disconnect = useCallback(() => { + webSocketService.disconnect(); + }, []); + + useEffect(() => { + if (!address) return; + + // Connect to WebSocket + connect(); + + // Subscribe to transaction events + const unsubscribeTxEvents = webSocketService.subscribeToTxEvents(onTxEvent); + + // Cleanup on unmount + return () => { + unsubscribeTxEvents(); + disconnect(); + }; + }, [address, connect, disconnect, onTxEvent]); + + return { connect, disconnect }; +} \ No newline at end of file diff --git a/front/src/routes/routes.tsx b/front/src/routes/routes.tsx new file mode 100644 index 0000000..b5e5b62 --- /dev/null +++ b/front/src/routes/routes.tsx @@ -0,0 +1,41 @@ +import { Navigate, RouteObject } from 'react-router-dom'; +import { Balance } from '../components/wallet/Balance'; +import { Send } from '../components/wallet/Send'; +import { History } from '../components/wallet/History'; +import { SessionKeys } from '../components/wallet/SessionKeys'; +import { WalletLayout } from '../components/layout/WalletLayout'; +import { Wallet } from '../types/wallet'; + +// Route path constants +export const ROUTES = { + ROOT: '/', + WALLET: '/wallet', + BALANCE: '/wallet/balance', + SEND: '/wallet/send', + HISTORY: '/wallet/history', + SESSION_KEYS: '/wallet/session-keys', +}; + +export const getPublicRoutes = (): RouteObject[] => [ + { path: ROUTES.ROOT, element: }, + { path: '*', element: }, +]; + +export const getProtectedRoutes = ( + wallet: Wallet | null, + balance: number, + transactions: any[], + onLogout: () => void +): RouteObject[] => [ + { + path: ROUTES.WALLET, + element: , + children: [ + { path: 'balance', element: }, + { path: 'send', element: }, + { path: 'history', element: }, + { path: 'session-keys', element: }, + { index: true, element: }, + ], + }, +]; \ No newline at end of file diff --git a/front/src/types/hyle-wallet-src.d.ts b/front/src/types/hyle-wallet-src.d.ts new file mode 100644 index 0000000..dcc19f2 --- /dev/null +++ b/front/src/types/hyle-wallet-src.d.ts @@ -0,0 +1,3 @@ +declare module '../../hyle-wallet/src' { + export * from '../../../hyle-wallet/src'; +} \ No newline at end of file diff --git a/front/src/types/hyle-wallet.d.ts b/front/src/types/hyle-wallet.d.ts new file mode 100644 index 0000000..e0d1bc2 --- /dev/null +++ b/front/src/types/hyle-wallet.d.ts @@ -0,0 +1,39 @@ +declare module 'hyle-wallet' { + import * as React from 'react'; + import type { Wallet } from './wallet'; + + export type ProviderOption = 'password' | 'google' | 'github' | 'x'; + + export interface HyleWalletProps { + providers?: ProviderOption[]; + button?: (props: { onClick: () => void }) => React.ReactNode; + onWalletConnected?: (wallet: Wallet) => void; + } + + export const HyleWallet: React.FC; + + export interface WalletProviderProps { + children: React.ReactNode; + } + + export const WalletProvider: React.FC; + + export interface UseWalletReturn { + wallet: Wallet | null; + isLoading: boolean; + error: string | null; + login: (provider: ProviderOption, credentials: any) => Promise; + register: (provider: ProviderOption, credentials: any) => Promise; + logout: () => void; + } + + export function useWallet(): UseWalletReturn; + + export interface UseSessionKeyReturn { + generateSessionKey: () => string; + clearSessionKey: (publicKey: string) => void; + createSignedBlobs: (account: string, key: string, message: string) => [any, any]; + } + + export function useSessionKey(): UseSessionKeyReturn; +} \ No newline at end of file diff --git a/hyle-wallet/package-lock.json b/hyle-wallet/package-lock.json index feca975..302f317 100644 --- a/hyle-wallet/package-lock.json +++ b/hyle-wallet/package-lock.json @@ -7,44 +7,3907 @@ "": { "name": "hyle-wallet", "version": "1.0.0", - "license": "ISC", "dependencies": { - "@types/node": "^22.15.17", - "@types/react": "^19.1.3", - "@types/react-dom": "^19.1.3", + "@types/crypto-js": "^4.2.2", + "@types/elliptic": "^6.4.18", + "@types/react-router-dom": "^5.3.3", + "crypto-js": "^4.2.0", + "elliptic": "^6.6.1", + "hyle": "^0.2.5", + "hyle-check-secret": "^0.3.2", "react": "^19.1.0", "react-dom": "^19.1.0", - "typescript": "^5.8.3" + "react-router-dom": "^7.5.0" + }, + "devDependencies": { + "@eslint/js": "^9.24.0", + "@types/react": "^19.1.3", + "@types/react-dom": "^19.1.4", + "@vitejs/plugin-react": "^4.4.0", + "autoprefixer": "^10.4.21", + "eslint": "^9.24.0", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.19", + "globals": "^15.15.0", + "postcss": "^8.5.3", + "tailwindcss": "^4.1.4", + "typescript": "~5.7.3", + "typescript-eslint": "^8.30.1", + "vite": "^6.2.6" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@aztec/bb.js": { + "version": "0.82.2", + "resolved": "https://registry.npmjs.org/@aztec/bb.js/-/bb.js-0.82.2.tgz", + "integrity": "sha512-MBOHFVHOtfsknyJ1IsHH30paYqf0qLwYkiDTPyH1/KtkMwemvo5VyIgY0Dsl81KQa388MzoKhC6qnaFgERiaog==", + "license": "MIT", + "dependencies": { + "comlink": "^4.4.1", + "commander": "^12.1.0", + "debug": "^4.3.4", + "fflate": "^0.8.0", + "pako": "^2.1.0", + "tslib": "^2.4.0" + }, + "bin": { + "bb.js": "dest/node/main.js" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz", + "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz", + "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.1", + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helpers": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/template": "^7.27.1", + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1", + "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/generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz", + "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.1", + "@babel/types": "^7.27.1", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz", + "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz", + "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", + "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz", + "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1", + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", + "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", + "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", + "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", + "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", + "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", + "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", + "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", + "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", + "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", + "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", + "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", + "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", + "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", + "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", + "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", + "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", + "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", + "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", + "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", + "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", + "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", + "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", + "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", + "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", + "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", + "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/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, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", + "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", + "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "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/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.26.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.26.0.tgz", + "integrity": "sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", + "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.13.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "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, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "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==", + "dev": true, + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.2.tgz", + "integrity": "sha512-H9vwztj5OAqHg9GockCQC06k1natgcxWQSRpQcPJf6i5+MWBzfKkRtxGbjQf0X2ihii0ffLZCRGbYV2f2bjNCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.3", + "eventsource": "^3.0.2", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@noir-lang/acvm_js": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/@noir-lang/acvm_js/-/acvm_js-1.0.0-beta.2.tgz", + "integrity": "sha512-vZYidnNS0MGRddggrq73Te0MiOb7j7ehZwM5L0dbxGwG6RqUNU+RDjG/TE7VUHOOFkZGY20lQqjHY1mj4pOH2A==", + "license": "MIT" + }, + "node_modules/@noir-lang/noir_js": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/@noir-lang/noir_js/-/noir_js-1.0.0-beta.2.tgz", + "integrity": "sha512-CiHnU5H1tUQHoKheHh93Ss7DJificdjXFUUfdasjMd8lsCMCPqY/oUoG4FZjWb7mWT8h0d/qcpGKMbs1VkBThQ==", + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "@noir-lang/acvm_js": "1.0.0-beta.2", + "@noir-lang/noirc_abi": "1.0.0-beta.2", + "@noir-lang/types": "1.0.0-beta.2" + } + }, + "node_modules/@noir-lang/noir_wasm": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/@noir-lang/noir_wasm/-/noir_wasm-1.0.0-beta.2.tgz", + "integrity": "sha512-B6zn1mgKBIDZE4nGvl6sOgErg7VsZOjP2D4FPHlHj4QF7h7ZbaISJ3+NM38FolaRkGEm2sSmSonaqKum0DchRA==", + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "@noir-lang/types": "1.0.0-beta.2", + "pako": "^2.1.0" + } + }, + "node_modules/@noir-lang/noirc_abi": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/@noir-lang/noirc_abi/-/noirc_abi-1.0.0-beta.2.tgz", + "integrity": "sha512-8/Pc6C0IY4F3UCsubs96G4Nwalzo49TVW+2jej7uNaEJB7LCqbOk5G641XGcCV2McS7n7WbLt1eN3cKJrxUWrA==", + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "@noir-lang/types": "1.0.0-beta.2" + } + }, + "node_modules/@noir-lang/types": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/@noir-lang/types/-/types-1.0.0-beta.2.tgz", + "integrity": "sha512-0CosvfeAhwjmEt5cwJtEbju+8itRpmOUOmyt6TUo6JcRxaR8d4A+7j0sOgGxs2KVqWnMi1akJdGodAu0e4H+1A==", + "license": "(MIT OR Apache-2.0)" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz", + "integrity": "sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.2.tgz", + "integrity": "sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.2.tgz", + "integrity": "sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.2.tgz", + "integrity": "sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.2.tgz", + "integrity": "sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.2.tgz", + "integrity": "sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.2.tgz", + "integrity": "sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.2.tgz", + "integrity": "sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.2.tgz", + "integrity": "sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.2.tgz", + "integrity": "sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.2.tgz", + "integrity": "sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.2.tgz", + "integrity": "sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.2.tgz", + "integrity": "sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.2.tgz", + "integrity": "sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.2.tgz", + "integrity": "sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.2.tgz", + "integrity": "sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.2.tgz", + "integrity": "sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.2.tgz", + "integrity": "sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.2.tgz", + "integrity": "sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz", + "integrity": "sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "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, + "license": "MIT", + "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.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/bn.js": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz", + "integrity": "sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/crypto-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz", + "integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==", + "license": "MIT" + }, + "node_modules/@types/elliptic": { + "version": "6.4.18", + "resolved": "https://registry.npmjs.org/@types/elliptic/-/elliptic-6.4.18.tgz", + "integrity": "sha512-UseG6H5vjRiNpQvrhy4VF/JXdA3V/Fp5amvveaL+fs28BZ6xIKJBPnUPRlEaZpysD9MbpfaLi8lbl7PGUAkpWw==", + "license": "MIT", + "dependencies": { + "@types/bn.js": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.15.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz", + "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/react": { + "version": "19.1.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.3.tgz", + "integrity": "sha512-dLWQ+Z0CkIvK1J8+wrDPwGxEYFA4RAyHoZPxHVGspYmFVnwGSNT24cGIhFJrtfRnWVuW8X7NO52gCXmhkVUWGQ==", + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.1.4", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.4.tgz", + "integrity": "sha512-WxYAszDYgsMV31OVyoG4jbAgJI1Gw0Xq9V19zwhy6+hUUJlJIdZ3r/cbdmTqFv++SktQkZ/X+46yGFxp5XJBEg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.0.0" + } + }, + "node_modules/@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "node_modules/@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.0.tgz", + "integrity": "sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.32.0", + "@typescript-eslint/type-utils": "8.32.0", + "@typescript-eslint/utils": "8.32.0", + "@typescript-eslint/visitor-keys": "8.32.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.0.tgz", + "integrity": "sha512-B2MdzyWxCE2+SqiZHAjPphft+/2x2FlO9YBx7eKE1BCb+rqBlQdhtAEhzIEdozHd55DXPmxBdpMygFJjfjjA9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.32.0", + "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/typescript-estree": "8.32.0", + "@typescript-eslint/visitor-keys": "8.32.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.0.tgz", + "integrity": "sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/visitor-keys": "8.32.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.0.tgz", + "integrity": "sha512-t2vouuYQKEKSLtJaa5bB4jHeha2HJczQ6E5IXPDPgIty9EqcJxpr1QHQ86YyIPwDwxvUmLfP2YADQ5ZY4qddZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.32.0", + "@typescript-eslint/utils": "8.32.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.0.tgz", + "integrity": "sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.0.tgz", + "integrity": "sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/visitor-keys": "8.32.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.0.tgz", + "integrity": "sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.32.0", + "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/typescript-estree": "8.32.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.0.tgz", + "integrity": "sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.32.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz", + "integrity": "sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.26.10", + "@babel/plugin-transform-react-jsx-self": "^7.25.9", + "@babel/plugin-transform-react-jsx-source": "^7.25.9", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "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, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.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, + "license": "MIT", + "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/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, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/autoprefixer": { + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.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, + "license": "MIT" + }, + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/borsh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/borsh/-/borsh-2.0.0.tgz", + "integrity": "sha512-kc9+BgR3zz9+cjbwM8ODoUB4fs3X3I5A/HtX7LZKxCLaMrEeDFoBpnhZY//DTS1VZBSs6S5v46RZRbZjRFspEg==", + "license": "Apache-2.0" + }, + "node_modules/borsher": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/borsher/-/borsher-3.6.0.tgz", + "integrity": "sha512-FMMQST0PdrhernqtxHGvq9wIgV6rJkJecfVs7VhL5jYCFFLsXGMn/VtY0s5zotkKHrrdS5Np/DoL2FTR4cdoqw==", + "license": "MIT", + "dependencies": { + "borsh": "^2.0.0", + "buffer": "^6.0.3" + } + }, + "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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "license": "MIT" + }, + "node_modules/browserslist": { + "version": "4.24.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", + "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", + "dev": true, + "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" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001716", + "electron-to-chromium": "^1.5.149", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001717", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001717.tgz", + "integrity": "sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==", + "dev": true, + "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" + } + ], + "license": "CC-BY-4.0" + }, + "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, + "license": "MIT", + "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/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, + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/comlink": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/comlink/-/comlink-4.4.2.tgz", + "integrity": "sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g==", + "license": "Apache-2.0" + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "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, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "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, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "license": "MIT" + }, + "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/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": 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, + "license": "MIT" + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.151", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.151.tgz", + "integrity": "sha512-Rl6uugut2l9sLojjS4H4SAr3A4IgACMLgpuEMPYCVcKydzfyPrn5absNRju38IhQOf/NwjJY8OGWjlteqYeBCA==", + "dev": true, + "license": "ISC" + }, + "node_modules/elliptic": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", + "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.4", + "@esbuild/android-arm": "0.25.4", + "@esbuild/android-arm64": "0.25.4", + "@esbuild/android-x64": "0.25.4", + "@esbuild/darwin-arm64": "0.25.4", + "@esbuild/darwin-x64": "0.25.4", + "@esbuild/freebsd-arm64": "0.25.4", + "@esbuild/freebsd-x64": "0.25.4", + "@esbuild/linux-arm": "0.25.4", + "@esbuild/linux-arm64": "0.25.4", + "@esbuild/linux-ia32": "0.25.4", + "@esbuild/linux-loong64": "0.25.4", + "@esbuild/linux-mips64el": "0.25.4", + "@esbuild/linux-ppc64": "0.25.4", + "@esbuild/linux-riscv64": "0.25.4", + "@esbuild/linux-s390x": "0.25.4", + "@esbuild/linux-x64": "0.25.4", + "@esbuild/netbsd-arm64": "0.25.4", + "@esbuild/netbsd-x64": "0.25.4", + "@esbuild/openbsd-arm64": "0.25.4", + "@esbuild/openbsd-x64": "0.25.4", + "@esbuild/sunos-x64": "0.25.4", + "@esbuild/win32-arm64": "0.25.4", + "@esbuild/win32-ia32": "0.25.4", + "@esbuild/win32-x64": "0.25.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.26.0.tgz", + "integrity": "sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.20.0", + "@eslint/config-helpers": "^0.2.1", + "@eslint/core": "^0.13.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.26.0", + "@eslint/plugin-kit": "^0.2.8", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@modelcontextprotocol/sdk": "^1.8.0", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.3.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.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", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "zod": "^3.24.2" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.20", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz", + "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-scope": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", + "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "dev": true, + "license": "BSD-2-Clause", + "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": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "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==", + "dev": true, + "license": "BSD-2-Clause", + "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, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz", + "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", + "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": "^4.11 || 5 || ^5.0.0-beta.1" + } + }, + "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, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "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.8" + }, + "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, + "license": "ISC", + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.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, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "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, + "license": "MIT", + "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/hyle": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/hyle/-/hyle-0.2.5.tgz", + "integrity": "sha512-gipgPr0Ae8DoJ6l5WxWnvrZSgo1iGhvoPcGw0DHU9gBaSWVjN/OgQezfnXaOUW8hB7yPE71oFpReqUmYQetpBQ==", + "license": "MIT", + "dependencies": { + "borsher": "^3.6.0" + } + }, + "node_modules/hyle-check-secret": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/hyle-check-secret/-/hyle-check-secret-0.3.2.tgz", + "integrity": "sha512-5Iq1Lk447I2jhQlcE7i39uTIrOnl8aQB2St6hUbu7YSE5Su9VjuvEvVOGRp04bd3yT15jJimXemiWrjD3dvctA==", + "license": "MIT", + "dependencies": { + "@aztec/bb.js": "0.82.2", + "@noir-lang/noir_js": "1.0.0-beta.2", + "@noir-lang/noir_wasm": "1.0.0-beta.2", + "hyle": "0.2.2" + } + }, + "node_modules/hyle-check-secret/node_modules/hyle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/hyle/-/hyle-0.2.2.tgz", + "integrity": "sha512-uyi5G+NoxEy39HVFfFZ8m328+c7dYKpK49hSW9stRfQV/OJxJjwUZBFh9BtcnQDnp+nKcaq5pqSNgQ0whVu1lQ==", + "license": "MIT", + "dependencies": { + "borsher": "^3.6.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "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==", + "dev": true, + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "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, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.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, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT" + }, + "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==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "license": "ISC" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "license": "MIT" + }, + "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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "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==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "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, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "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/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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "license": "(MIT AND Zlib)" + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/postcss": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "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" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" } }, - "node_modules/@types/node": { - "version": "22.15.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz", - "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==", + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "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, + "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" } }, - "node_modules/@types/react": { - "version": "19.1.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.3.tgz", - "integrity": "sha512-dLWQ+Z0CkIvK1J8+wrDPwGxEYFA4RAyHoZPxHVGspYmFVnwGSNT24cGIhFJrtfRnWVuW8X7NO52gCXmhkVUWGQ==", + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "csstype": "^3.0.2" + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/react-dom": { - "version": "19.1.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.3.tgz", - "integrity": "sha512-rJXC08OG0h3W6wDMFxQrZF00Kq6qQvw0djHRdzl3U5DnIERz0MRce3WVc7IS6JYBwtaP/DwYtRRjVlvivNveKg==", - "peerDependencies": { - "@types/react": "^19.0.0" + "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" + } + ], + "license": "MIT" + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.6" } }, - "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/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } }, "node_modules/react": { "version": "19.1.0", @@ -65,15 +3928,533 @@ "react": "^19.1.0" } }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.6.0.tgz", + "integrity": "sha512-GGufuHIVCJDbnIAXP3P9Sxzq3UUsddG3rrI3ut1q6m0FI6vxVBF3JoPQ38+W/blslLH4a5Yutp8drkEpXoddGQ==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.6.0.tgz", + "integrity": "sha512-DYgm6RDEuKdopSyGOWZGtDfSm7Aofb8CCzgkliTjtu/eDuB0gcsv6qdFhhi8HdtmA+KHkt5MfZ5K2PdzjugYsA==", + "license": "MIT", + "dependencies": { + "react-router": "7.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/react-router/node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.2.tgz", + "integrity": "sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.7" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.40.2", + "@rollup/rollup-android-arm64": "4.40.2", + "@rollup/rollup-darwin-arm64": "4.40.2", + "@rollup/rollup-darwin-x64": "4.40.2", + "@rollup/rollup-freebsd-arm64": "4.40.2", + "@rollup/rollup-freebsd-x64": "4.40.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.40.2", + "@rollup/rollup-linux-arm-musleabihf": "4.40.2", + "@rollup/rollup-linux-arm64-gnu": "4.40.2", + "@rollup/rollup-linux-arm64-musl": "4.40.2", + "@rollup/rollup-linux-loongarch64-gnu": "4.40.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.40.2", + "@rollup/rollup-linux-riscv64-gnu": "4.40.2", + "@rollup/rollup-linux-riscv64-musl": "4.40.2", + "@rollup/rollup-linux-s390x-gnu": "4.40.2", + "@rollup/rollup-linux-x64-gnu": "4.40.2", + "@rollup/rollup-linux-x64-musl": "4.40.2", + "@rollup/rollup-win32-arm64-msvc": "4.40.2", + "@rollup/rollup-win32-ia32-msvc": "4.40.2", + "@rollup/rollup-win32-x64-msvc": "4.40.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "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" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "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" + } + ], + "license": "MIT" + }, + "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, + "license": "MIT" + }, "node_modules/scheduler": { "version": "0.26.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==" }, + "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, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.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, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tailwindcss": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.6.tgz", + "integrity": "sha512-j0cGLTreM6u4OWzBeLBpycK0WIh8w7kSwcUsQZoGLHZ7xDTdM69lN64AgoIEEwFi0tnhs4wSykUa5YWxAzgFYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "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, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -82,10 +4463,270 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.0.tgz", + "integrity": "sha512-UMq2kxdXCzinFFPsXc9o2ozIpYCCOiEC46MG3yEh5Vipq6BO27otTtEBZA1fQ66DulEUgE97ucQ/3YY66CPg0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.32.0", + "@typescript-eslint/parser": "8.32.0", + "@typescript-eslint/utils": "8.32.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==" + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "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" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.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, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.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, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vite": { + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "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, + "license": "MIT", + "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, + "license": "ISC" + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.24.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz", + "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.5", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", + "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", + "dev": true, + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } } } } diff --git a/hyle-wallet/package.json b/hyle-wallet/package.json index bf5b93f..b812094 100644 --- a/hyle-wallet/package.json +++ b/hyle-wallet/package.json @@ -27,14 +27,14 @@ "elliptic": "^6.6.1", "hyle": "^0.2.5", "hyle-check-secret": "^0.3.2", - "react": "^19.1.0", - "react-dom": "^19.1.0", + "react": "^18.0.0", + "react-dom": "^18.0.0", "react-router-dom": "^7.5.0" }, "devDependencies": { "@eslint/js": "^9.24.0", - "@types/react": "^19.1.2", - "@types/react-dom": "^19.1.2", + "@types/react": "^19.1.3", + "@types/react-dom": "^19.1.4", "@vitejs/plugin-react": "^4.4.0", "autoprefixer": "^10.4.21", "eslint": "^9.24.0", diff --git a/hyle-wallet/src/components/HyleWallet.tsx b/hyle-wallet/src/components/HyleWallet.tsx index 2c59ad7..9e7c6b9 100644 --- a/hyle-wallet/src/components/HyleWallet.tsx +++ b/hyle-wallet/src/components/HyleWallet.tsx @@ -1,11 +1,11 @@ -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import { Wallet } from '../types/wallet'; import { authProviderManager } from '../providers/AuthProviderManager'; import { AuthForm } from './auth/AuthForm'; import './HyleWallet.css'; import { useConfig } from '../hooks/useConfig'; - -export type ProviderOption = 'password' | 'google' | 'github' | 'x'; +import type { ProviderOption } from '../hooks/useWallet'; +import { useWallet } from '../hooks/useWallet'; // SVG Icons for providers const ProviderIcons = { @@ -38,30 +38,36 @@ const ProviderIcons = { }; interface HyleWalletProps { - /** - * List of providers to display in the selector. "password" will always be shown if omitted. - */ - providers?: ProviderOption[]; /** * Optional render prop that gives full control over the connect button UI. * If not supplied, a simple default button will be rendered. */ button?: (props: { onClick: () => void }) => React.ReactNode; /** - * Callback invoked when the user successfully connects (creates or logs-in) a wallet. + * Optional explicit provider list (e.g., ["password", "google"]). If omitted, available providers will be detected automatically. */ - onWalletConnected?: (wallet: Wallet) => void; + providers?: ProviderOption[]; } export const HyleWallet = ({ - providers = [], button, - onWalletConnected, + providers, }: HyleWalletProps) => { const [isOpen, setIsOpen] = useState(false); const [selectedProvider, setSelectedProvider] = useState(null); const [showLogin, setShowLogin] = useState(true); // true = login (default), false = create/sign-up const { isLoading: isLoadingConfig, error: configError } = useConfig(); + const { wallet } = useWallet(); + + // Get available providers dynamically + const availableProviders = authProviderManager.getAvailableProviders() as ProviderOption[]; + + // Close the modal automatically when the user is connected + useEffect(() => { + if (wallet && isOpen) { + setIsOpen(false); + } + }, [wallet, isOpen]); const openModal = () => setIsOpen(true); @@ -70,11 +76,6 @@ export const HyleWallet = ({ setSelectedProvider(null); setShowLogin(true); }; - - const handleWalletConnected = (wallet: Wallet) => { - onWalletConnected?.(wallet); - closeModal(); - }; if (isLoadingConfig) { return
Loading configuration...
; @@ -148,7 +149,7 @@ export const HyleWallet = ({

Sign in

- {providers.map(renderProviderButton)} + {(providers ?? availableProviders).map(renderProviderButton)}
)} @@ -161,7 +162,6 @@ export const HyleWallet = ({
@@ -73,7 +93,7 @@ export const AuthForm: React.FC = ({ value={credentials.password} onChange={handleInputChange} placeholder="Enter your password" - disabled={isLoading} + disabled={isSubmitting || stage === 'submitting' || stage === 'blobSent'} /> @@ -87,20 +107,26 @@ export const AuthForm: React.FC = ({ value={credentials.confirmPassword} onChange={handleInputChange} placeholder="Confirm your password" - disabled={isLoading} + disabled={isSubmitting || stage === 'submitting' || stage === 'blobSent'} /> )} {error &&
{error}
} - {status &&
{status}
} + {statusMessage &&
{statusMessage}
} ); diff --git a/hyle-wallet/src/hooks/useWallet.tsx b/hyle-wallet/src/hooks/useWallet.tsx index 0d20f16..30777bb 100644 --- a/hyle-wallet/src/hooks/useWallet.tsx +++ b/hyle-wallet/src/hooks/useWallet.tsx @@ -3,6 +3,7 @@ import React, { createContext, useContext, useState, useCallback } from 'react'; import type { Wallet } from '../types/wallet'; import type { AuthCredentials } from '../providers/BaseAuthProvider'; import { authProviderManager } from '../providers/AuthProviderManager'; +import { AuthStage } from '../types/login'; export type ProviderOption = 'password' | 'google' | 'github' | 'x'; @@ -10,6 +11,7 @@ interface WalletContextType { wallet: Wallet | null; isLoading: boolean; error: string | null; + stage: AuthStage; login: (provider: ProviderOption, credentials: AuthCredentials) => Promise; register: (provider: ProviderOption, credentials: AuthCredentials) => Promise; logout: () => void; @@ -21,10 +23,12 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr const [wallet, setWallet] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); + const [stage, setStage] = useState('idle'); const clear = () => { setWallet(null); setError(null); + setStage('idle'); }; const login = useCallback(async (provider: ProviderOption, credentials: AuthCredentials) => { @@ -36,14 +40,30 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr try { setIsLoading(true); setError(null); - const result = await authProvider.login(credentials as any); + setStage('submitting'); + + const resultPromise = authProvider.login(credentials as any, (optimisticWallet: Wallet) => { + // Called as soon as blob/proofs are sent + setWallet(optimisticWallet); + setStage('blobSent'); + setIsLoading(false); + }); + + const result = await resultPromise; + if (result.success && result.wallet) { + // Settlement achieved setWallet(result.wallet); + setStage('settled'); } else { + setStage('error'); setError(result.error ?? 'Login failed'); + setWallet(null); } } catch (e) { + setStage('error'); setError(e instanceof Error ? e.message : 'Login failed'); + setWallet(null); } finally { setIsLoading(false); } @@ -58,14 +78,28 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr try { setIsLoading(true); setError(null); - const result = await authProvider.register(credentials as any); + setStage('submitting'); + + const resultPromise = authProvider.register(credentials as any, (optimisticWallet: Wallet) => { + setWallet(optimisticWallet); + setStage('blobSent'); + setIsLoading(false); + }); + + const result = await resultPromise; + if (result.success && result.wallet) { setWallet(result.wallet); + setStage('settled'); } else { + setStage('error'); setError(result.error ?? 'Registration failed'); + setWallet(null); } } catch (e) { + setStage('error'); setError(e instanceof Error ? e.message : 'Registration failed'); + setWallet(null); } finally { setIsLoading(false); } @@ -76,7 +110,7 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr }, []); return ( - + {children} ); diff --git a/hyle-wallet/src/providers/BaseAuthProvider.ts b/hyle-wallet/src/providers/BaseAuthProvider.ts index 301b109..4f22977 100644 --- a/hyle-wallet/src/providers/BaseAuthProvider.ts +++ b/hyle-wallet/src/providers/BaseAuthProvider.ts @@ -13,7 +13,7 @@ export interface AuthResult { export interface AuthProvider { type: string; - login(credentials: AuthCredentials): Promise; - register(credentials: AuthCredentials): Promise; + login(credentials: AuthCredentials, onBlobSent?: (wallet: Wallet) => void): Promise; + register(credentials: AuthCredentials, onBlobSent?: (wallet: Wallet) => void): Promise; isEnabled(): boolean; } \ No newline at end of file diff --git a/hyle-wallet/src/providers/PasswordAuthProvider.ts b/hyle-wallet/src/providers/PasswordAuthProvider.ts index b850a49..99353a3 100644 --- a/hyle-wallet/src/providers/PasswordAuthProvider.ts +++ b/hyle-wallet/src/providers/PasswordAuthProvider.ts @@ -18,7 +18,7 @@ export class PasswordAuthProvider implements AuthProvider { return true; } - async login(credentials: PasswordAuthCredentials): Promise { + async login(credentials: PasswordAuthCredentials, onBlobSent?: (wallet: Wallet) => void): Promise { try { const { username, password } = credentials; @@ -38,6 +38,17 @@ export class PasswordAuthProvider implements AuthProvider { console.log('Blob transaction:', blobTx); const tx_hash = await nodeService.client.sendBlobTx(blobTx); + + // Optimistic notification to the caller that the blobTx has been sent successfully + const optimisticWallet: Wallet = { + username, + address: identity, + }; + onBlobSent?.(optimisticWallet); + + // TODO: Execute noir circuit to make sure the blobTx is valid + + // Build and send the proof transaction (may take some time) const proofTx = await build_proof_transaction( identity, password, @@ -48,6 +59,7 @@ export class PasswordAuthProvider implements AuthProvider { await nodeService.client.sendProofTx(proofTx); + // Wait for on-chain settlement (existing behaviour) await new Promise((resolve, reject) => { const timeout = setTimeout(() => { webSocketService.unsubscribeFromWalletEvents(); @@ -56,11 +68,17 @@ export class PasswordAuthProvider implements AuthProvider { webSocketService.connect(identity); const unsubscribeWalletEvents = webSocketService.subscribeToWalletEvents((event) => { - if (event.event === 'Identity verified') { + const msg = event.event.toLowerCase(); + if (msg.includes('identity verified')) { clearTimeout(timeout); unsubscribeWalletEvents(); webSocketService.disconnect(); resolve(event); + } else if (msg.includes('failed') || msg.includes('error')) { + clearTimeout(timeout); + unsubscribeWalletEvents(); + webSocketService.disconnect(); + reject(new Error(event.event)); } }); }); @@ -79,7 +97,7 @@ export class PasswordAuthProvider implements AuthProvider { } } - async register(credentials: PasswordAuthCredentials): Promise { + async register(credentials: PasswordAuthCredentials, onBlobSent?: (wallet: Wallet) => void): Promise { try { const { username, password, confirmPassword } = credentials; @@ -110,6 +128,14 @@ export class PasswordAuthProvider implements AuthProvider { await register_contract(nodeService.client as any); const tx_hash = await nodeService.client.sendBlobTx(blobTx); + // Optimistic notification to the caller that the blobTx has been sent successfully + const optimisticWallet: Wallet = { + username, + address: identity, + }; + onBlobSent?.(optimisticWallet); + + // Build and send the proof transaction (may take some time) const proofTx = await build_proof_transaction( identity, password, @@ -120,6 +146,7 @@ export class PasswordAuthProvider implements AuthProvider { await nodeService.client.sendProofTx(proofTx); + // Wait for on-chain settlement (existing behaviour) await new Promise((resolve, reject) => { const timeout = setTimeout(() => { webSocketService.unsubscribeFromWalletEvents(); @@ -128,11 +155,17 @@ export class PasswordAuthProvider implements AuthProvider { webSocketService.connect(identity); const unsubscribeWalletEvents = webSocketService.subscribeToWalletEvents((event) => { - if (event.event.startsWith('Successfully registered identity for account')) { + const msg = event.event.toLowerCase(); + if (msg.startsWith('successfully registered identity')) { clearTimeout(timeout); unsubscribeWalletEvents(); webSocketService.disconnect(); resolve(event); + } else if (msg.includes('failed') || msg.includes('error')) { + clearTimeout(timeout); + unsubscribeWalletEvents(); + webSocketService.disconnect(); + reject(new Error(event.event)); } }); }); diff --git a/hyle-wallet/src/types/login.ts b/hyle-wallet/src/types/login.ts new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/hyle-wallet/src/types/login.ts @@ -0,0 +1 @@ + \ No newline at end of file From 3e5169bb391cc8d0612510b5adec16f476f278d5 Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Mon, 12 May 2025 18:26:46 +0200 Subject: [PATCH 04/17] diverse clean --- hyle-wallet/bun.lockb | Bin 133892 -> 135409 bytes hyle-wallet/src/components/HyleWallet.tsx | 1 - hyle-wallet/src/components/auth/AuthForm.tsx | 2 +- hyle-wallet/src/index.ts | 3 ++- hyle-wallet/src/types/login.ts | 10 +++++++++- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/hyle-wallet/bun.lockb b/hyle-wallet/bun.lockb index a797b68094d523e70cf5d9fad41dfca5c77c9f55..1a699a47f19498e3e0c9a41623a3fa070396d8a7 100755 GIT binary patch delta 24211 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 T%Cf6i`IOb#TGvK?So8k?m_R^^ delta 23536 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 diff --git a/hyle-wallet/src/components/HyleWallet.tsx b/hyle-wallet/src/components/HyleWallet.tsx index 9e7c6b9..dc18016 100644 --- a/hyle-wallet/src/components/HyleWallet.tsx +++ b/hyle-wallet/src/components/HyleWallet.tsx @@ -1,5 +1,4 @@ import { useState, useEffect } from 'react'; -import { Wallet } from '../types/wallet'; import { authProviderManager } from '../providers/AuthProviderManager'; import { AuthForm } from './auth/AuthForm'; import './HyleWallet.css'; diff --git a/hyle-wallet/src/components/auth/AuthForm.tsx b/hyle-wallet/src/components/auth/AuthForm.tsx index 1d92b42..c349fa2 100644 --- a/hyle-wallet/src/components/auth/AuthForm.tsx +++ b/hyle-wallet/src/components/auth/AuthForm.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { AuthCredentials, AuthProvider, AuthResult } from '../../providers/BaseAuthProvider'; +import { AuthCredentials, AuthProvider } from '../../providers/BaseAuthProvider'; import { useWallet, ProviderOption } from '../../hooks/useWallet'; import { AuthStage } from '../../types/login'; import './AuthForm.css'; diff --git a/hyle-wallet/src/index.ts b/hyle-wallet/src/index.ts index edbc69b..2bdfd9b 100644 --- a/hyle-wallet/src/index.ts +++ b/hyle-wallet/src/index.ts @@ -1,6 +1,7 @@ import React from 'react'; import { createRoot } from 'react-dom/client'; -import { HyleWallet, ProviderOption } from './components/HyleWallet'; +import { HyleWallet } from './components/HyleWallet'; +import { ProviderOption } from './hooks/useWallet'; // Export the React component directly export { HyleWallet } from './components/HyleWallet'; diff --git a/hyle-wallet/src/types/login.ts b/hyle-wallet/src/types/login.ts index 0519ecb..f992c0b 100644 --- a/hyle-wallet/src/types/login.ts +++ b/hyle-wallet/src/types/login.ts @@ -1 +1,9 @@ - \ No newline at end of file +/** + * Represents the different stages of the authentication process + */ +export type AuthStage = + | 'idle' // Initial state, no authentication in progress + | 'submitting' // Authentication request is being sent + | 'blobSent' // Blob/proofs have been sent and we're waiting for confirmation + | 'settled' // Authentication has completed successfully + | 'error'; // An error occurred during authentication From 3e4990d5c6636ed488b9ec22562fa981087dcbf4 Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Mon, 12 May 2025 18:43:53 +0200 Subject: [PATCH 05/17] Remove code redundancy --- front/src/App.tsx | 8 +- front/src/components/auth/CreateWallet.tsx | 177 ------------------ front/src/components/auth/LoginWallet.tsx | 142 -------------- front/src/components/wallet/SessionKeys.tsx | 10 +- front/src/hooks/useConfig.ts | 27 --- front/src/services/SessionKeyService.ts | 92 --------- front/src/services/config.ts | 13 -- hyle-wallet/src/services/SessionKeyService.ts | 1 - 8 files changed, 10 insertions(+), 460 deletions(-) delete mode 100644 front/src/components/auth/CreateWallet.tsx delete mode 100644 front/src/components/auth/LoginWallet.tsx delete mode 100644 front/src/hooks/useConfig.ts delete mode 100644 front/src/services/SessionKeyService.ts delete mode 100644 front/src/services/config.ts diff --git a/front/src/App.tsx b/front/src/App.tsx index 5a67a52..8052f21 100644 --- a/front/src/App.tsx +++ b/front/src/App.tsx @@ -1,14 +1,14 @@ -import { useState, useEffect } from 'react'; -import { BrowserRouter, Routes, Route, useNavigate, useRoutes } from 'react-router-dom'; +import { useEffect } from 'react'; +import { BrowserRouter, Routes, Route, useNavigate } from 'react-router-dom'; import './App.css'; -import { LoadingErrorState } from './components/common/LoadingErrorState'; import { WalletShowcase } from './components/WalletShowcase'; -import { useConfig } from './hooks/useConfig'; import { useWalletBalance } from './hooks/useWalletBalance'; import { useWalletTransactions } from './hooks/useWalletTransactions'; import { useWebSocketConnection } from './hooks/useWebSocketConnection'; import { getPublicRoutes, getProtectedRoutes, ROUTES } from './routes/routes'; import { WalletProvider, useWallet } from '../../hyle-wallet/src'; +import { useConfig } from 'hyle-wallet/src/hooks/useConfig'; +import { LoadingErrorState } from './components/common/LoadingErrorState'; function AppContent() { const { isLoading: isLoadingConfig, error: configError } = useConfig(); diff --git a/front/src/components/auth/CreateWallet.tsx b/front/src/components/auth/CreateWallet.tsx deleted file mode 100644 index bf1b885..0000000 --- a/front/src/components/auth/CreateWallet.tsx +++ /dev/null @@ -1,177 +0,0 @@ -import { useState } from 'react'; -import { Buffer } from 'buffer'; -import { register, Wallet, walletContractName } from '../../types/wallet'; -import { build_proof_transaction, build_blob as check_secret_blob, register_contract } from 'hyle-check-secret'; -import { BlobTransaction } from 'hyle'; -import { nodeService } from '../../services/NodeService'; -import { webSocketService } from '../../services/WebSocketService'; - -interface CreateWalletProps { - onWalletCreated: (wallet: Wallet) => void; -} - -export const CreateWallet = ({ onWalletCreated }: CreateWalletProps) => { - const [username, setUsername] = useState('bob'); - const [password, setPassword] = useState('password123'); - const [confirmPassword, setConfirmPassword] = useState('password123'); - const [error, setError] = useState(''); - const [isLoading, setIsLoading] = useState(false); - const [status, setStatus] = useState(''); - const [transactionHash, setTransactionHash] = useState(''); - - const handleCreateWallet = async () => { - setError(''); - setIsLoading(true); - setStatus('Validating input...'); - - try { - if (!username || !password || !confirmPassword) { - setError('Please fill in all fields'); - return; - } - - if (password !== confirmPassword) { - setError('Passwords do not match'); - return; - } - - if (password.length < 8) { - setError('Password must be at least 8 characters long'); - return; - } - - setStatus('Generating wallet credentials...'); - const identity = `${username}@${walletContractName}`; - const blob0 = await check_secret_blob(identity, password); - const hash = Buffer.from(blob0.data).toString('hex'); - const blob1 = register(username, Date.now(), hash); - - const blobTx: BlobTransaction = { - identity, - blobs: [blob0, blob1], - } - - setStatus('Sending transaction...'); - await register_contract(nodeService.client as any); - const tx_hash = await nodeService.client.sendBlobTx(blobTx); - setTransactionHash(tx_hash); - - setStatus('Building proof transaction (this may take a few moments)...'); - const proofTx = await build_proof_transaction( - identity, - password, - tx_hash, - 0, - blobTx.blobs.length, - ); - - setStatus('Sending proof transaction...'); - await nodeService.client.sendProofTx(proofTx); - setStatus('Waiting for wallet creation confirmation...'); - - try { - await new Promise((resolve, reject) => { - const timeout = setTimeout(() => { - unsubscribeWalletEvents(); - reject(new Error('Wallet creation timed out')); - }, 60000); - - webSocketService.connect(identity); - const unsubscribeWalletEvents = webSocketService.subscribeToWalletEvents((event) => { - if (event.event.startsWith('Successfully registered identity for account')) { - clearTimeout(timeout); - unsubscribeWalletEvents(); - webSocketService.disconnect(); - resolve(event); - } else { - clearTimeout(timeout); - unsubscribeWalletEvents(); - webSocketService.disconnect(); - reject(new Error('Wallet creation failed: ' + event.event)); - } - }); - }); - - setStatus('Wallet created successfully!'); - - const wallet: Wallet = { - username, - address: identity - }; - - onWalletCreated(wallet); - } catch (error) { - throw new Error(error instanceof Error ? error.message : 'Wallet creation failed'); - } - } catch (error) { - setError('Failed to create wallet. Please try again.'); - console.error('Error creating wallet:', error); - } finally { - setIsLoading(false); - } - }; - - return ( -
-

Create Your Wallet

-
-
- - setUsername(e.target.value)} - placeholder="Choose a username" - className="form-input" - /> -
-
- - setPassword(e.target.value)} - placeholder="Create a password" - className="form-input" - /> -
-
- - setConfirmPassword(e.target.value)} - placeholder="Confirm your password" - className="form-input" - /> -
- - {error &&
{error}
} - {status &&
{status}
} - - - - {transactionHash && ( - - )} -
-
- ); -}; diff --git a/front/src/components/auth/LoginWallet.tsx b/front/src/components/auth/LoginWallet.tsx deleted file mode 100644 index 0a942c2..0000000 --- a/front/src/components/auth/LoginWallet.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import { useState } from 'react'; -import { verifyIdentity, Wallet, walletContractName } from '../../types/wallet'; -import { nodeService } from '../../services/NodeService'; -import { webSocketService } from '../../services/WebSocketService'; -import { build_proof_transaction, build_blob as check_secret_blob } from 'hyle-check-secret'; -import { BlobTransaction } from 'hyle'; - -interface LoginWalletProps { - onWalletLoggedIn: (wallet: Wallet) => void; -} - -export const LoginWallet = ({ onWalletLoggedIn }: LoginWalletProps) => { - const [username, setUsername] = useState('bob'); - const [password, setPassword] = useState('password123'); - const [error, setError] = useState(''); - const [isLoading, setIsLoading] = useState(false); - const [status, setStatus] = useState(''); - const [transactionHash, setTransactionHash] = useState(''); - - const handleLogin = async () => { - setError(''); - setIsLoading(true); - setStatus('Validating credentials...'); - - if (!username || !password) { - setError('Please fill in all fields'); - setIsLoading(false); - return; - } - const identity = `${username}@${walletContractName}`; - const blob0 = await check_secret_blob(identity, password); - const blob1 = verifyIdentity(username, Date.now()); - - const blobTx: BlobTransaction = { - identity, - blobs: [blob0, blob1], - } - - try { - setStatus('Verifying identity...'); - const tx_hash = await nodeService.client.sendBlobTx(blobTx); - setTransactionHash(tx_hash); - setStatus('Building proof transaction (this may take a few moments)...'); - const proofTx = await build_proof_transaction( - identity, - password, - tx_hash, - 0, - blobTx.blobs.length, - ); - setStatus('Sending proof transaction...'); - await nodeService.client.sendProofTx(proofTx); - setStatus('Waiting for transaction confirmation...'); - - try { - await new Promise((resolve, reject) => { - const timeout = setTimeout(() => { - webSocketService.unsubscribeFromWalletEvents(); - reject(new Error('Identity verification timed out')); - }, 30000); - - webSocketService.connect(identity); - const unsubscribeWalletEvents = webSocketService.subscribeToWalletEvents((event) => { - if (event.event === 'Identity verified') { - clearTimeout(timeout); - unsubscribeWalletEvents(); - webSocketService.disconnect(); - resolve(event); - } - }); - }); - } catch (error) { - setError('' + error); - setStatus(''); - console.error('Transaction error:', error); - return; - } - setStatus('Logged in successfully!'); - - const wallet: Wallet = { - username, - address: identity - }; - - onWalletLoggedIn(wallet); - } catch (error) { - setError('Invalid credentials or wallet does not exist'); - console.error('Login error:', error); - } finally { - setIsLoading(false); - } - }; - - return ( -
-

Login to Your Wallet

-
-
- - setUsername(e.target.value)} - placeholder="Enter your username" - /> -
-
- - setPassword(e.target.value)} - placeholder="Enter your password" - /> -
- {error &&
{error}
} - {status &&
{status}
} - - {transactionHash && ( - - )} - -
-
- ); -}; - diff --git a/front/src/components/wallet/SessionKeys.tsx b/front/src/components/wallet/SessionKeys.tsx index b934210..f4f6354 100644 --- a/front/src/components/wallet/SessionKeys.tsx +++ b/front/src/components/wallet/SessionKeys.tsx @@ -3,7 +3,7 @@ import { Wallet, addSessionKey, removeSessionKey, walletContractName } from '../ import { nodeService } from '../../services/NodeService'; import { indexerService } from '../../services/IndexerService'; import { webSocketService } from '../../services/WebSocketService'; -import { sessionKeyService } from '../../services/SessionKeyService'; +import { useSessionKey } from 'hyle-wallet/src/hooks/useSessionKey'; import { build_proof_transaction, build_blob as check_secret_blob } from 'hyle-check-secret'; import { BlobTransaction } from 'hyle'; import './SessionKeys.css'; @@ -32,6 +32,8 @@ export const SessionKeys = ({ wallet }: SessionKeysProps) => { const [isLoading, setIsLoading] = useState(false); const [transactionHash, setTransactionHash] = useState(''); + const { generateSessionKey, clearSessionKey, createSignedBlobs } = useSessionKey(); + const fetchSessionKeys = async () => { try { const accountInfo = await indexerService.getAccountInfo(wallet.username); @@ -64,7 +66,7 @@ export const SessionKeys = ({ wallet }: SessionKeysProps) => { setTransactionHash(''); // Génère une nouvelle paire de clés - const publicKey = sessionKeyService.generateSessionKey(); + const publicKey = generateSessionKey(); try { const identity = `${wallet.username}@${walletContractName}`; @@ -116,7 +118,7 @@ export const SessionKeys = ({ wallet }: SessionKeysProps) => { await fetchSessionKeys(); } catch (error) { setError('Failed to add session key: ' + error); - sessionKeyService.clear(publicKey); // Remove key from local storage if it fails + clearSessionKey(publicKey); // Remove key from local storage if it fails } finally { setIsLoading(false); } @@ -177,7 +179,7 @@ export const SessionKeys = ({ wallet }: SessionKeysProps) => { try { const identity = `${wallet.username}@${walletContractName}`; - const [blob0, blob1] = sessionKeyService.useSessionKey(wallet.username, key, "Hello world!"); + const [blob0, blob1] = createSignedBlobs(wallet.username, key, "Hello world!"); const blobTx: BlobTransaction = { identity, diff --git a/front/src/hooks/useConfig.ts b/front/src/hooks/useConfig.ts deleted file mode 100644 index 1696dfc..0000000 --- a/front/src/hooks/useConfig.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { useEffect, useState } from "react"; -import { fetchConfig } from "../services/config"; -import { setWalletContractName } from "../types/wallet"; - -export function useConfig() { - const [isLoading, setIsLoading] = useState(true); - const [error, setError] = useState(null); - - useEffect(() => { - const loadConfig = async () => { - try { - const config = await fetchConfig(); - setWalletContractName(config.contract_name); - setIsLoading(false); - } catch (err) { - setError( - err instanceof Error ? err.message : "Failed to load configuration", - ); - setIsLoading(false); - } - }; - - loadConfig(); - }, []); - - return { isLoading, error }; -} diff --git a/front/src/services/SessionKeyService.ts b/front/src/services/SessionKeyService.ts deleted file mode 100644 index a6b15b5..0000000 --- a/front/src/services/SessionKeyService.ts +++ /dev/null @@ -1,92 +0,0 @@ -import EC from 'elliptic'; -import { SHA256 } from 'crypto-js'; -import { Secp256k1Blob, serializeIdentityAction, serializeSecp256k1Blob, WalletAction, walletContractName } from '../types/wallet'; -import { Buffer } from 'buffer'; -import { Blob } from "hyle"; - -class SessionKeyService { - private ec: EC.ec; - - constructor() { - this.ec = new EC.ec('secp256k1'); - } - - - generateSessionKey(): string { - // Génère une paire de clés ECDSA - const keyPair = this.ec.genKeyPair(); - - const privateKey = keyPair.getPrivate('hex'); - if (!privateKey) { - throw new Error('Failed to generate private key'); - } - - const publicKey = keyPair.getPublic(true, 'hex'); - if (!publicKey) { - throw new Error('Failed to generate public key'); - } - - localStorage.setItem(publicKey, privateKey); - - return publicKey; - } - - getSignedBlob(identity: string, message: string, publicKey: string): Secp256k1Blob { - const privateKey = localStorage.getItem(publicKey); - if (!privateKey) { - throw new Error('No session key or provided private key available'); - } - const hash = SHA256(message); - const hashBytes = Buffer.from(hash.toString(), 'hex'); - - if (hashBytes.length !== 32) { - throw new Error('Hash length is not 32 bytes'); - } - - const keyPair = this.ec.keyFromPrivate(privateKey); - const signature = keyPair.sign(hash.toString()); - - // Normaliser s en utilisant min(s, n-s) - const n = this.ec.curve.n; - var s = signature.s; - if (s.gt(n.shrn(1))) { - signature.s = n.sub(s); - } - - const signatureBytes = new Uint8Array([...signature.r.toArray('be', 32), ...signature.s.toArray('be', 32)]); - - const secp256k1Blob: Secp256k1Blob = { - identity: identity, - data: hashBytes, - public_key: new Uint8Array(Buffer.from(publicKey, 'hex')), - signature: signatureBytes, - }; - console.log('secp256k1Blob', secp256k1Blob); - return secp256k1Blob; - } - - useSessionKey(account: string, key: string, message: string): [Blob, Blob] { - const action: WalletAction = { - UseSessionKey: { account, key, message } - }; - - const identity = `${account}@${walletContractName}`; - const secp256k1Blob: Secp256k1Blob = this.getSignedBlob(identity, message, key); - const blob0: Blob = { - contract_name: "secp256k1", - data: serializeSecp256k1Blob(secp256k1Blob), - }; - - const blob1: Blob = { - contract_name: walletContractName, - data: serializeIdentityAction(action), - }; - return [blob0, blob1]; - } - - clear(publicKey: string): void { - localStorage.removeItem(publicKey); - } -} - -export const sessionKeyService = new SessionKeyService(); diff --git a/front/src/services/config.ts b/front/src/services/config.ts deleted file mode 100644 index 959d085..0000000 --- a/front/src/services/config.ts +++ /dev/null @@ -1,13 +0,0 @@ -interface Config { - contract_name: string; -} - -export async function fetchConfig(): Promise { - const response = await fetch( - `${import.meta.env.VITE_SERVER_BASE_URL}/api/config`, - ); - if (!response.ok) { - throw new Error("Failed to fetch config"); - } - return response.json(); -} diff --git a/hyle-wallet/src/services/SessionKeyService.ts b/hyle-wallet/src/services/SessionKeyService.ts index a6b15b5..e300260 100644 --- a/hyle-wallet/src/services/SessionKeyService.ts +++ b/hyle-wallet/src/services/SessionKeyService.ts @@ -11,7 +11,6 @@ class SessionKeyService { this.ec = new EC.ec('secp256k1'); } - generateSessionKey(): string { // Génère une paire de clés ECDSA const keyPair = this.ec.genKeyPair(); From 488022d28d981423f077e269762e720e375371dc Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Mon, 12 May 2025 18:50:49 +0200 Subject: [PATCH 06/17] fix config loading --- front/src/components/wallet/SessionKeys.tsx | 3 ++- front/src/services/IndexerService.ts | 3 ++- front/src/types/wallet.ts | 7 +------ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/front/src/components/wallet/SessionKeys.tsx b/front/src/components/wallet/SessionKeys.tsx index f4f6354..009af65 100644 --- a/front/src/components/wallet/SessionKeys.tsx +++ b/front/src/components/wallet/SessionKeys.tsx @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react'; -import { Wallet, addSessionKey, removeSessionKey, walletContractName } from '../../types/wallet'; +import { Wallet, addSessionKey, removeSessionKey } from '../../types/wallet'; import { nodeService } from '../../services/NodeService'; import { indexerService } from '../../services/IndexerService'; import { webSocketService } from '../../services/WebSocketService'; @@ -7,6 +7,7 @@ import { useSessionKey } from 'hyle-wallet/src/hooks/useSessionKey'; import { build_proof_transaction, build_blob as check_secret_blob } from 'hyle-check-secret'; import { BlobTransaction } from 'hyle'; import './SessionKeys.css'; +import { walletContractName } from 'hyle-wallet/src/types/wallet'; interface SessionKeysProps { wallet: Wallet; diff --git a/front/src/services/IndexerService.ts b/front/src/services/IndexerService.ts index 89fab26..29f7f62 100644 --- a/front/src/services/IndexerService.ts +++ b/front/src/services/IndexerService.ts @@ -1,5 +1,6 @@ import { IndexerApiHttpClient } from "hyle"; -import { Transaction, AuthMethod, walletContractName } from "../types/wallet"; +import { Transaction, AuthMethod } from "../types/wallet"; +import { walletContractName } from "hyle-wallet/src/types/wallet"; interface BalanceResponse { account: string; diff --git a/front/src/types/wallet.ts b/front/src/types/wallet.ts index d2a4aba..0119115 100644 --- a/front/src/types/wallet.ts +++ b/front/src/types/wallet.ts @@ -16,12 +16,7 @@ export interface Wallet { import { borshSerialize, BorshSchema, borshDeserialize } from "borsher"; import { Blob } from "hyle"; - -export let walletContractName = "wallet"; // Default value that will be updated - -export const setWalletContractName = (name: string) => { - walletContractName = name; -}; +import { walletContractName } from 'hyle-wallet/src/types/wallet'; // // Types From e5e19dccfa91b80c37b8e9c88ea6464e0f8c4cd0 Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Mon, 12 May 2025 18:58:01 +0200 Subject: [PATCH 07/17] remove useless --- hyle-wallet/src/services/IndexerService.ts | 80 ---------------------- 1 file changed, 80 deletions(-) delete mode 100644 hyle-wallet/src/services/IndexerService.ts diff --git a/hyle-wallet/src/services/IndexerService.ts b/hyle-wallet/src/services/IndexerService.ts deleted file mode 100644 index 89fab26..0000000 --- a/hyle-wallet/src/services/IndexerService.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { IndexerApiHttpClient } from "hyle"; -import { Transaction, AuthMethod, walletContractName } from "../types/wallet"; - -interface BalanceResponse { - account: string; - balance: number; -} - -interface TransactionHistoryResponse { - account: string; - history: Transaction[]; -} - -interface SessionKey { - key: string; - expiration_date: number; - nonce: number; -} - -interface AccountInfo { - account: string; - auth_method: AuthMethod; - session_keys: SessionKey[]; - nonce: number; -} - -class IndexerService { - client: IndexerApiHttpClient; - server: IndexerApiHttpClient; - - constructor() { - this.client = new IndexerApiHttpClient( - import.meta.env.VITE_INDEXER_BASE_URL, - ); - this.server = new IndexerApiHttpClient( - import.meta.env.VITE_SERVER_BASE_URL, - ); - } - - async getBalance(address: string): Promise { - try { - const response = await this.client.get( - `v1/indexer/contract/hyllar/balance/${address}`, - "Fetching balance", - ); - return response.balance; - } catch (error) { - console.error("Error while fetching the balance:", error); - return 0; - } - } - - async getTransactionHistory(address: string): Promise { - try { - const response = await this.server.get( - `v1/indexer/contract/hyllar/history/${address}`, - "Fetching transaction history", - ); - return response.history; - } catch (error) { - console.error("Error while fetching the transaction history:", error); - return []; - } - } - - async getAccountInfo(address: string): Promise { - try { - const response = await this.server.get( - `v1/indexer/contract/${walletContractName}/account/${address}`, - "Fetching account info", - ); - return response; - } catch (error) { - console.error("Error while fetching the account info:", error); - throw new Error('Failed to fetch account info'); - } - } -} - -export const indexerService = new IndexerService(); From d750d39da266e3d5c59abc6569b1dbc845353c85 Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Tue, 13 May 2025 10:25:02 +0200 Subject: [PATCH 08/17] Remove redundnacy in sessionkey management --- front/src/components/layout/WalletLayout.tsx | 2 +- front/src/components/wallet/Balance.tsx | 2 +- front/src/components/wallet/History.tsx | 2 +- front/src/components/wallet/Send.tsx | 2 +- front/src/components/wallet/SessionKeys.tsx | 2 +- front/src/hooks/useWalletTransactions.ts | 2 +- front/src/routes/routes.tsx | 2 +- front/src/types/wallet.ts | 185 ------------------- hyle-wallet/src/index.ts | 12 +- 9 files changed, 18 insertions(+), 193 deletions(-) delete mode 100644 front/src/types/wallet.ts diff --git a/front/src/components/layout/WalletLayout.tsx b/front/src/components/layout/WalletLayout.tsx index 0862d02..5b1d18b 100644 --- a/front/src/components/layout/WalletLayout.tsx +++ b/front/src/components/layout/WalletLayout.tsx @@ -1,5 +1,5 @@ import { Outlet, useNavigate, useLocation } from 'react-router-dom'; -import { Wallet } from '../../types/wallet'; +import { Wallet } from 'hyle-wallet/src'; interface WalletLayoutProps { wallet: Wallet; diff --git a/front/src/components/wallet/Balance.tsx b/front/src/components/wallet/Balance.tsx index 92db5d9..ad90569 100644 --- a/front/src/components/wallet/Balance.tsx +++ b/front/src/components/wallet/Balance.tsx @@ -1,4 +1,4 @@ -import { Wallet } from '../../types/wallet'; +import { Wallet } from 'hyle-wallet/src'; interface BalanceProps { wallet: Wallet; diff --git a/front/src/components/wallet/History.tsx b/front/src/components/wallet/History.tsx index 77ae81c..dc28174 100644 --- a/front/src/components/wallet/History.tsx +++ b/front/src/components/wallet/History.tsx @@ -1,4 +1,4 @@ -import { Transaction } from '../../types/wallet'; +import { Transaction } from 'hyle-wallet/src'; interface HistoryProps { transactions: Transaction[]; diff --git a/front/src/components/wallet/Send.tsx b/front/src/components/wallet/Send.tsx index 1678334..8ba34f0 100644 --- a/front/src/components/wallet/Send.tsx +++ b/front/src/components/wallet/Send.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { Transaction, verifyIdentity, Wallet } from '../../types/wallet'; +import { Transaction, verifyIdentity, Wallet } from 'hyle-wallet/src'; import { blob_builder, BlobTransaction } from 'hyle' import { build_proof_transaction, build_blob as check_secret_blob } from 'hyle-check-secret'; import { nodeService } from '../../services/NodeService'; diff --git a/front/src/components/wallet/SessionKeys.tsx b/front/src/components/wallet/SessionKeys.tsx index 009af65..62b75a7 100644 --- a/front/src/components/wallet/SessionKeys.tsx +++ b/front/src/components/wallet/SessionKeys.tsx @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react'; -import { Wallet, addSessionKey, removeSessionKey } from '../../types/wallet'; +import { Wallet, addSessionKey, removeSessionKey } from 'hyle-wallet/src'; import { nodeService } from '../../services/NodeService'; import { indexerService } from '../../services/IndexerService'; import { webSocketService } from '../../services/WebSocketService'; diff --git a/front/src/hooks/useWalletTransactions.ts b/front/src/hooks/useWalletTransactions.ts index 546b41c..123b8ae 100644 --- a/front/src/hooks/useWalletTransactions.ts +++ b/front/src/hooks/useWalletTransactions.ts @@ -1,5 +1,5 @@ import { useState, useEffect, useCallback } from 'react'; -import { Transaction } from '../types/wallet'; +import { Transaction } from 'hyle-wallet/src'; import { indexerService } from '../services/IndexerService'; import { AppEvent } from '../services/WebSocketService'; diff --git a/front/src/routes/routes.tsx b/front/src/routes/routes.tsx index b5e5b62..4f81d83 100644 --- a/front/src/routes/routes.tsx +++ b/front/src/routes/routes.tsx @@ -4,7 +4,7 @@ import { Send } from '../components/wallet/Send'; import { History } from '../components/wallet/History'; import { SessionKeys } from '../components/wallet/SessionKeys'; import { WalletLayout } from '../components/layout/WalletLayout'; -import { Wallet } from '../types/wallet'; +import { Wallet } from 'hyle-wallet/src'; // Route path constants export const ROUTES = { diff --git a/front/src/types/wallet.ts b/front/src/types/wallet.ts deleted file mode 100644 index 0119115..0000000 --- a/front/src/types/wallet.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { Buffer } from 'buffer'; - -export interface Transaction { - id: string; - type: string; - amount: number; - address: string; - status: string; - timestamp: number; -} - -export interface Wallet { - username: string; - address: string; -} - -import { borshSerialize, BorshSchema, borshDeserialize } from "borsher"; -import { Blob } from "hyle"; -import { walletContractName } from 'hyle-wallet/src/types/wallet'; - -// -// Types -// - -export type Secp256k1Blob = { - identity: String; - data: Uint8Array; - public_key: Uint8Array; - signature: Uint8Array; -}; - -export type AuthMethod = { - Password: { - hash: string; - }; -}; - -export type WalletAction = - | { - RegisterIdentity: { - account: string; - nonce: number; - auth_method: AuthMethod; - }; - } - | { - VerifyIdentity: { - nonce: number; - account: string; - }; - } - | { - AddSessionKey: { - account: string; - key: string; - expiration: number; - }; - } - | { - RemoveSessionKey: { - account: string; - key: string; - }; -} -| { - UseSessionKey: { - account: string; - key: string; - message: string; - }; - } - | { - UseSessionKey: { - account: string; - key: string; - message: string; - }; - }; - -// -// Builders -// - -export const register = (account: string, nonce: number, hash: string): Blob => { - const action: WalletAction = { - RegisterIdentity: { - account, - nonce, - auth_method: { Password: { hash } }, - }, - }; - const blob: Blob = { - contract_name: walletContractName, - data: serializeIdentityAction(action), - }; - return blob; -}; - -export const verifyIdentity = (account: string, nonce: number): Blob => { - const action: WalletAction = { - VerifyIdentity: { nonce, account }, - }; - - const blob: Blob = { - contract_name: walletContractName, - data: serializeIdentityAction(action), - }; - return blob; -}; - -export const addSessionKey = (account: string, key: string, expiration: number): Blob => { - const action: WalletAction = { - AddSessionKey: { account, key, expiration } - }; - const blob: Blob = { - contract_name: walletContractName, - data: serializeIdentityAction(action), - }; - return blob; -}; - -export const removeSessionKey = (account: string, key: string): Blob => { - const action: WalletAction = { - RemoveSessionKey: { account, key } - }; - const blob: Blob = { - contract_name: walletContractName, - data: serializeIdentityAction(action), - }; - return blob; -}; - -// Removed the `useSessionKey` function as it has been moved to `SessionKeyService`. - -// -// Serialisation -// - -export const serializeSecp256k1Blob = (blob: Secp256k1Blob): number[] => { - - return Array.from(borshSerialize(secp256k1BlobSchema, blob)); -}; - -export const serializeIdentityAction = (action: WalletAction): number[] => { - return Array.from(borshSerialize(schema, action)); -}; -export const deserializeIdentityAction = (data: number[]): WalletAction => { - return borshDeserialize(schema, Buffer.from(data)); -}; - -const secp256k1BlobSchema = BorshSchema.Struct({ - identity: BorshSchema.String, - data: BorshSchema.Array(BorshSchema.u8, 32), - public_key: BorshSchema.Array(BorshSchema.u8, 33), - signature: BorshSchema.Array(BorshSchema.u8, 64), -}); - -const schema = BorshSchema.Enum({ - RegisterIdentity: BorshSchema.Struct({ - account: BorshSchema.String, - nonce: BorshSchema.u128, - auth_method: BorshSchema.Enum({ - Password: BorshSchema.Struct({ - hash: BorshSchema.String, - }), - }), - }), - VerifyIdentity: BorshSchema.Struct({ - account: BorshSchema.String, - nonce: BorshSchema.u128, - }), - AddSessionKey: BorshSchema.Struct({ - account: BorshSchema.String, - key: BorshSchema.String, - expiration: BorshSchema.u128, - }), - RemoveSessionKey: BorshSchema.Struct({ - account: BorshSchema.String, - key: BorshSchema.String, - }), -UseSessionKey: BorshSchema.Struct({ - account: BorshSchema.String, - message: BorshSchema.String, - }), -}); diff --git a/hyle-wallet/src/index.ts b/hyle-wallet/src/index.ts index 2bdfd9b..fe7c222 100644 --- a/hyle-wallet/src/index.ts +++ b/hyle-wallet/src/index.ts @@ -7,7 +7,17 @@ import { ProviderOption } from './hooks/useWallet'; export { HyleWallet } from './components/HyleWallet'; export { PasswordAuthProvider } from './providers/PasswordAuthProvider'; export type { AuthProvider, AuthCredentials } from './types/auth'; -export type { Wallet, Transaction } from './types/wallet'; +export type { Wallet, WalletAction, Transaction } from './types/wallet'; +export { + register, + verifyIdentity, + addSessionKey, + removeSessionKey, + serializeSecp256k1Blob, + serializeIdentityAction, + deserializeIdentityAction, + setWalletContractName +} from './types/wallet'; export type { ProviderOption }; export { WalletProvider, useWallet } from './hooks/useWallet'; export { useSessionKey } from './hooks/useSessionKey'; From 522c71fa6d40a07218145e67a56cfa5aece4118a Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Tue, 13 May 2025 11:37:00 +0200 Subject: [PATCH 09/17] Do not store automatically session keys --- front/src/components/wallet/SessionKeys.tsx | 3 ++- hyle-wallet/src/hooks/useSessionKey.ts | 2 +- hyle-wallet/src/services/SessionKeyService.ts | 13 ++++--------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/front/src/components/wallet/SessionKeys.tsx b/front/src/components/wallet/SessionKeys.tsx index 62b75a7..dab9f2a 100644 --- a/front/src/components/wallet/SessionKeys.tsx +++ b/front/src/components/wallet/SessionKeys.tsx @@ -67,7 +67,8 @@ export const SessionKeys = ({ wallet }: SessionKeysProps) => { setTransactionHash(''); // Génère une nouvelle paire de clés - const publicKey = generateSessionKey(); + const [publicKey, privateKey] = generateSessionKey(); + localStorage.setItem(publicKey, privateKey); try { const identity = `${wallet.username}@${walletContractName}`; diff --git a/hyle-wallet/src/hooks/useSessionKey.ts b/hyle-wallet/src/hooks/useSessionKey.ts index c5cb0b7..ef84b91 100644 --- a/hyle-wallet/src/hooks/useSessionKey.ts +++ b/hyle-wallet/src/hooks/useSessionKey.ts @@ -4,7 +4,7 @@ import { sessionKeyService } from '../services/SessionKeyService'; import type { Blob } from 'hyle'; export const useSessionKey = () => { - const generateSessionKey = useCallback((): string => { + const generateSessionKey = useCallback((): [string, string] => { return sessionKeyService.generateSessionKey(); }, []); diff --git a/hyle-wallet/src/services/SessionKeyService.ts b/hyle-wallet/src/services/SessionKeyService.ts index e300260..df0b560 100644 --- a/hyle-wallet/src/services/SessionKeyService.ts +++ b/hyle-wallet/src/services/SessionKeyService.ts @@ -11,7 +11,7 @@ class SessionKeyService { this.ec = new EC.ec('secp256k1'); } - generateSessionKey(): string { + generateSessionKey(): [string, string] { // Génère une paire de clés ECDSA const keyPair = this.ec.genKeyPair(); @@ -25,16 +25,10 @@ class SessionKeyService { throw new Error('Failed to generate public key'); } - localStorage.setItem(publicKey, privateKey); - - return publicKey; + return [publicKey, privateKey]; } - getSignedBlob(identity: string, message: string, publicKey: string): Secp256k1Blob { - const privateKey = localStorage.getItem(publicKey); - if (!privateKey) { - throw new Error('No session key or provided private key available'); - } + getSignedBlob(identity: string, message: string, privateKey: string): Secp256k1Blob { const hash = SHA256(message); const hashBytes = Buffer.from(hash.toString(), 'hex'); @@ -43,6 +37,7 @@ class SessionKeyService { } const keyPair = this.ec.keyFromPrivate(privateKey); + const publicKey = keyPair.getPublic(true, 'hex'); const signature = keyPair.sign(hash.toString()); // Normaliser s en utilisant min(s, n-s) From b3cdd858b6341d851e90b73345bb2fc4a98bf053 Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Tue, 13 May 2025 11:50:40 +0200 Subject: [PATCH 10/17] forgot one --- front/src/services/WebSocketService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front/src/services/WebSocketService.ts b/front/src/services/WebSocketService.ts index 1c3a0f7..e87dc62 100644 --- a/front/src/services/WebSocketService.ts +++ b/front/src/services/WebSocketService.ts @@ -1,4 +1,4 @@ -import { Transaction } from "../types/wallet"; +import { Transaction } from 'hyle-wallet/src'; export interface AppEvent { TxEvent: { From 0f1fa1e05b34d77dc7a7d0e1b7134cb20d74a13e Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Tue, 13 May 2025 13:24:05 +0200 Subject: [PATCH 11/17] Remove ambiguity in env var name --- front/.env | 2 +- front/.env.production | 2 +- front/src/App.tsx | 2 +- front/src/components/WalletShowcase.tsx | 2 +- front/src/services/IndexerService.ts | 2 +- front/src/types/hyle-wallet-src.d.ts | 2 +- hyle-wallet/.env | 2 +- hyle-wallet/src/services/config.ts | 2 +- hyle-wallet/src/vite-env.d.ts | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/front/.env b/front/.env index d305c2d..bb4b3e7 100644 --- a/front/.env +++ b/front/.env @@ -1,4 +1,4 @@ -VITE_SERVER_BASE_URL=http://localhost:4000 +VITE_WALLET_SERVER_BASE_URL=http://localhost:4000 VITE_WS_URL=ws://localhost:8081/ws VITE_NODE_BASE_URL=http://localhost:4321 VITE_INDEXER_BASE_URL=http://localhost:4321 diff --git a/front/.env.production b/front/.env.production index fab04c2..7ae1e1d 100644 --- a/front/.env.production +++ b/front/.env.production @@ -1,4 +1,4 @@ -VITE_SERVER_BASE_URL=https://wallet.testnet.hyle.eu +VITE_WALLET_SERVER_BASE_URL=https://wallet.testnet.hyle.eu VITE_WS_URL=wss://wallet.testnet.hyle.eu/ws VITE_NODE_BASE_URL=https://node.testnet.hyle.eu VITE_INDEXER_BASE_URL=https://indexer.testnet.hyle.eu diff --git a/front/src/App.tsx b/front/src/App.tsx index 8052f21..e19f7d5 100644 --- a/front/src/App.tsx +++ b/front/src/App.tsx @@ -6,7 +6,7 @@ import { useWalletBalance } from './hooks/useWalletBalance'; import { useWalletTransactions } from './hooks/useWalletTransactions'; import { useWebSocketConnection } from './hooks/useWebSocketConnection'; import { getPublicRoutes, getProtectedRoutes, ROUTES } from './routes/routes'; -import { WalletProvider, useWallet } from '../../hyle-wallet/src'; +import { WalletProvider, useWallet } from 'hyle-wallet/src'; import { useConfig } from 'hyle-wallet/src/hooks/useConfig'; import { LoadingErrorState } from './components/common/LoadingErrorState'; diff --git a/front/src/components/WalletShowcase.tsx b/front/src/components/WalletShowcase.tsx index 9e52e01..b262ce5 100644 --- a/front/src/components/WalletShowcase.tsx +++ b/front/src/components/WalletShowcase.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { HyleWallet } from '../../../hyle-wallet/src'; +import { HyleWallet } from 'hyle-wallet/src'; import { useLocation } from 'react-router-dom'; type ProviderOption = 'password' | 'google' | 'github'; diff --git a/front/src/services/IndexerService.ts b/front/src/services/IndexerService.ts index 29f7f62..01e0249 100644 --- a/front/src/services/IndexerService.ts +++ b/front/src/services/IndexerService.ts @@ -34,7 +34,7 @@ class IndexerService { import.meta.env.VITE_INDEXER_BASE_URL, ); this.server = new IndexerApiHttpClient( - import.meta.env.VITE_SERVER_BASE_URL, + import.meta.env.VITE_WALLET_SERVER_BASE_URL, ); } diff --git a/front/src/types/hyle-wallet-src.d.ts b/front/src/types/hyle-wallet-src.d.ts index dcc19f2..3ade579 100644 --- a/front/src/types/hyle-wallet-src.d.ts +++ b/front/src/types/hyle-wallet-src.d.ts @@ -1,3 +1,3 @@ declare module '../../hyle-wallet/src' { export * from '../../../hyle-wallet/src'; -} \ No newline at end of file +} \ No newline at end of file diff --git a/hyle-wallet/.env b/hyle-wallet/.env index d305c2d..bb4b3e7 100644 --- a/hyle-wallet/.env +++ b/hyle-wallet/.env @@ -1,4 +1,4 @@ -VITE_SERVER_BASE_URL=http://localhost:4000 +VITE_WALLET_SERVER_BASE_URL=http://localhost:4000 VITE_WS_URL=ws://localhost:8081/ws VITE_NODE_BASE_URL=http://localhost:4321 VITE_INDEXER_BASE_URL=http://localhost:4321 diff --git a/hyle-wallet/src/services/config.ts b/hyle-wallet/src/services/config.ts index 959d085..ab53e17 100644 --- a/hyle-wallet/src/services/config.ts +++ b/hyle-wallet/src/services/config.ts @@ -4,7 +4,7 @@ interface Config { export async function fetchConfig(): Promise { const response = await fetch( - `${import.meta.env.VITE_SERVER_BASE_URL}/api/config`, + `${import.meta.env.VITE_WALLET_SERVER_BASE_URL}/api/config`, ); if (!response.ok) { throw new Error("Failed to fetch config"); diff --git a/hyle-wallet/src/vite-env.d.ts b/hyle-wallet/src/vite-env.d.ts index 3cbdabc..63df761 100644 --- a/hyle-wallet/src/vite-env.d.ts +++ b/hyle-wallet/src/vite-env.d.ts @@ -1,7 +1,7 @@ /// interface ImportMetaEnv { - readonly VITE_SERVER_BASE_URL: string; + readonly VITE_WALLET_SERVER_BASE_URL: string; readonly VITE_WS_URL: string; readonly VITE_NODE_BASE_URL: string; readonly VITE_INDEXER_BASE_URL: string; From 8163477662401071c61f5102633a865043e03d07 Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Tue, 13 May 2025 14:16:00 +0200 Subject: [PATCH 12/17] Remove ambiguity in env var name websocket --- front/.env | 2 +- front/.env.production | 2 +- front/src/services/WebSocketService.ts | 2 +- hyle-wallet/.env | 2 +- hyle-wallet/src/components/HyleWallet.css | 2 +- hyle-wallet/src/providers/PasswordAuthProvider.ts | 4 ---- hyle-wallet/src/services/WebSocketService.ts | 2 +- hyle-wallet/src/vite-env.d.ts | 2 +- 8 files changed, 7 insertions(+), 11 deletions(-) diff --git a/front/.env b/front/.env index bb4b3e7..6192b29 100644 --- a/front/.env +++ b/front/.env @@ -1,5 +1,5 @@ VITE_WALLET_SERVER_BASE_URL=http://localhost:4000 -VITE_WS_URL=ws://localhost:8081/ws +VITE_WALLET_WS_URL=ws://localhost:8081/ws VITE_NODE_BASE_URL=http://localhost:4321 VITE_INDEXER_BASE_URL=http://localhost:4321 VITE_TX_EXPLORER_URL=http://localhost:8000 diff --git a/front/.env.production b/front/.env.production index 7ae1e1d..7f51aad 100644 --- a/front/.env.production +++ b/front/.env.production @@ -1,5 +1,5 @@ VITE_WALLET_SERVER_BASE_URL=https://wallet.testnet.hyle.eu -VITE_WS_URL=wss://wallet.testnet.hyle.eu/ws +VITE_WALLET_WS_URL=wss://wallet.testnet.hyle.eu/ws VITE_NODE_BASE_URL=https://node.testnet.hyle.eu VITE_INDEXER_BASE_URL=https://indexer.testnet.hyle.eu VITE_TX_EXPLORER_URL=https://hyleou.hyle.eu/ diff --git a/front/src/services/WebSocketService.ts b/front/src/services/WebSocketService.ts index e87dc62..3ddc244 100644 --- a/front/src/services/WebSocketService.ts +++ b/front/src/services/WebSocketService.ts @@ -40,7 +40,7 @@ export class WebSocketService { } this.currentAccount = account; - this.ws = new WebSocket(import.meta.env.VITE_WS_URL); + this.ws = new WebSocket(import.meta.env.VITE_WALLET_WS_URL); this.ws.onopen = () => { console.log("WebSocket connected"); diff --git a/hyle-wallet/.env b/hyle-wallet/.env index bb4b3e7..6192b29 100644 --- a/hyle-wallet/.env +++ b/hyle-wallet/.env @@ -1,5 +1,5 @@ VITE_WALLET_SERVER_BASE_URL=http://localhost:4000 -VITE_WS_URL=ws://localhost:8081/ws +VITE_WALLET_WS_URL=ws://localhost:8081/ws VITE_NODE_BASE_URL=http://localhost:4321 VITE_INDEXER_BASE_URL=http://localhost:4321 VITE_TX_EXPLORER_URL=http://localhost:8000 diff --git a/hyle-wallet/src/components/HyleWallet.css b/hyle-wallet/src/components/HyleWallet.css index 163f2d2..5130160 100644 --- a/hyle-wallet/src/components/HyleWallet.css +++ b/hyle-wallet/src/components/HyleWallet.css @@ -52,7 +52,7 @@ display: flex; align-items: center; justify-content: center; - z-index: 1000; + z-index: 999999; animation: fadeIn var(--anim-normal) var(--anim-ease); } diff --git a/hyle-wallet/src/providers/PasswordAuthProvider.ts b/hyle-wallet/src/providers/PasswordAuthProvider.ts index 99353a3..2c7330e 100644 --- a/hyle-wallet/src/providers/PasswordAuthProvider.ts +++ b/hyle-wallet/src/providers/PasswordAuthProvider.ts @@ -35,8 +35,6 @@ export class PasswordAuthProvider implements AuthProvider { blobs: [blob0, blob1], }; - console.log('Blob transaction:', blobTx); - const tx_hash = await nodeService.client.sendBlobTx(blobTx); // Optimistic notification to the caller that the blobTx has been sent successfully @@ -123,8 +121,6 @@ export class PasswordAuthProvider implements AuthProvider { blobs: [blob0, blob1], }; - console.log('Blob transaction:', blobTx); - await register_contract(nodeService.client as any); const tx_hash = await nodeService.client.sendBlobTx(blobTx); diff --git a/hyle-wallet/src/services/WebSocketService.ts b/hyle-wallet/src/services/WebSocketService.ts index 1c3a0f7..f169218 100644 --- a/hyle-wallet/src/services/WebSocketService.ts +++ b/hyle-wallet/src/services/WebSocketService.ts @@ -40,7 +40,7 @@ export class WebSocketService { } this.currentAccount = account; - this.ws = new WebSocket(import.meta.env.VITE_WS_URL); + this.ws = new WebSocket(import.meta.env.VITE_WALLET_WS_URL); this.ws.onopen = () => { console.log("WebSocket connected"); diff --git a/hyle-wallet/src/vite-env.d.ts b/hyle-wallet/src/vite-env.d.ts index 63df761..b5a5ac6 100644 --- a/hyle-wallet/src/vite-env.d.ts +++ b/hyle-wallet/src/vite-env.d.ts @@ -2,7 +2,7 @@ interface ImportMetaEnv { readonly VITE_WALLET_SERVER_BASE_URL: string; - readonly VITE_WS_URL: string; + readonly VITE_WALLET_WS_URL: string; readonly VITE_NODE_BASE_URL: string; readonly VITE_INDEXER_BASE_URL: string; readonly VITE_TX_EXPLORER_URL: string; From 4a08130da4000c9b9338aa350930b9bddfbe27ca Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Tue, 13 May 2025 14:59:52 +0200 Subject: [PATCH 13/17] persist wallet state --- hyle-wallet/src/hooks/useWallet.tsx | 15 +++++++++++++-- hyle-wallet/src/types/wallet.ts | 16 +++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/hyle-wallet/src/hooks/useWallet.tsx b/hyle-wallet/src/hooks/useWallet.tsx index 30777bb..64588ab 100644 --- a/hyle-wallet/src/hooks/useWallet.tsx +++ b/hyle-wallet/src/hooks/useWallet.tsx @@ -20,15 +20,26 @@ interface WalletContextType { const WalletContext = createContext(undefined); export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { - const [wallet, setWallet] = useState(null); + const [wallet, setWallet] = useState(() => { + const storedWallet = localStorage.getItem('wallet'); + return storedWallet ? JSON.parse(storedWallet) : null; + }); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [stage, setStage] = useState('idle'); + // Persist wallet when updated + React.useEffect(() => { + if (wallet) { + localStorage.setItem('wallet', JSON.stringify(wallet)); + } + }, [wallet]); + const clear = () => { setWallet(null); setError(null); setStage('idle'); + localStorage.removeItem('wallet'); }; const login = useCallback(async (provider: ProviderOption, credentials: AuthCredentials) => { @@ -122,4 +133,4 @@ export const useWallet = (): WalletContextType => { throw new Error('useWallet must be used within a WalletProvider'); } return ctx; -}; \ No newline at end of file +}; \ No newline at end of file diff --git a/hyle-wallet/src/types/wallet.ts b/hyle-wallet/src/types/wallet.ts index d2a4aba..0b72927 100644 --- a/hyle-wallet/src/types/wallet.ts +++ b/hyle-wallet/src/types/wallet.ts @@ -135,7 +135,21 @@ export const removeSessionKey = (account: string, key: string): Blob => { return blob; }; -// Removed the `useSessionKey` function as it has been moved to `SessionKeyService`. +// Store wallet in localStorage +export const storeWallet = (wallet: Wallet) => { + localStorage.setItem('wallet', JSON.stringify(wallet)); +}; + +// Get wallet from localStorage +export const getStoredWallet = (): Wallet | null => { + const storedWallet = localStorage.getItem('wallet'); + return storedWallet ? JSON.parse(storedWallet) : null; +}; + +// Clear wallet from localStorage +export const clearStoredWallet = () => { + localStorage.removeItem('wallet'); +}; // // Serialisation From b7a32201cee9442c6ddce1c13f4b9ecf120bdd5f Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Tue, 13 May 2025 15:31:39 +0200 Subject: [PATCH 14/17] fix wrong key --- front/src/components/wallet/SessionKeys.tsx | 9 +++++++-- hyle-wallet/src/hooks/useSessionKey.ts | 4 ++-- hyle-wallet/src/services/SessionKeyService.ts | 7 +++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/front/src/components/wallet/SessionKeys.tsx b/front/src/components/wallet/SessionKeys.tsx index dab9f2a..1cb3afc 100644 --- a/front/src/components/wallet/SessionKeys.tsx +++ b/front/src/components/wallet/SessionKeys.tsx @@ -173,15 +173,20 @@ export const SessionKeys = ({ wallet }: SessionKeysProps) => { } }; - const handleSendTransactionWithSessionKey = async (key: string) => { + const handleSendTransactionWithSessionKey = async (publicKey: string) => { setIsLoading(true); setError(''); setStatus('Sending transaction...'); setTransactionHash(''); try { + const identity = `${wallet.username}@${walletContractName}`; - const [blob0, blob1] = createSignedBlobs(wallet.username, key, "Hello world!"); + const privateKey = localStorage.getItem(publicKey); + if (!privateKey) { + throw new Error('Private key not found in local storage'); + } + const [blob0, blob1] = createSignedBlobs(wallet.username, publicKey, privateKey, "Hello world!"); const blobTx: BlobTransaction = { identity, diff --git a/hyle-wallet/src/hooks/useSessionKey.ts b/hyle-wallet/src/hooks/useSessionKey.ts index ef84b91..e2e6dc5 100644 --- a/hyle-wallet/src/hooks/useSessionKey.ts +++ b/hyle-wallet/src/hooks/useSessionKey.ts @@ -12,8 +12,8 @@ export const useSessionKey = () => { sessionKeyService.clear(publicKey); }, []); - const createSignedBlobs = useCallback((account: string, key: string, message: string): [Blob, Blob] => { - return sessionKeyService.useSessionKey(account, key, message); + const createSignedBlobs = useCallback((account: string, publicKey: string, privateKey: string, message: string): [Blob, Blob] => { + return sessionKeyService.useSessionKey(account, publicKey, privateKey, message); }, []); return { diff --git a/hyle-wallet/src/services/SessionKeyService.ts b/hyle-wallet/src/services/SessionKeyService.ts index df0b560..6de9853 100644 --- a/hyle-wallet/src/services/SessionKeyService.ts +++ b/hyle-wallet/src/services/SessionKeyService.ts @@ -55,17 +55,16 @@ class SessionKeyService { public_key: new Uint8Array(Buffer.from(publicKey, 'hex')), signature: signatureBytes, }; - console.log('secp256k1Blob', secp256k1Blob); return secp256k1Blob; } - useSessionKey(account: string, key: string, message: string): [Blob, Blob] { + useSessionKey(account: string, public_key: string, privateKey: string, message: string): [Blob, Blob] { const action: WalletAction = { - UseSessionKey: { account, key, message } + UseSessionKey: { account, key: public_key, message } }; const identity = `${account}@${walletContractName}`; - const secp256k1Blob: Secp256k1Blob = this.getSignedBlob(identity, message, key); + const secp256k1Blob: Secp256k1Blob = this.getSignedBlob(identity, message, privateKey); const blob0: Blob = { contract_name: "secp256k1", data: serializeSecp256k1Blob(secp256k1Blob), From 4558b85fd13a7c187542f7e54efd6ff00aa23f26 Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Tue, 13 May 2025 16:09:52 +0200 Subject: [PATCH 15/17] useless pub key --- front/src/components/wallet/SessionKeys.tsx | 2 +- hyle-wallet/src/hooks/useSessionKey.ts | 4 ++-- hyle-wallet/src/services/SessionKeyService.ts | 6 ++++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/front/src/components/wallet/SessionKeys.tsx b/front/src/components/wallet/SessionKeys.tsx index 1cb3afc..9f1a985 100644 --- a/front/src/components/wallet/SessionKeys.tsx +++ b/front/src/components/wallet/SessionKeys.tsx @@ -186,7 +186,7 @@ export const SessionKeys = ({ wallet }: SessionKeysProps) => { if (!privateKey) { throw new Error('Private key not found in local storage'); } - const [blob0, blob1] = createSignedBlobs(wallet.username, publicKey, privateKey, "Hello world!"); + const [blob0, blob1] = createSignedBlobs(wallet.username, privateKey, "Hello world!"); const blobTx: BlobTransaction = { identity, diff --git a/hyle-wallet/src/hooks/useSessionKey.ts b/hyle-wallet/src/hooks/useSessionKey.ts index e2e6dc5..9e359bf 100644 --- a/hyle-wallet/src/hooks/useSessionKey.ts +++ b/hyle-wallet/src/hooks/useSessionKey.ts @@ -12,8 +12,8 @@ export const useSessionKey = () => { sessionKeyService.clear(publicKey); }, []); - const createSignedBlobs = useCallback((account: string, publicKey: string, privateKey: string, message: string): [Blob, Blob] => { - return sessionKeyService.useSessionKey(account, publicKey, privateKey, message); + const createSignedBlobs = useCallback((account: string, privateKey: string, message: string): [Blob, Blob] => { + return sessionKeyService.useSessionKey(account, privateKey, message); }, []); return { diff --git a/hyle-wallet/src/services/SessionKeyService.ts b/hyle-wallet/src/services/SessionKeyService.ts index 6de9853..41c6760 100644 --- a/hyle-wallet/src/services/SessionKeyService.ts +++ b/hyle-wallet/src/services/SessionKeyService.ts @@ -58,9 +58,11 @@ class SessionKeyService { return secp256k1Blob; } - useSessionKey(account: string, public_key: string, privateKey: string, message: string): [Blob, Blob] { + useSessionKey(account: string, privateKey: string, message: string): [Blob, Blob] { + const publicKey = this.ec.keyFromPrivate(privateKey).getPublic(true, 'hex'); + const action: WalletAction = { - UseSessionKey: { account, key: public_key, message } + UseSessionKey: { account, key: publicKey, message } }; const identity = `${account}@${walletContractName}`; From 14308e902d0b97672b0d56674e6c47e4a6605687 Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Tue, 13 May 2025 17:01:19 +0200 Subject: [PATCH 16/17] Button text reactive --- hyle-wallet/src/components/HyleWallet.tsx | 19 ++++++++++++------- hyle-wallet/src/hooks/useWallet.tsx | 12 ++++-------- hyle-wallet/src/index.ts | 1 + hyle-wallet/src/services/SessionKeyService.ts | 2 +- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/hyle-wallet/src/components/HyleWallet.tsx b/hyle-wallet/src/components/HyleWallet.tsx index dc18016..af75152 100644 --- a/hyle-wallet/src/components/HyleWallet.tsx +++ b/hyle-wallet/src/components/HyleWallet.tsx @@ -56,7 +56,15 @@ export const HyleWallet = ({ const [selectedProvider, setSelectedProvider] = useState(null); const [showLogin, setShowLogin] = useState(true); // true = login (default), false = create/sign-up const { isLoading: isLoadingConfig, error: configError } = useConfig(); - const { wallet } = useWallet(); + const { wallet, logout } = useWallet(); + + const handleButtonClick = () => { + if (wallet) { + logout(); + } else { + setIsOpen(true); + } + }; // Get available providers dynamically const availableProviders = authProviderManager.getAvailableProviders() as ProviderOption[]; @@ -68,8 +76,6 @@ export const HyleWallet = ({ } }, [wallet, isOpen]); - const openModal = () => setIsOpen(true); - const closeModal = () => { setIsOpen(false); setSelectedProvider(null); @@ -83,7 +89,6 @@ export const HyleWallet = ({ if (configError) { return
Error loading configuration: {configError}
; } - const renderProviderButton = (providerType: ProviderOption) => { const provider = authProviderManager.getProvider(providerType); @@ -120,10 +125,10 @@ export const HyleWallet = ({ return ( <> {button ? ( - button({ onClick: openModal }) + button({ onClick: handleButtonClick }) ) : ( - )} diff --git a/hyle-wallet/src/hooks/useWallet.tsx b/hyle-wallet/src/hooks/useWallet.tsx index 64588ab..4343038 100644 --- a/hyle-wallet/src/hooks/useWallet.tsx +++ b/hyle-wallet/src/hooks/useWallet.tsx @@ -35,13 +35,6 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr } }, [wallet]); - const clear = () => { - setWallet(null); - setError(null); - setStage('idle'); - localStorage.removeItem('wallet'); - }; - const login = useCallback(async (provider: ProviderOption, credentials: AuthCredentials) => { const authProvider = authProviderManager.getProvider(provider); if (!authProvider) { @@ -117,7 +110,10 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr }, []); const logout = useCallback(() => { - clear(); + localStorage.removeItem('wallet'); + setWallet(null); + setError(null); + setStage('idle'); }, []); return ( diff --git a/hyle-wallet/src/index.ts b/hyle-wallet/src/index.ts index fe7c222..c60e12a 100644 --- a/hyle-wallet/src/index.ts +++ b/hyle-wallet/src/index.ts @@ -21,6 +21,7 @@ export { export type { ProviderOption }; export { WalletProvider, useWallet } from './hooks/useWallet'; export { useSessionKey } from './hooks/useSessionKey'; +export { sessionKeyService } from './services/SessionKeyService'; // Register the Web Component class HyleWalletElement extends HTMLElement { diff --git a/hyle-wallet/src/services/SessionKeyService.ts b/hyle-wallet/src/services/SessionKeyService.ts index 41c6760..ea22d7a 100644 --- a/hyle-wallet/src/services/SessionKeyService.ts +++ b/hyle-wallet/src/services/SessionKeyService.ts @@ -4,7 +4,7 @@ import { Secp256k1Blob, serializeIdentityAction, serializeSecp256k1Blob, WalletA import { Buffer } from 'buffer'; import { Blob } from "hyle"; -class SessionKeyService { +export class SessionKeyService { private ec: EC.ec; constructor() { From d5d8e98a1007ee32513b84c2126aee842be38946 Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Tue, 13 May 2025 18:21:39 +0200 Subject: [PATCH 17/17] Proper way to build + import hyle-wallet --- front/bun.lockb | Bin 106476 -> 132551 bytes front/package.json | 27 +- front/src/App.tsx | 4 +- front/src/components/WalletShowcase.tsx | 2 +- front/src/components/layout/WalletLayout.tsx | 2 +- front/src/components/wallet/Balance.tsx | 2 +- front/src/components/wallet/History.tsx | 2 +- front/src/components/wallet/Send.tsx | 2 +- front/src/components/wallet/SessionKeys.tsx | 5 +- front/src/hooks/useWalletTransactions.ts | 2 +- front/src/routes/routes.tsx | 4 +- front/src/services/IndexerService.ts | 3 +- front/src/services/WebSocketService.ts | 2 +- front/src/types/hyle-wallet-src.d.ts | 3 - front/src/types/hyle-wallet.d.ts | 39 - hyle-wallet/bun.lockb | Bin 135409 -> 162830 bytes hyle-wallet/index.css | 23 - hyle-wallet/index.html | 12 - hyle-wallet/lib.ts | 18 + hyle-wallet/package-lock.json | 4732 ------------------ hyle-wallet/package.json | 40 +- hyle-wallet/src/index.ts | 29 +- hyle-wallet/tsconfig.app.json | 26 - hyle-wallet/tsconfig.json | 25 +- hyle-wallet/tsconfig.node.json | 24 - hyle-wallet/vite.config.ts | 42 +- 26 files changed, 130 insertions(+), 4940 deletions(-) delete mode 100644 front/src/types/hyle-wallet-src.d.ts delete mode 100644 front/src/types/hyle-wallet.d.ts delete mode 100644 hyle-wallet/index.css delete mode 100644 hyle-wallet/index.html create mode 100644 hyle-wallet/lib.ts delete mode 100644 hyle-wallet/package-lock.json delete mode 100644 hyle-wallet/tsconfig.app.json delete mode 100644 hyle-wallet/tsconfig.node.json diff --git a/front/bun.lockb b/front/bun.lockb index 79dbcadef4734cb9f8ee28c1d0c9e8e59da66490..b09b2115aa01f48874fd80ccf206d7e449ce133e 100755 GIT binary patch literal 132551 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 }, ], }, -]; \ No newline at end of file +]; \ No newline at end of file diff --git a/front/src/services/IndexerService.ts b/front/src/services/IndexerService.ts index 01e0249..b35814d 100644 --- a/front/src/services/IndexerService.ts +++ b/front/src/services/IndexerService.ts @@ -1,6 +1,5 @@ import { IndexerApiHttpClient } from "hyle"; -import { Transaction, AuthMethod } from "../types/wallet"; -import { walletContractName } from "hyle-wallet/src/types/wallet"; +import { Transaction, AuthMethod, walletContractName } from "hyle-wallet"; interface BalanceResponse { account: string; diff --git a/front/src/services/WebSocketService.ts b/front/src/services/WebSocketService.ts index 3ddc244..2a20420 100644 --- a/front/src/services/WebSocketService.ts +++ b/front/src/services/WebSocketService.ts @@ -1,4 +1,4 @@ -import { Transaction } from 'hyle-wallet/src'; +import { Transaction } from 'hyle-wallet'; export interface AppEvent { TxEvent: { diff --git a/front/src/types/hyle-wallet-src.d.ts b/front/src/types/hyle-wallet-src.d.ts deleted file mode 100644 index 3ade579..0000000 --- a/front/src/types/hyle-wallet-src.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare module '../../hyle-wallet/src' { - export * from '../../../hyle-wallet/src'; -} \ No newline at end of file diff --git a/front/src/types/hyle-wallet.d.ts b/front/src/types/hyle-wallet.d.ts deleted file mode 100644 index e0d1bc2..0000000 --- a/front/src/types/hyle-wallet.d.ts +++ /dev/null @@ -1,39 +0,0 @@ -declare module 'hyle-wallet' { - import * as React from 'react'; - import type { Wallet } from './wallet'; - - export type ProviderOption = 'password' | 'google' | 'github' | 'x'; - - export interface HyleWalletProps { - providers?: ProviderOption[]; - button?: (props: { onClick: () => void }) => React.ReactNode; - onWalletConnected?: (wallet: Wallet) => void; - } - - export const HyleWallet: React.FC; - - export interface WalletProviderProps { - children: React.ReactNode; - } - - export const WalletProvider: React.FC; - - export interface UseWalletReturn { - wallet: Wallet | null; - isLoading: boolean; - error: string | null; - login: (provider: ProviderOption, credentials: any) => Promise; - register: (provider: ProviderOption, credentials: any) => Promise; - logout: () => void; - } - - export function useWallet(): UseWalletReturn; - - export interface UseSessionKeyReturn { - generateSessionKey: () => string; - clearSessionKey: (publicKey: string) => void; - createSignedBlobs: (account: string, key: string, message: string) => [any, any]; - } - - export function useSessionKey(): UseSessionKeyReturn; -} \ No newline at end of file diff --git a/hyle-wallet/bun.lockb b/hyle-wallet/bun.lockb index 1a699a47f19498e3e0c9a41623a3fa070396d8a7..55de28aa2147a08aa64417e1a4d9648a88f9c388 100755 GIT binary patch delta 45873 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 z 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 - - - - - HyleWallet Demo - - - - - - \ No newline at end of file diff --git a/hyle-wallet/lib.ts b/hyle-wallet/lib.ts new file mode 100644 index 0000000..7532e3a --- /dev/null +++ b/hyle-wallet/lib.ts @@ -0,0 +1,18 @@ +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import { HyleWallet } from './src/components/HyleWallet'; +import type { ProviderOption } from './src/hooks/useWallet'; + +class HyleWalletElement extends HTMLElement { + connectedCallback() { + const mountPoint = document.createElement('div'); + this.appendChild(mountPoint); + + const providersAttr = this.getAttribute('providers'); + const providers = providersAttr ? providersAttr.split(',') as ProviderOption[] : ["password" as ProviderOption]; + + createRoot(mountPoint).render(React.createElement(HyleWallet, { providers })); + } +} + +customElements.define('hyle-wallet', HyleWalletElement); diff --git a/hyle-wallet/package-lock.json b/hyle-wallet/package-lock.json deleted file mode 100644 index 302f317..0000000 --- a/hyle-wallet/package-lock.json +++ /dev/null @@ -1,4732 +0,0 @@ -{ - "name": "hyle-wallet", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "hyle-wallet", - "version": "1.0.0", - "dependencies": { - "@types/crypto-js": "^4.2.2", - "@types/elliptic": "^6.4.18", - "@types/react-router-dom": "^5.3.3", - "crypto-js": "^4.2.0", - "elliptic": "^6.6.1", - "hyle": "^0.2.5", - "hyle-check-secret": "^0.3.2", - "react": "^19.1.0", - "react-dom": "^19.1.0", - "react-router-dom": "^7.5.0" - }, - "devDependencies": { - "@eslint/js": "^9.24.0", - "@types/react": "^19.1.3", - "@types/react-dom": "^19.1.4", - "@vitejs/plugin-react": "^4.4.0", - "autoprefixer": "^10.4.21", - "eslint": "^9.24.0", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.19", - "globals": "^15.15.0", - "postcss": "^8.5.3", - "tailwindcss": "^4.1.4", - "typescript": "~5.7.3", - "typescript-eslint": "^8.30.1", - "vite": "^6.2.6" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@aztec/bb.js": { - "version": "0.82.2", - "resolved": "https://registry.npmjs.org/@aztec/bb.js/-/bb.js-0.82.2.tgz", - "integrity": "sha512-MBOHFVHOtfsknyJ1IsHH30paYqf0qLwYkiDTPyH1/KtkMwemvo5VyIgY0Dsl81KQa388MzoKhC6qnaFgERiaog==", - "license": "MIT", - "dependencies": { - "comlink": "^4.4.1", - "commander": "^12.1.0", - "debug": "^4.3.4", - "fflate": "^0.8.0", - "pako": "^2.1.0", - "tslib": "^2.4.0" - }, - "bin": { - "bb.js": "dest/node/main.js" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz", - "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz", - "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.1", - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helpers": "^7.27.1", - "@babel/parser": "^7.27.1", - "@babel/template": "^7.27.1", - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1", - "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/generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz", - "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.27.1", - "@babel/types": "^7.27.1", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz", - "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz", - "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", - "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.27.1" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz", - "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.1", - "@babel/parser": "^7.27.1", - "@babel/template": "^7.27.1", - "@babel/types": "^7.27.1", - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/types": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", - "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", - "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", - "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", - "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", - "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", - "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", - "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", - "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", - "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", - "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", - "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", - "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", - "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", - "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", - "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", - "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", - "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", - "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", - "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", - "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", - "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", - "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", - "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", - "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", - "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", - "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/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, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", - "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", - "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/core": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", - "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", - "dev": true, - "license": "MIT", - "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/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "9.26.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.26.0.tgz", - "integrity": "sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", - "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.13.0", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", - "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.3.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "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, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dev": true, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "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==", - "dev": true, - "license": "MIT" - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.2.tgz", - "integrity": "sha512-H9vwztj5OAqHg9GockCQC06k1natgcxWQSRpQcPJf6i5+MWBzfKkRtxGbjQf0X2ihii0ffLZCRGbYV2f2bjNCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.3", - "eventsource": "^3.0.2", - "express": "^5.0.1", - "express-rate-limit": "^7.5.0", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.23.8", - "zod-to-json-schema": "^3.24.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, - "license": "MIT", - "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, - "license": "MIT", - "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, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@noir-lang/acvm_js": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/@noir-lang/acvm_js/-/acvm_js-1.0.0-beta.2.tgz", - "integrity": "sha512-vZYidnNS0MGRddggrq73Te0MiOb7j7ehZwM5L0dbxGwG6RqUNU+RDjG/TE7VUHOOFkZGY20lQqjHY1mj4pOH2A==", - "license": "MIT" - }, - "node_modules/@noir-lang/noir_js": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/@noir-lang/noir_js/-/noir_js-1.0.0-beta.2.tgz", - "integrity": "sha512-CiHnU5H1tUQHoKheHh93Ss7DJificdjXFUUfdasjMd8lsCMCPqY/oUoG4FZjWb7mWT8h0d/qcpGKMbs1VkBThQ==", - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "@noir-lang/acvm_js": "1.0.0-beta.2", - "@noir-lang/noirc_abi": "1.0.0-beta.2", - "@noir-lang/types": "1.0.0-beta.2" - } - }, - "node_modules/@noir-lang/noir_wasm": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/@noir-lang/noir_wasm/-/noir_wasm-1.0.0-beta.2.tgz", - "integrity": "sha512-B6zn1mgKBIDZE4nGvl6sOgErg7VsZOjP2D4FPHlHj4QF7h7ZbaISJ3+NM38FolaRkGEm2sSmSonaqKum0DchRA==", - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "@noir-lang/types": "1.0.0-beta.2", - "pako": "^2.1.0" - } - }, - "node_modules/@noir-lang/noirc_abi": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/@noir-lang/noirc_abi/-/noirc_abi-1.0.0-beta.2.tgz", - "integrity": "sha512-8/Pc6C0IY4F3UCsubs96G4Nwalzo49TVW+2jej7uNaEJB7LCqbOk5G641XGcCV2McS7n7WbLt1eN3cKJrxUWrA==", - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "@noir-lang/types": "1.0.0-beta.2" - } - }, - "node_modules/@noir-lang/types": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/@noir-lang/types/-/types-1.0.0-beta.2.tgz", - "integrity": "sha512-0CosvfeAhwjmEt5cwJtEbju+8itRpmOUOmyt6TUo6JcRxaR8d4A+7j0sOgGxs2KVqWnMi1akJdGodAu0e4H+1A==", - "license": "(MIT OR Apache-2.0)" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz", - "integrity": "sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.2.tgz", - "integrity": "sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.2.tgz", - "integrity": "sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.2.tgz", - "integrity": "sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.2.tgz", - "integrity": "sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.2.tgz", - "integrity": "sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.2.tgz", - "integrity": "sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.2.tgz", - "integrity": "sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.2.tgz", - "integrity": "sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.2.tgz", - "integrity": "sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.2.tgz", - "integrity": "sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.2.tgz", - "integrity": "sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.2.tgz", - "integrity": "sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.2.tgz", - "integrity": "sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.2.tgz", - "integrity": "sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.2.tgz", - "integrity": "sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.2.tgz", - "integrity": "sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.2.tgz", - "integrity": "sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.2.tgz", - "integrity": "sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz", - "integrity": "sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "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, - "license": "MIT", - "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.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, - "license": "MIT", - "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, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", - "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/bn.js": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz", - "integrity": "sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/crypto-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz", - "integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==", - "license": "MIT" - }, - "node_modules/@types/elliptic": { - "version": "6.4.18", - "resolved": "https://registry.npmjs.org/@types/elliptic/-/elliptic-6.4.18.tgz", - "integrity": "sha512-UseG6H5vjRiNpQvrhy4VF/JXdA3V/Fp5amvveaL+fs28BZ6xIKJBPnUPRlEaZpysD9MbpfaLi8lbl7PGUAkpWw==", - "license": "MIT", - "dependencies": { - "@types/bn.js": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/history": { - "version": "4.7.11", - "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", - "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", - "license": "MIT" - }, - "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, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "22.15.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz", - "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/react": { - "version": "19.1.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.3.tgz", - "integrity": "sha512-dLWQ+Z0CkIvK1J8+wrDPwGxEYFA4RAyHoZPxHVGspYmFVnwGSNT24cGIhFJrtfRnWVuW8X7NO52gCXmhkVUWGQ==", - "license": "MIT", - "dependencies": { - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.1.4", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.4.tgz", - "integrity": "sha512-WxYAszDYgsMV31OVyoG4jbAgJI1Gw0Xq9V19zwhy6+hUUJlJIdZ3r/cbdmTqFv++SktQkZ/X+46yGFxp5XJBEg==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^19.0.0" - } - }, - "node_modules/@types/react-router": { - "version": "5.1.20", - "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", - "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", - "license": "MIT", - "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*" - } - }, - "node_modules/@types/react-router-dom": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", - "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", - "license": "MIT", - "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.0.tgz", - "integrity": "sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/type-utils": "8.32.0", - "@typescript-eslint/utils": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.0.tgz", - "integrity": "sha512-B2MdzyWxCE2+SqiZHAjPphft+/2x2FlO9YBx7eKE1BCb+rqBlQdhtAEhzIEdozHd55DXPmxBdpMygFJjfjjA9A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/typescript-estree": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.0.tgz", - "integrity": "sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.0.tgz", - "integrity": "sha512-t2vouuYQKEKSLtJaa5bB4jHeha2HJczQ6E5IXPDPgIty9EqcJxpr1QHQ86YyIPwDwxvUmLfP2YADQ5ZY4qddZg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "8.32.0", - "@typescript-eslint/utils": "8.32.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.0.tgz", - "integrity": "sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.0.tgz", - "integrity": "sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/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, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/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, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.0.tgz", - "integrity": "sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/typescript-estree": "8.32.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.0.tgz", - "integrity": "sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.32.0", - "eslint-visitor-keys": "^4.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@vitejs/plugin-react": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz", - "integrity": "sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.26.10", - "@babel/plugin-transform-react-jsx-self": "^7.25.9", - "@babel/plugin-transform-react-jsx-source": "^7.25.9", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" - } - }, - "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "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, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.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, - "license": "MIT", - "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/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, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/autoprefixer": { - "version": "10.4.21", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", - "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "browserslist": "^4.24.4", - "caniuse-lite": "^1.0.30001702", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.1.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.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, - "license": "MIT" - }, - "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==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.0", - "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", - "on-finished": "^2.4.1", - "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/borsh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/borsh/-/borsh-2.0.0.tgz", - "integrity": "sha512-kc9+BgR3zz9+cjbwM8ODoUB4fs3X3I5A/HtX7LZKxCLaMrEeDFoBpnhZY//DTS1VZBSs6S5v46RZRbZjRFspEg==", - "license": "Apache-2.0" - }, - "node_modules/borsher": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/borsher/-/borsher-3.6.0.tgz", - "integrity": "sha512-FMMQST0PdrhernqtxHGvq9wIgV6rJkJecfVs7VhL5jYCFFLsXGMn/VtY0s5zotkKHrrdS5Np/DoL2FTR4cdoqw==", - "license": "MIT", - "dependencies": { - "borsh": "^2.0.0", - "buffer": "^6.0.3" - } - }, - "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, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "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, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", - "license": "MIT" - }, - "node_modules/browserslist": { - "version": "4.24.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", - "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", - "dev": true, - "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" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001716", - "electron-to-chromium": "^1.5.149", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001717", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001717.tgz", - "integrity": "sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==", - "dev": true, - "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" - } - ], - "license": "CC-BY-4.0" - }, - "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, - "license": "MIT", - "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/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, - "license": "MIT", - "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, - "license": "MIT" - }, - "node_modules/comlink": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/comlink/-/comlink-4.4.2.tgz", - "integrity": "sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g==", - "license": "Apache-2.0" - }, - "node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "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, - "license": "MIT" - }, - "node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", - "dev": true, - "license": "MIT", - "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, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "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, - "license": "MIT" - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", - "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", - "license": "MIT" - }, - "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/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": 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, - "license": "MIT" - }, - "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, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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, - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.151", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.151.tgz", - "integrity": "sha512-Rl6uugut2l9sLojjS4H4SAr3A4IgACMLgpuEMPYCVcKydzfyPrn5absNRju38IhQOf/NwjJY8OGWjlteqYeBCA==", - "dev": true, - "license": "ISC" - }, - "node_modules/elliptic": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", - "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, - "license": "MIT", - "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, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", - "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.4", - "@esbuild/android-arm": "0.25.4", - "@esbuild/android-arm64": "0.25.4", - "@esbuild/android-x64": "0.25.4", - "@esbuild/darwin-arm64": "0.25.4", - "@esbuild/darwin-x64": "0.25.4", - "@esbuild/freebsd-arm64": "0.25.4", - "@esbuild/freebsd-x64": "0.25.4", - "@esbuild/linux-arm": "0.25.4", - "@esbuild/linux-arm64": "0.25.4", - "@esbuild/linux-ia32": "0.25.4", - "@esbuild/linux-loong64": "0.25.4", - "@esbuild/linux-mips64el": "0.25.4", - "@esbuild/linux-ppc64": "0.25.4", - "@esbuild/linux-riscv64": "0.25.4", - "@esbuild/linux-s390x": "0.25.4", - "@esbuild/linux-x64": "0.25.4", - "@esbuild/netbsd-arm64": "0.25.4", - "@esbuild/netbsd-x64": "0.25.4", - "@esbuild/openbsd-arm64": "0.25.4", - "@esbuild/openbsd-x64": "0.25.4", - "@esbuild/sunos-x64": "0.25.4", - "@esbuild/win32-arm64": "0.25.4", - "@esbuild/win32-ia32": "0.25.4", - "@esbuild/win32-x64": "0.25.4" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "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, - "license": "MIT" - }, - "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, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "9.26.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.26.0.tgz", - "integrity": "sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.20.0", - "@eslint/config-helpers": "^0.2.1", - "@eslint/core": "^0.13.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.26.0", - "@eslint/plugin-kit": "^0.2.8", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@modelcontextprotocol/sdk": "^1.8.0", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.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", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "zod": "^3.24.2" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", - "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.20", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz", - "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "eslint": ">=8.40" - } - }, - "node_modules/eslint-scope": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", - "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", - "dev": true, - "license": "BSD-2-Clause", - "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": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.14.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "license": "BSD-3-Clause", - "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, - "license": "BSD-2-Clause", - "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, - "license": "BSD-2-Clause", - "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==", - "dev": true, - "license": "BSD-2-Clause", - "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, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventsource": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", - "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eventsource-parser": "^3.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/eventsource-parser": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz", - "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/express": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", - "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.0", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express-rate-limit": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", - "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/express-rate-limit" - }, - "peerDependencies": { - "express": "^4.11 || 5 || ^5.0.0-beta.1" - } - }, - "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, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "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.8" - }, - "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, - "license": "ISC", - "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, - "license": "MIT" - }, - "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, - "license": "MIT" - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", - "license": "MIT" - }, - "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, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.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, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "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, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, - "license": "ISC" - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "15.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", - "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "license": "MIT", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "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, - "license": "MIT", - "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/hyle": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/hyle/-/hyle-0.2.5.tgz", - "integrity": "sha512-gipgPr0Ae8DoJ6l5WxWnvrZSgo1iGhvoPcGw0DHU9gBaSWVjN/OgQezfnXaOUW8hB7yPE71oFpReqUmYQetpBQ==", - "license": "MIT", - "dependencies": { - "borsher": "^3.6.0" - } - }, - "node_modules/hyle-check-secret": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/hyle-check-secret/-/hyle-check-secret-0.3.2.tgz", - "integrity": "sha512-5Iq1Lk447I2jhQlcE7i39uTIrOnl8aQB2St6hUbu7YSE5Su9VjuvEvVOGRp04bd3yT15jJimXemiWrjD3dvctA==", - "license": "MIT", - "dependencies": { - "@aztec/bb.js": "0.82.2", - "@noir-lang/noir_js": "1.0.0-beta.2", - "@noir-lang/noir_wasm": "1.0.0-beta.2", - "hyle": "0.2.2" - } - }, - "node_modules/hyle-check-secret/node_modules/hyle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/hyle/-/hyle-0.2.2.tgz", - "integrity": "sha512-uyi5G+NoxEy39HVFfFZ8m328+c7dYKpK49hSW9stRfQV/OJxJjwUZBFh9BtcnQDnp+nKcaq5pqSNgQ0whVu1lQ==", - "license": "MIT", - "dependencies": { - "borsher": "^3.6.0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "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==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "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, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "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, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "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==", - "dev": true, - "license": "MIT" - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "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, - "license": "MIT" - }, - "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, - "license": "MIT" - }, - "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, - "license": "MIT" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "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, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "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, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.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, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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, - "license": "MIT" - }, - "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==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "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==", - "license": "ISC" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", - "license": "MIT" - }, - "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, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "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==", - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "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, - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, - "license": "MIT" - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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, - "license": "MIT", - "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, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "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/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, - "license": "MIT", - "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, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pako": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", - "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", - "license": "(MIT AND Zlib)" - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pkce-challenge": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", - "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", - "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" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.8", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "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, - "license": "MIT" - }, - "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, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "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, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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" - } - ], - "license": "MIT" - }, - "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, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", - "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.6.3", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", - "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", - "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", - "dependencies": { - "scheduler": "^0.26.0" - }, - "peerDependencies": { - "react": "^19.1.0" - } - }, - "node_modules/react-refresh": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-router": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.6.0.tgz", - "integrity": "sha512-GGufuHIVCJDbnIAXP3P9Sxzq3UUsddG3rrI3ut1q6m0FI6vxVBF3JoPQ38+W/blslLH4a5Yutp8drkEpXoddGQ==", - "license": "MIT", - "dependencies": { - "cookie": "^1.0.1", - "set-cookie-parser": "^2.6.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - } - } - }, - "node_modules/react-router-dom": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.6.0.tgz", - "integrity": "sha512-DYgm6RDEuKdopSyGOWZGtDfSm7Aofb8CCzgkliTjtu/eDuB0gcsv6qdFhhi8HdtmA+KHkt5MfZ5K2PdzjugYsA==", - "license": "MIT", - "dependencies": { - "react-router": "7.6.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - } - }, - "node_modules/react-router/node_modules/cookie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", - "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.2.tgz", - "integrity": "sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.7" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.40.2", - "@rollup/rollup-android-arm64": "4.40.2", - "@rollup/rollup-darwin-arm64": "4.40.2", - "@rollup/rollup-darwin-x64": "4.40.2", - "@rollup/rollup-freebsd-arm64": "4.40.2", - "@rollup/rollup-freebsd-x64": "4.40.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.40.2", - "@rollup/rollup-linux-arm-musleabihf": "4.40.2", - "@rollup/rollup-linux-arm64-gnu": "4.40.2", - "@rollup/rollup-linux-arm64-musl": "4.40.2", - "@rollup/rollup-linux-loongarch64-gnu": "4.40.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.40.2", - "@rollup/rollup-linux-riscv64-gnu": "4.40.2", - "@rollup/rollup-linux-riscv64-musl": "4.40.2", - "@rollup/rollup-linux-s390x-gnu": "4.40.2", - "@rollup/rollup-linux-x64-gnu": "4.40.2", - "@rollup/rollup-linux-x64-musl": "4.40.2", - "@rollup/rollup-win32-arm64-msvc": "4.40.2", - "@rollup/rollup-win32-ia32-msvc": "4.40.2", - "@rollup/rollup-win32-x64-msvc": "4.40.2", - "fsevents": "~2.3.2" - } - }, - "node_modules/router": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "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" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "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" - } - ], - "license": "MIT" - }, - "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, - "license": "MIT" - }, - "node_modules/scheduler": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==" - }, - "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, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/send": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", - "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.5", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "mime-types": "^3.0.1", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/set-cookie-parser": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", - "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", - "license": "MIT" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true, - "license": "ISC" - }, - "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, - "license": "MIT", - "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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">= 0.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, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tailwindcss": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.6.tgz", - "integrity": "sha512-j0cGLTreM6u4OWzBeLBpycK0WIh8w7kSwcUsQZoGLHZ7xDTdM69lN64AgoIEEwFi0tnhs4wSykUa5YWxAzgFYg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyglobby": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", - "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "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, - "license": "MIT", - "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, - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "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, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "dev": true, - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-eslint": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.0.tgz", - "integrity": "sha512-UMq2kxdXCzinFFPsXc9o2ozIpYCCOiEC46MG3yEh5Vipq6BO27otTtEBZA1fQ66DulEUgE97ucQ/3YY66CPg0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "8.32.0", - "@typescript-eslint/parser": "8.32.0", - "@typescript-eslint/utils": "8.32.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==" - }, - "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, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "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" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.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, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.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, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vite": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", - "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/fdir": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "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, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "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, - "license": "MIT", - "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, - "license": "ISC" - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, - "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, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "3.24.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz", - "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.24.5", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", - "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", - "dev": true, - "license": "ISC", - "peerDependencies": { - "zod": "^3.24.1" - } - } - } -} diff --git a/hyle-wallet/package.json b/hyle-wallet/package.json index b812094..e544349 100644 --- a/hyle-wallet/package.json +++ b/hyle-wallet/package.json @@ -3,21 +3,32 @@ "version": "1.0.0", "type": "module", "description": "A reusable wallet component for React applications", - "main": "dist/index.js", - "module": "dist/index.mjs", - "types": "dist/index.d.ts", + "main": "./dist/hyle-wallet.cjs.js", + "types": "dist/hyle-wallet.d.ts", + "module": "./dist/hyle-wallet.es.js", "files": [ "dist" ], + "exports": { + ".": { + "types": "./dist/hyle-wallet.d.ts", + "import": "./dist/hyle-wallet.es.js", + "require": "./dist/hyle-wallet.cjs.js" + } + }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "hyle-check-secret": "^0.3.2", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-router-dom": "^7.5.0" }, "scripts": { + "clean": "rm -rf dist", "dev": "vite", - "build": "tsc -b && vite build", - "lint": "eslint .", - "preview": "vite preview" + "build": "vite build", + "build:lib": "tsc", + "prepublishOnly": "bun run build:lib", + "pub": "npm publish" }, "dependencies": { "@types/crypto-js": "^4.2.2", @@ -25,17 +36,14 @@ "@types/react-router-dom": "^5.3.3", "crypto-js": "^4.2.0", "elliptic": "^6.6.1", - "hyle": "^0.2.5", - "hyle-check-secret": "^0.3.2", - "react": "^18.0.0", - "react-dom": "^18.0.0", - "react-router-dom": "^7.5.0" + "hyle": "^0.2.5" }, "devDependencies": { "@eslint/js": "^9.24.0", "@types/react": "^19.1.3", "@types/react-dom": "^19.1.4", "@vitejs/plugin-react": "^4.4.0", + "ajv": "^8.17.1", "autoprefixer": "^10.4.21", "eslint": "^9.24.0", "eslint-plugin-react-hooks": "^5.2.0", @@ -43,8 +51,10 @@ "globals": "^15.15.0", "postcss": "^8.5.3", "tailwindcss": "^4.1.4", - "typescript": "~5.7.3", + "typescript": "^5.8.3", "typescript-eslint": "^8.30.1", - "vite": "^6.2.6" + "vite": "^6.3.5", + "vite-plugin-css-injected-by-js": "^3.5.2", + "vite-plugin-dts": "^4.5.3" } } diff --git a/hyle-wallet/src/index.ts b/hyle-wallet/src/index.ts index c60e12a..3c22348 100644 --- a/hyle-wallet/src/index.ts +++ b/hyle-wallet/src/index.ts @@ -1,13 +1,8 @@ -import React from 'react'; -import { createRoot } from 'react-dom/client'; -import { HyleWallet } from './components/HyleWallet'; -import { ProviderOption } from './hooks/useWallet'; - -// Export the React component directly export { HyleWallet } from './components/HyleWallet'; export { PasswordAuthProvider } from './providers/PasswordAuthProvider'; export type { AuthProvider, AuthCredentials } from './types/auth'; -export type { Wallet, WalletAction, Transaction } from './types/wallet'; +export type { AuthMethod, Wallet, WalletAction, Transaction } from './types/wallet'; +export { walletContractName } from './types/wallet'; export { register, verifyIdentity, @@ -18,22 +13,8 @@ export { deserializeIdentityAction, setWalletContractName } from './types/wallet'; -export type { ProviderOption }; +export type { ProviderOption } from './hooks/useWallet'; export { WalletProvider, useWallet } from './hooks/useWallet'; export { useSessionKey } from './hooks/useSessionKey'; -export { sessionKeyService } from './services/SessionKeyService'; - -// Register the Web Component -class HyleWalletElement extends HTMLElement { - connectedCallback() { - const mountPoint = document.createElement('div'); - this.appendChild(mountPoint); - - const providersAttr = this.getAttribute('providers'); - const providers = providersAttr ? providersAttr.split(',') as ProviderOption[] : ["password" as ProviderOption]; - - createRoot(mountPoint).render(React.createElement(HyleWallet, { providers })); - } -} - -customElements.define('hyle-wallet', HyleWalletElement); +export { useConfig } from './hooks/useConfig'; +export { sessionKeyService } from './services/SessionKeyService'; \ No newline at end of file diff --git a/hyle-wallet/tsconfig.app.json b/hyle-wallet/tsconfig.app.json deleted file mode 100644 index 358ca9b..0000000 --- a/hyle-wallet/tsconfig.app.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true - }, - "include": ["src"] -} diff --git a/hyle-wallet/tsconfig.json b/hyle-wallet/tsconfig.json index 1ffef60..886e16d 100644 --- a/hyle-wallet/tsconfig.json +++ b/hyle-wallet/tsconfig.json @@ -1,7 +1,20 @@ { - "files": [], - "references": [ - { "path": "./tsconfig.app.json" }, - { "path": "./tsconfig.node.json" } - ] -} + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "lib": ["DOM", "ESNext"], + "declaration": true, + "declarationDir": "dist/types", + "emitDeclarationOnly": false, + "outDir": "dist", + "moduleResolution": "Node", + "esModuleInterop": true, + "jsx": "react-jsx", + "strict": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "allowSyntheticDefaultImports": true + }, + "include": ["src"], + "exclude": ["dist", "node_modules", "bun.lockb"] +} \ No newline at end of file diff --git a/hyle-wallet/tsconfig.node.json b/hyle-wallet/tsconfig.node.json deleted file mode 100644 index db0becc..0000000 --- a/hyle-wallet/tsconfig.node.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "compilerOptions": { - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", - "target": "ES2022", - "lib": ["ES2023"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true - }, - "include": ["vite.config.ts"] -} diff --git a/hyle-wallet/vite.config.ts b/hyle-wallet/vite.config.ts index 445dae1..866ad3f 100644 --- a/hyle-wallet/vite.config.ts +++ b/hyle-wallet/vite.config.ts @@ -1,11 +1,39 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import dts from 'vite-plugin-dts' +import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js' -// https://vite.dev/config/ export default defineConfig({ - plugins: [react()], - optimizeDeps: { - esbuildOptions: { target: "esnext" }, - exclude: ["@noir-lang/noirc_abi", "@noir-lang/acvm_js"], + build: { + lib: { + entry: 'src/index.ts', + name: 'HyleWallet', + fileName: (format) => `hyle-wallet.${format}.js`, + formats: ['es', 'cjs'] + }, + rollupOptions: { + external: [ + 'react', + 'react-dom', + 'hyle-check-secret', + 'barretenberg', + 'barretenberg/threads' + ], + output: { + globals: { + react: 'React', + 'react-dom': 'ReactDOM' + } + } + }, + outDir: 'dist' }, + plugins: [ + react(), + dts({ + entryRoot: 'src', + insertTypesEntry: true + }), + cssInjectedByJsPlugin() + ], });