From c590b09682a1c7538da8f52aeab84e80f5bf10b6 Mon Sep 17 00:00:00 2001 From: Georgy Butaev <41178744+g-but@users.noreply.github.com> Date: Mon, 31 Aug 2026 15:47:53 +0200 Subject: [PATCH] refactor(test): migrate the unit suite from Jest 30 to Vitest 4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Full parity: 282 test files / 2645 tests green before and after. - vitest.config.ts mirrors the old moduleNameMapper as ordered resolve.alias entries; jsdom env, globals, 30s timeout, v8 coverage with the same ratchet. - vitest.setup.ts ports jest.setup.ts; lucide-react is now a vi.mock Proxy (any icon resolves — the old CJS-alias Proxy surfaced no named exports and every unlisted icon crashed renders as "Element type is invalid"). - Codemod jest.* -> vi.* across tests; @jest-environment -> @vitest-environment. - Constructor mocks use function expressions (vitest news the implementation; arrows are not constructable). - Factories returning a bare component now return { default: ... }; one TDZ factory moved under vi.hoisted; one require() -> await import(). - jest.isolateModulesAsync dropped in the auth smoke test (resetModules + doMock per test covers it). - Scripts ported (positional path filters replace --testPathPatterns); verify's --watchAll flag removed; ci.yml comment updated. - Deleted jest.config.js, jest.setup.ts, __mocks__/vitest.js, tsconfig.test.json, tests/jest-dom.d.ts, and the unimported jest-era tests/utils.ts; uninstalled jest, ts-jest, jest-environment-jsdom, @types/jest; dropped the dead mcp:jest script. - Snapshot file rewritten in Vitest format (content byte-identical). Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01WqKqMnHQHSmkGFfc5t7Rxn --- .github/workflows/ci.yml | 2 +- __mocks__/next-navigation.js | 12 +- __mocks__/next-server.js | 6 +- __mocks__/nostr-nwc.js | 30 +- __mocks__/vitest.js | 1 - __tests__/create/FormField.voice.test.tsx | 6 +- __tests__/smoke/auth-login.test.ts | 73 +- __tests__/unit/ai/link-health.test.ts | 6 +- .../api/ai-form-prefill-input-length.test.ts | 30 +- .../api/entity-delete-wallet-cleanup.test.ts | 18 +- .../entity-id-crud.financial-social.test.ts | 116 +- .../unit/api/entity-id-crud.workflows.test.ts | 102 +- .../unit/api/payment-reconcile-cron.test.ts | 55 +- __tests__/unit/api/projects-id-api.test.ts | 124 +- __tests__/unit/api/receive-request.test.ts | 52 +- __tests__/unit/api/research-id-api.test.ts | 150 +- __tests__/unit/api/services-api.test.ts | 74 +- __tests__/unit/api/services.test.ts | 22 +- .../api/standardResponse.contract.test.ts | 12 +- __tests__/unit/api/v1-pay-l402.test.ts | 34 +- __tests__/unit/api/v1-payments.test.ts | 72 +- __tests__/unit/billing/getUserPlan.test.ts | 8 +- ...ntext-string-builder.snapshot.test.ts.snap | 4 +- .../unit/cat/action-executor-columns.test.ts | 113 +- .../unit/cat/connectWalletHandler.test.ts | 28 +- .../context-string-builder.snapshot.test.ts | 4 +- __tests__/unit/cat/credit-metering.test.ts | 16 +- __tests__/unit/cat/discovery.test.ts | 6 +- __tests__/unit/cat/failure-alert.test.ts | 34 +- .../forget-failure-is-not-no-match.test.ts | 16 +- .../cat/forget-generic-stem-innocents.test.ts | 10 +- .../cat/forget-reports-dropped-facts.test.ts | 10 +- .../unit/cat/forget-semantic-floor.test.ts | 24 +- .../unit/cat/health-report-honesty.test.ts | 2 +- __tests__/unit/cat/interests.test.ts | 6 +- __tests__/unit/cat/openai-compat.test.ts | 2 +- __tests__/unit/cat/platform-ceiling.test.ts | 18 +- __tests__/unit/cat/proactive.test.ts | 17 +- __tests__/unit/cat/rename-handle.test.ts | 14 +- __tests__/unit/cat/response-parser.test.ts | 4 +- __tests__/unit/cat/sendPaymentHandler.test.ts | 16 +- __tests__/unit/cat/social-handlers.test.ts | 25 +- __tests__/unit/cat/spend-caps.test.ts | 49 +- __tests__/unit/cat/suggestions.test.ts | 14 +- .../unit/cat/tool-executor-forget.test.ts | 12 +- __tests__/unit/cat/tool-use-bare-url.test.ts | 14 +- .../unit/cat/tool-use-prefill-dedupe.test.ts | 16 +- .../unit/cat/track-record-setbacks.test.ts | 19 +- __tests__/unit/cat/website-analysis.test.ts | 16 +- .../ai-assistant-free-messages.test.tsx | 14 +- .../cat-chat-composer-resize.test.tsx | 2 +- .../unit/components/cat-reply-badge.test.tsx | 7 +- .../create/AIAssistChip.a11y.test.tsx | 8 +- .../layout/HeaderActions.a11y.test.tsx | 6 +- .../layout/HeaderNavigation.a11y.test.tsx | 8 +- .../mention-autocomplete-wiring.test.tsx | 8 +- .../components/money/AmountField.test.tsx | 10 +- .../components/money/MoneyReceipt.test.tsx | 19 +- .../money/firstPaintCurrency.test.tsx | 6 +- .../payment/payFlowFirstPaint.test.tsx | 20 +- .../profile-support-section.test.tsx | 14 +- .../profile-wallet-section-public.test.tsx | 10 +- ...ct-summary-rail-target-completion.test.tsx | 4 +- .../repost-reaches-the-timeline.test.tsx | 28 +- .../repost-renders-as-a-post.test.tsx | 2 +- .../send/useRecipientCheck.test.tsx | 14 +- .../ContextSwitcher.collapsed.test.tsx | 14 +- .../timeline-composer-tools-on-focus.test.tsx | 34 +- .../components/ui/SegmentedControl.test.tsx | 30 +- .../create/entityFormSubmitAction.test.ts | 42 +- .../domain/commerce-list-workflows.test.ts | 28 +- .../domain/entity-create-financial.test.ts | 30 +- .../domain/entity-create-workflows.test.ts | 36 +- .../unit/domain/loans/obligation.test.ts | 12 +- __tests__/unit/domain/loans/offers.test.ts | 34 +- __tests__/unit/domain/loans/payments.test.ts | 26 +- .../payments/buyerConfirmPayment.test.ts | 50 +- .../payments/checkPaymentStatus.test.ts | 26 +- .../domain/payments/exactlyOncePaid.test.ts | 48 +- .../domain/payments/fiatPricedAmount.test.ts | 26 +- .../payments/handlePaymentConfirmed.test.ts | 58 +- .../payments/initiatePayment.guards.test.ts | 32 +- .../unit/domain/payments/lnurlVerify.test.ts | 32 +- .../payments/payableOnchainAddress.test.ts | 14 +- .../payments/paymentRequestService.test.ts | 18 +- .../payments/publicPaymentStatus.test.ts | 34 +- .../payments/resolveSellerWallet.test.ts | 14 +- .../resolveSpecificUserWallet.test.ts | 20 +- .../sellerIdentityAndReceiveInfo.test.ts | 14 +- .../payments/sendPaymentService.test.ts | 49 +- .../payments/settlementRailDispatch.test.ts | 34 +- .../undetectableIntentLifecycle.test.ts | 36 +- .../payments/walletResolutionQueries.test.ts | 18 +- .../domain/projects-list-workflow.test.ts | 36 +- .../domain/wallets/transferService.test.ts | 16 +- .../unit/hooks/messaging-live-writes.test.tsx | 24 +- __tests__/unit/hooks/useAwaitCatReply.test.ts | 24 +- .../hooks/useContentEditableEditor.test.tsx | 6 +- .../unit/hooks/useDisplayCurrency.test.ts | 4 +- .../unit/hooks/useEntityCreateEdit.test.ts | 24 +- __tests__/unit/hooks/useNavigation.test.ts | 30 +- ...gationContext-hides-fixture-groups.test.ts | 6 +- .../unit/hooks/useNavigationStorage.test.ts | 34 +- __tests__/unit/hooks/useNotifications.test.ts | 18 +- .../unit/hooks/usePostComposerClears.test.ts | 16 +- .../unit/hooks/usePostLikeDislike.test.ts | 23 +- __tests__/unit/hooks/useRequireAuth.test.tsx | 18 +- __tests__/unit/hooks/useThrottledLog.test.ts | 26 +- __tests__/unit/images/generate.test.ts | 22 +- __tests__/unit/lib/ai-assist-any-form.test.ts | 4 +- __tests__/unit/lib/api-owner-filter.test.ts | 20 +- __tests__/unit/lib/haptics.test.ts | 18 +- .../lightning-address/lnurl-service.test.ts | 24 +- __tests__/unit/middleware.auth.test.ts | 6 +- .../unit/offline/offline-queue-events.test.ts | 6 +- .../payments/incomplete-settlement.test.ts | 26 +- __tests__/unit/payments/l402-verify.test.ts | 29 +- .../retired-handle-not-available.test.ts | 14 +- .../unit/public-surface-filtering.test.ts | 10 +- .../unit/services/ai/assistant-charge.test.ts | 14 +- __tests__/unit/services/ai/openrouter.test.ts | 14 +- .../services/bookings.notifications.test.ts | 24 +- __tests__/unit/services/cat-account.test.ts | 6 +- .../unit/services/cat-mention-queue.test.ts | 76 +- .../unit/services/cat-post-mentions.test.ts | 28 +- .../services/cat-worker-bootstrap.test.ts | 36 +- .../unit/services/cat/credit-topup.test.ts | 34 +- __tests__/unit/services/cat/credits.test.ts | 8 +- .../services/cat/platform-feedback.test.ts | 14 +- .../unit/services/cat/topup-reconcile.test.ts | 34 +- .../unit/services/cat/track-record.test.ts | 4 +- .../services/count-public-wallets.test.ts | 14 +- .../unit/services/currency/conversion.test.ts | 4 +- .../services/current-user-id-cache.test.ts | 11 +- __tests__/unit/services/domain-search.test.ts | 8 +- .../unit/services/notify-mentions.test.ts | 9 +- .../project-funding-enrichment.test.ts | 15 +- .../rate-refresh-outside-render.test.ts | 18 +- .../unit/services/reaction-count.test.ts | 8 +- .../unit/services/reaction-state.test.ts | 6 +- .../services/reply-tree-query-count.test.ts | 16 +- .../services/timeline-warms-reader.test.ts | 68 +- .../unit/services/voice/intentRouter.test.ts | 8 +- .../warm-reader-is-browser-only.test.ts | 6 +- .../unit/services/weeklyDigest.email.test.ts | 2 +- .../unit/solon/allocation-policy.test.ts | 14 +- __tests__/unit/solon/cat-proposer.test.ts | 28 +- __tests__/unit/solon/decision-verify.test.ts | 26 +- __tests__/unit/tips/tip-service.test.ts | 42 +- __tests__/unit/wallets/receive-status.test.ts | 24 +- .../wallets/wallet-update-handles.test.ts | 12 +- __tests__/unit/wallets/wallet-usage.test.ts | 10 +- jest.config.js | 83 - package-lock.json | 16078 +++++++--------- package.json | 30 +- tests/TestWrapper.tsx | 46 +- tests/jest-dom.d.ts | 9 - tests/setup.ts | 6 +- tests/unit/Button.test.tsx | 12 +- tests/unit/app/Home.test.tsx | 16 +- tests/unit/app/api/cron/cleanup.test.ts | 38 +- .../unit/app/api/cron/webhook-worker.test.ts | 92 +- .../app/api/integration-keys/rotate.test.ts | 42 +- .../api/webhook-endpoints/deliveries.test.ts | 78 +- .../app/api/webhook-endpoints/route.test.ts | 60 +- .../components/layout/AuthButtons.test.tsx | 24 +- .../sidebar/ContextSwitcher.test.tsx | 22 +- .../sidebar/SidebarNavigation.test.tsx | 8 +- .../services/auth/integrationKeys.test.ts | 6 +- .../idempotency/claimIdempotencyKey.test.ts | 2 +- .../services/webhooks/deliveryService.test.ts | 2 +- tests/utils.ts | 143 - tsconfig.json | 42 +- tsconfig.test.json | 16 - vitest.config.ts | 55 + jest.setup.ts => vitest.setup.ts | 221 +- 176 files changed, 9311 insertions(+), 11448 deletions(-) delete mode 100644 __mocks__/vitest.js delete mode 100644 jest.config.js delete mode 100644 tests/jest-dom.d.ts delete mode 100644 tests/utils.ts delete mode 100644 tsconfig.test.json create mode 100644 vitest.config.ts rename jest.setup.ts => vitest.setup.ts (72%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a0036b8f1..408cab938 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -76,7 +76,7 @@ jobs: # → 404 class of bug. Static, fast. # - lint : eslint — catches the undefined-identifier class (e.g. # the `IntegrationNote` bug that once landed on main). - # - test:unit : Jest unit suite (--watchAll=false). + # - test:unit : Vitest unit suite. # (Playwright/E2E stays a separate post-build gate below — it needs a # running server + secrets, so it isn't part of the static verify bundle.) run: npm run verify diff --git a/__mocks__/next-navigation.js b/__mocks__/next-navigation.js index 1de0e9fd2..9de96bf29 100644 --- a/__mocks__/next-navigation.js +++ b/__mocks__/next-navigation.js @@ -1,13 +1,13 @@ // Simple Jest mock for next/navigation module.exports = { useRouter: () => ({ - push: jest.fn(), - replace: jest.fn(), - prefetch: jest.fn(), - back: jest.fn(), + push: vi.fn(), + replace: vi.fn(), + prefetch: vi.fn(), + back: vi.fn(), }), useSearchParams: () => ({ - get: jest.fn(), + get: vi.fn(), }), - usePathname: jest.fn(() => '/'), + usePathname: vi.fn(() => '/'), }; diff --git a/__mocks__/next-server.js b/__mocks__/next-server.js index fd301f79f..51d50a037 100644 --- a/__mocks__/next-server.js +++ b/__mocks__/next-server.js @@ -1,8 +1,8 @@ module.exports = { NextRequest: class NextRequest {}, NextResponse: { - json: jest.fn(), - redirect: jest.fn(), - next: jest.fn(), + json: vi.fn(), + redirect: vi.fn(), + next: vi.fn(), }, }; diff --git a/__mocks__/nostr-nwc.js b/__mocks__/nostr-nwc.js index fafe8db24..bcbb1ed20 100644 --- a/__mocks__/nostr-nwc.js +++ b/__mocks__/nostr-nwc.js @@ -1,17 +1,31 @@ // Mock for @/lib/nostr/nwc — prevents nostr-tools ESM/CJS issues in Jest. -// NWCClient is mocked with jest.fn() stubs; real NWC tests use integration environment. +// NWCClient is mocked with vi.fn() stubs; real NWC tests use integration environment. class NWCClient { constructor(_uri) {} - connect() { return Promise.resolve(); } + connect() { + return Promise.resolve(); + } disconnect() {} - payInvoice(_bolt11) { return Promise.resolve({ payment_hash: 'mock_hash', invoice: _bolt11 }); } - makeInvoice(_sats, _desc, _expiry) { return Promise.resolve({ invoice: 'lnbc_mock', payment_hash: 'mock_hash' }); } - getBalance() { return Promise.resolve(100000); } - lookupInvoice(_hash) { return Promise.resolve({ payment_hash: _hash }); } + payInvoice(_bolt11) { + return Promise.resolve({ payment_hash: 'mock_hash', invoice: _bolt11 }); + } + makeInvoice(_sats, _desc, _expiry) { + return Promise.resolve({ invoice: 'lnbc_mock', payment_hash: 'mock_hash' }); + } + getBalance() { + return Promise.resolve(100000); + } + lookupInvoice(_hash) { + return Promise.resolve({ payment_hash: _hash }); + } } -function parseNWCUri(uri) { return { walletPubkey: 'mock', relayUrl: 'wss://mock', secret: 'mock' }; } -function isValidNWCUri(uri) { return typeof uri === 'string' && uri.startsWith('nostr+walletconnect://'); } +function parseNWCUri(uri) { + return { walletPubkey: 'mock', relayUrl: 'wss://mock', secret: 'mock' }; +} +function isValidNWCUri(uri) { + return typeof uri === 'string' && uri.startsWith('nostr+walletconnect://'); +} module.exports = { NWCClient, parseNWCUri, isValidNWCUri }; diff --git a/__mocks__/vitest.js b/__mocks__/vitest.js deleted file mode 100644 index f053ebf79..000000000 --- a/__mocks__/vitest.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = {}; diff --git a/__tests__/create/FormField.voice.test.tsx b/__tests__/create/FormField.voice.test.tsx index 97de918d7..ec6f795ac 100644 --- a/__tests__/create/FormField.voice.test.tsx +++ b/__tests__/create/FormField.voice.test.tsx @@ -6,9 +6,9 @@ import { AIFillPanel } from '@/components/create/AIFillPanel'; // Voice input is env-gated behind FEATURES.voiceInput, evaluated at module-load // time — mock the flag ON so the voice path is exercised regardless of the // deployment default. -jest.mock('@/config/features', () => ({ FEATURES: { voiceInput: true } })); +vi.mock('@/config/features', () => ({ FEATURES: { voiceInput: true } })); -jest.mock('@/components/ui/DictationButton', () => ({ +vi.mock('@/components/ui/DictationButton', () => ({ __esModule: true, DictationButton: ({ onTranscript, @@ -52,7 +52,7 @@ describe('voice placement', () => { }); it('renders ONE mic in the AI fill panel, appending to the description', () => { - const onDescriptionChange = jest.fn(); + const onDescriptionChange = vi.fn(); render( { beforeEach(() => { - jest.resetModules() - }) + vi.resetModules(); + }); it('renders public home when not authenticated', async () => { - await jest.isolateModulesAsync(async () => { - jest.doMock('next/navigation', () => ({ - redirect: jest.fn(), - })) - jest.doMock('@/lib/supabase/server', () => ({ + // jest.isolateModulesAsync has no vitest equivalent; beforeEach's + // vi.resetModules() plus vi.doMock give each test a fresh module graph. + await (async () => { + vi.doMock('next/navigation', () => ({ + redirect: vi.fn(), + })); + vi.doMock('@/lib/supabase/server', () => ({ createServerClient: () => Promise.resolve({ auth: { - getUser: jest.fn().mockResolvedValue({ data: { user: null } }), + getUser: vi.fn().mockResolvedValue({ data: { user: null } }), }, }), - })) + })); - const { default: Home } = await import('@/app/page') - await Home() - const { redirect } = await import('next/navigation') - expect((redirect as jest.Mock)).not.toHaveBeenCalled() - }) - }) + const { default: Home } = await import('@/app/page'); + await Home(); + const { redirect } = await import('next/navigation'); + expect(redirect as Mock).not.toHaveBeenCalled(); + })(); + }); it('redirects to dashboard when authenticated', async () => { - await jest.isolateModulesAsync(async () => { - jest.doMock('next/navigation', () => ({ - redirect: jest.fn(), - })) - jest.doMock('@/lib/supabase/server', () => ({ + await (async () => { + vi.doMock('next/navigation', () => ({ + redirect: vi.fn(), + })); + vi.doMock('@/lib/supabase/server', () => ({ createServerClient: () => Promise.resolve({ auth: { - getUser: jest.fn().mockResolvedValue({ data: { user: { id: '123' } } }), + getUser: vi.fn().mockResolvedValue({ data: { user: { id: '123' } } }), }, - from: jest.fn().mockReturnValue({ - select: jest.fn().mockReturnValue({ - eq: jest.fn().mockReturnValue({ - single: jest.fn().mockResolvedValue({ + from: vi.fn().mockReturnValue({ + select: vi.fn().mockReturnValue({ + eq: vi.fn().mockReturnValue({ + single: vi.fn().mockResolvedValue({ data: { onboarding_completed: true }, error: null, }), @@ -56,13 +60,12 @@ describe('auth smoke', () => { }), }), }), - })) - - const { default: Home } = await import('@/app/page') - await Home() - const { redirect } = await import('next/navigation') - expect((redirect as jest.Mock)).toHaveBeenCalled() - }) - }) -}) + })); + const { default: Home } = await import('@/app/page'); + await Home(); + const { redirect } = await import('next/navigation'); + expect(redirect as Mock).toHaveBeenCalled(); + })(); + }); +}); diff --git a/__tests__/unit/ai/link-health.test.ts b/__tests__/unit/ai/link-health.test.ts index cc104dfde..5fecf69a6 100644 --- a/__tests__/unit/ai/link-health.test.ts +++ b/__tests__/unit/ai/link-health.test.ts @@ -19,10 +19,10 @@ const CHAIN = [ describe('link-health', () => { beforeEach(() => { resetLinkHealth(); - jest.useFakeTimers(); + vi.useFakeTimers(); }); afterEach(() => { - jest.useRealTimers(); + vi.useRealTimers(); }); it('marks a link down and prunes it from the chain', () => { @@ -34,7 +34,7 @@ describe('link-health', () => { it('expires the down-mark after the TTL', () => { markLinkDown('groq', 'llama-3.3-70b-versatile', 1000); - jest.advanceTimersByTime(1001); + vi.advanceTimersByTime(1001); expect(isLinkDown('groq', 'llama-3.3-70b-versatile')).toBe(false); expect(pruneDownLinks(CHAIN, l => l)).toHaveLength(3); }); diff --git a/__tests__/unit/api/ai-form-prefill-input-length.test.ts b/__tests__/unit/api/ai-form-prefill-input-length.test.ts index 8bc4e0d83..a7851a903 100644 --- a/__tests__/unit/api/ai-form-prefill-input-length.test.ts +++ b/__tests__/unit/api/ai-form-prefill-input-length.test.ts @@ -15,39 +15,41 @@ import { POST } from '@/app/api/ai/form-prefill/route'; import { generateFormPrefill } from '@/lib/ai/form-prefill-service'; import { AI_ASSIST_MIN_INPUT_LENGTH, AI_ADJUSTMENTS } from '@/config/ai-form-assist'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { MockedFunction } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); // withAuth wraps the handler in a real Supabase session lookup; the request // itself is what this suite is about, so authentication is stubbed through. -jest.mock('@/lib/api/withAuth', () => ({ +vi.mock('@/lib/api/withAuth', () => ({ withAuth: (handler: (req: unknown) => Promise) => (req: unknown): Promise => handler(Object.assign(req as object, { user: { id: 'test-user' }, supabase: {} })), })); -jest.mock('@/lib/rate-limit', () => ({ - rateLimitWriteAsync: jest.fn().mockResolvedValue({ success: true }), +vi.mock('@/lib/rate-limit', () => ({ + rateLimitWriteAsync: vi.fn().mockResolvedValue({ success: true }), retryAfterSeconds: () => 0, })); // The response helpers wrap NextResponse, which needs the Next runtime; the // established convention in route tests is to stub them. -jest.mock('@/lib/api/standardResponse', () => ({ - apiSuccess: jest.fn((data: unknown) => ({ status: 200, body: { success: true, data } })), - apiValidationError: jest.fn((error: string) => ({ status: 400, error })), - apiBadRequest: jest.fn((error: string) => ({ status: 400, error })), - apiRateLimited: jest.fn(() => ({ status: 429 })), - apiInternalError: jest.fn(() => ({ status: 500 })), +vi.mock('@/lib/api/standardResponse', () => ({ + apiSuccess: vi.fn((data: unknown) => ({ status: 200, body: { success: true, data } })), + apiValidationError: vi.fn((error: string) => ({ status: 400, error })), + apiBadRequest: vi.fn((error: string) => ({ status: 400, error })), + apiRateLimited: vi.fn(() => ({ status: 429 })), + apiInternalError: vi.fn(() => ({ status: 500 })), })); -jest.mock('@/lib/ai/form-prefill-service', () => ({ - generateFormPrefill: jest.fn(), +vi.mock('@/lib/ai/form-prefill-service', () => ({ + generateFormPrefill: vi.fn(), })); -const mockedPrefill = generateFormPrefill as jest.MockedFunction; +const mockedPrefill = generateFormPrefill as MockedFunction; const BASE = { entityType: 'service', diff --git a/__tests__/unit/api/entity-delete-wallet-cleanup.test.ts b/__tests__/unit/api/entity-delete-wallet-cleanup.test.ts index dbfe6a02b..c9973377e 100644 --- a/__tests__/unit/api/entity-delete-wallet-cleanup.test.ts +++ b/__tests__/unit/api/entity-delete-wallet-cleanup.test.ts @@ -7,19 +7,21 @@ * someone's money built on rows that outlived their subject. */ -const mockLinkDelete = jest.fn(); -const mockAdminFrom = jest.fn(); +const mockLinkDelete = vi.fn(); +const mockAdminFrom = vi.fn(); -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/supabase/admin', () => ({ +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: () => ({ from: (t: string) => mockAdminFrom(t) }), })); import { DATABASE_TABLES } from '@/config/database-tables'; +import type { Mock } from 'vitest'; + /** * The handler is a thick closure over Next request plumbing; this exercises the * cleanup contract directly against the same admin-client shape it uses. @@ -37,11 +39,11 @@ beforeEach(() => { mockLinkDelete.mockReset(); mockAdminFrom.mockReset(); const eqChain = { - eq: jest.fn(function (this: unknown) { + eq: vi.fn(function (this: unknown) { return eqChain; }), then: undefined, - } as never as { eq: jest.Mock }; + } as never as { eq: Mock }; mockLinkDelete.mockReturnValue(eqChain); mockAdminFrom.mockReturnValue({ delete: mockLinkDelete }); }); @@ -50,7 +52,7 @@ describe('entity delete → entity_wallets cleanup', () => { it('targets the entity_wallets table scoped to BOTH type and id', async () => { const eqCalls: Array<[string, string]> = []; const chain: Record = {}; - chain.eq = jest.fn((col: string, val: string) => { + chain.eq = vi.fn((col: string, val: string) => { eqCalls.push([col, val]); return chain; }); diff --git a/__tests__/unit/api/entity-id-crud.financial-social.test.ts b/__tests__/unit/api/entity-id-crud.financial-social.test.ts index 98361be68..7fdf953e6 100644 --- a/__tests__/unit/api/entity-id-crud.financial-social.test.ts +++ b/__tests__/unit/api/entity-id-crud.financial-social.test.ts @@ -4,68 +4,70 @@ import { GET as getEvent, PUT as putEvent } from '@/app/api/events/[id]/route'; import { GET as getWishlist, PUT as putWishlist } from '@/app/api/wishlists/[id]/route'; import { GET as getInvestment, PUT as putInvestment } from '@/app/api/investments/[id]/route'; -jest.mock('@/lib/supabase/server', () => ({ - createServerClient: jest.fn(), +vi.mock('@/lib/supabase/server', () => ({ + createServerClient: vi.fn(), })); -jest.mock('@/services/actors', () => ({ - checkOwnership: jest.fn(), +vi.mock('@/services/actors', () => ({ + checkOwnership: vi.fn(), })); -jest.mock('@/services/actors/getOrCreateUserActor', () => ({ - getOrCreateUserActor: jest.fn().mockResolvedValue({ id: 'a1' }), +vi.mock('@/services/actors/getOrCreateUserActor', () => ({ + getOrCreateUserActor: vi.fn().mockResolvedValue({ id: 'a1' }), })); -jest.mock('@/lib/api/standardResponse', () => ({ - apiSuccess: jest.fn((data: unknown) => ({ +vi.mock('@/lib/api/standardResponse', () => ({ + apiSuccess: vi.fn((data: unknown) => ({ status: 200, json: async () => ({ success: true, data }), })), - apiUnauthorized: jest.fn((message = 'Unauthorized') => ({ + apiUnauthorized: vi.fn((message = 'Unauthorized') => ({ status: 401, json: async () => ({ success: false, error: { message } }), })), - apiNotFound: jest.fn((message = 'Not found') => ({ + apiNotFound: vi.fn((message = 'Not found') => ({ status: 404, json: async () => ({ success: false, error: { message } }), })), - apiValidationError: jest.fn((message = 'Validation failed') => ({ + apiValidationError: vi.fn((message = 'Validation failed') => ({ status: 400, json: async () => ({ success: false, error: { message } }), })), - handleApiError: jest.fn(() => ({ + handleApiError: vi.fn(() => ({ status: 500, json: async () => ({ success: false, error: { message: 'Internal error' } }), })), - handleSupabaseError: jest.fn(() => ({ + handleSupabaseError: vi.fn(() => ({ status: 500, json: async () => ({ success: false, error: { message: 'DB error' } }), })), - apiForbidden: jest.fn((message = 'Forbidden') => ({ + apiForbidden: vi.fn((message = 'Forbidden') => ({ status: 403, json: async () => ({ success: false, error: { message } }), })), - apiRateLimited: jest.fn(() => ({ + apiRateLimited: vi.fn(() => ({ status: 429, json: async () => ({ success: false, error: { message: 'Rate limited' } }), })), - apiBadRequest: jest.fn((message = 'Bad request') => ({ + apiBadRequest: vi.fn((message = 'Bad request') => ({ status: 400, json: async () => ({ success: false, error: { message } }), })), })); -jest.mock('@/lib/rate-limit', () => ({ - rateLimit: jest.fn(), - rateLimitWriteAsync: jest.fn(), - createRateLimitResponse: jest.fn(() => ({ status: 429, json: async () => ({ success: false }) })), - applyRateLimitHeaders: jest.fn((response: unknown) => response), +vi.mock('@/lib/rate-limit', () => ({ + rateLimit: vi.fn(), + rateLimitWriteAsync: vi.fn(), + createRateLimitResponse: vi.fn(() => ({ status: 429, json: async () => ({ success: false }) })), + applyRateLimitHeaders: vi.fn((response: unknown) => response), })); import { createServerClient } from '@/lib/supabase/server'; import { checkOwnership } from '@/services/actors'; import { rateLimit, rateLimitWriteAsync } from '@/lib/rate-limit'; +import type { Mock } from 'vitest'; + type Case = { name: string; table: string; @@ -149,13 +151,13 @@ const cases: Case[] = [ describe('Entity [id] CRUD workflows (asset/loan/event/wishlist/investment)', () => { beforeEach(() => { - jest.clearAllMocks(); - (rateLimit as jest.Mock).mockResolvedValue({ success: true }); - (rateLimitWriteAsync as jest.Mock).mockResolvedValue({ + vi.clearAllMocks(); + (rateLimit as Mock).mockResolvedValue({ success: true }); + (rateLimitWriteAsync as Mock).mockResolvedValue({ success: true, resetTime: Date.now() + 60000, }); - (checkOwnership as jest.Mock).mockResolvedValue(true); + (checkOwnership as Mock).mockResolvedValue(true); }); describe.each(cases)('$name id routes', c => { @@ -168,24 +170,26 @@ describe('Entity [id] CRUD workflows (asset/loan/event/wishlist/investment)', () entity[c.ownerField] = c.ownerField === 'actor_id' ? 'a1' : 'u1'; const fetchQuery = { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: entity, error: null }), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: entity, error: null }), } as any; const supabase = { auth: { - getUser: jest.fn().mockResolvedValue({ data: { user: { id: 'u1' } }, error: null }), + getUser: vi.fn().mockResolvedValue({ data: { user: { id: 'u1' } }, error: null }), }, - from: jest.fn().mockImplementation((name: string) => { + from: vi.fn().mockImplementation((name: string) => { expect(name).toBe(c.table); return fetchQuery; }), }; - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); - const response = await c.getHandler({} as any, { params: { id: '00000000-0000-0000-0000-000000000001' } }); + const response = await c.getHandler({} as any, { + params: { id: '00000000-0000-0000-0000-000000000001' }, + }); const body = await response.json(); expect(response.status).toBe(200); @@ -194,37 +198,40 @@ describe('Entity [id] CRUD workflows (asset/loan/event/wishlist/investment)', () }); it('PUT updates own entity', async () => { - const existing: Record = { id: '00000000-0000-0000-0000-000000000001', title: 'Old' }; + const existing: Record = { + id: '00000000-0000-0000-0000-000000000001', + title: 'Old', + }; existing[c.ownerField] = c.ownerField === 'actor_id' ? 'a1' : 'u1'; const updated = { ...existing, title: String(c.validUpdate.title) }; const fetchQuery = { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: existing, error: null }), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: existing, error: null }), } as any; const updateQuery = { - update: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - select: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: updated, error: null }), + update: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + select: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: updated, error: null }), } as any; const supabase = { auth: { - getUser: jest.fn().mockResolvedValue({ data: { user: { id: 'u1' } }, error: null }), + getUser: vi.fn().mockResolvedValue({ data: { user: { id: 'u1' } }, error: null }), }, - from: jest + from: vi .fn() .mockImplementationOnce(() => fetchQuery) .mockImplementationOnce(() => updateQuery), }; - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); const response = await c.putHandler( - { json: jest.fn().mockResolvedValue(c.validUpdate) } as any, + { json: vi.fn().mockResolvedValue(c.validUpdate) } as any, { params: { id: '00000000-0000-0000-0000-000000000001' } } ); const body = await response.json(); @@ -235,30 +242,33 @@ describe('Entity [id] CRUD workflows (asset/loan/event/wishlist/investment)', () }); it('PUT rejects non-owner update', async () => { - const existing: Record = { id: '00000000-0000-0000-0000-000000000001', title: 'Locked' }; + const existing: Record = { + id: '00000000-0000-0000-0000-000000000001', + title: 'Locked', + }; existing[c.ownerField] = c.ownerField === 'actor_id' ? 'a1' : 'someone-else'; if (c.usesActorOwnership) { - (checkOwnership as jest.Mock).mockResolvedValue(false); + (checkOwnership as Mock).mockResolvedValue(false); } const fetchQuery = { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: existing, error: null }), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: existing, error: null }), } as any; const supabase = { auth: { - getUser: jest.fn().mockResolvedValue({ data: { user: { id: 'u1' } }, error: null }), + getUser: vi.fn().mockResolvedValue({ data: { user: { id: 'u1' } }, error: null }), }, - from: jest.fn().mockImplementation(() => fetchQuery), + from: vi.fn().mockImplementation(() => fetchQuery), }; - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); const response = await c.putHandler( - { json: jest.fn().mockResolvedValue(c.validUpdate) } as any, + { json: vi.fn().mockResolvedValue(c.validUpdate) } as any, { params: { id: '00000000-0000-0000-0000-000000000001' } } ); const body = await response.json(); diff --git a/__tests__/unit/api/entity-id-crud.workflows.test.ts b/__tests__/unit/api/entity-id-crud.workflows.test.ts index 95272c5ea..101423798 100644 --- a/__tests__/unit/api/entity-id-crud.workflows.test.ts +++ b/__tests__/unit/api/entity-id-crud.workflows.test.ts @@ -2,68 +2,70 @@ import { GET as getService, PUT as putService } from '@/app/api/services/[id]/ro import { GET as getProduct, PUT as putProduct } from '@/app/api/products/[id]/route'; import { GET as getCause, PUT as putCause } from '@/app/api/causes/[id]/route'; -jest.mock('@/lib/supabase/server', () => ({ - createServerClient: jest.fn(), +vi.mock('@/lib/supabase/server', () => ({ + createServerClient: vi.fn(), })); -jest.mock('@/lib/api/standardResponse', () => ({ - apiSuccess: jest.fn((data: unknown) => ({ +vi.mock('@/lib/api/standardResponse', () => ({ + apiSuccess: vi.fn((data: unknown) => ({ status: 200, json: async () => ({ success: true, data }), })), - apiUnauthorized: jest.fn((message = 'Unauthorized') => ({ + apiUnauthorized: vi.fn((message = 'Unauthorized') => ({ status: 401, json: async () => ({ success: false, error: { message } }), })), - apiNotFound: jest.fn((message = 'Not found') => ({ + apiNotFound: vi.fn((message = 'Not found') => ({ status: 404, json: async () => ({ success: false, error: { message } }), })), - apiValidationError: jest.fn((message = 'Validation failed') => ({ + apiValidationError: vi.fn((message = 'Validation failed') => ({ status: 400, json: async () => ({ success: false, error: { message } }), })), - handleApiError: jest.fn(() => ({ + handleApiError: vi.fn(() => ({ status: 500, json: async () => ({ success: false, error: { message: 'Internal error' } }), })), - handleSupabaseError: jest.fn(() => ({ + handleSupabaseError: vi.fn(() => ({ status: 500, json: async () => ({ success: false, error: { message: 'DB error' } }), })), - apiForbidden: jest.fn((message = 'Forbidden') => ({ + apiForbidden: vi.fn((message = 'Forbidden') => ({ status: 403, json: async () => ({ success: false, error: { message } }), })), - apiRateLimited: jest.fn(() => ({ + apiRateLimited: vi.fn(() => ({ status: 429, json: async () => ({ success: false, error: { message: 'Rate limited' } }), })), - apiBadRequest: jest.fn((message = 'Bad request') => ({ + apiBadRequest: vi.fn((message = 'Bad request') => ({ status: 400, json: async () => ({ success: false, error: { message } }), })), })); -jest.mock('@/services/actors', () => ({ - checkOwnership: jest.fn(), +vi.mock('@/services/actors', () => ({ + checkOwnership: vi.fn(), })); -jest.mock('@/services/actors/getOrCreateUserActor', () => ({ - getOrCreateUserActor: jest.fn().mockResolvedValue({ id: 'a1' }), +vi.mock('@/services/actors/getOrCreateUserActor', () => ({ + getOrCreateUserActor: vi.fn().mockResolvedValue({ id: 'a1' }), })); -jest.mock('@/lib/rate-limit', () => ({ - rateLimit: jest.fn(), - rateLimitWriteAsync: jest.fn(), - createRateLimitResponse: jest.fn(() => ({ status: 429, json: async () => ({ success: false }) })), - applyRateLimitHeaders: jest.fn((response: unknown) => response), +vi.mock('@/lib/rate-limit', () => ({ + rateLimit: vi.fn(), + rateLimitWriteAsync: vi.fn(), + createRateLimitResponse: vi.fn(() => ({ status: 429, json: async () => ({ success: false }) })), + applyRateLimitHeaders: vi.fn((response: unknown) => response), })); import { createServerClient } from '@/lib/supabase/server'; import { checkOwnership } from '@/services/actors'; import { rateLimit, rateLimitWriteAsync } from '@/lib/rate-limit'; +import type { Mock } from 'vitest'; + type Case = { name: string; table: string; @@ -111,13 +113,13 @@ const cases: Case[] = [ describe('Entity [id] CRUD workflows (service/product/cause)', () => { beforeEach(() => { - jest.clearAllMocks(); - (rateLimit as jest.Mock).mockResolvedValue({ success: true }); - (rateLimitWriteAsync as jest.Mock).mockResolvedValue({ + vi.clearAllMocks(); + (rateLimit as Mock).mockResolvedValue({ success: true }); + (rateLimitWriteAsync as Mock).mockResolvedValue({ success: true, resetTime: Date.now() + 60000, }); - (checkOwnership as jest.Mock).mockResolvedValue(true); + (checkOwnership as Mock).mockResolvedValue(true); }); describe.each(cases)('$name id routes', ({ table, getHandler, putHandler, validUpdate }) => { @@ -131,20 +133,20 @@ describe('Entity [id] CRUD workflows (service/product/cause)', () => { }; const fetchQuery = { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: entity, error: null }), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: entity, error: null }), } as any; const supabase = { - auth: { getUser: jest.fn().mockResolvedValue({ data: { user: null } }) }, - from: jest.fn().mockImplementation((name: string) => { + auth: { getUser: vi.fn().mockResolvedValue({ data: { user: null } }) }, + from: vi.fn().mockImplementation((name: string) => { expect(name).toBe(table); return fetchQuery; }), }; - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); const response = await getHandler({} as any, { params: { id: '00000000-0000-0000-0000-000000000001' }, @@ -166,31 +168,31 @@ describe('Entity [id] CRUD workflows (service/product/cause)', () => { const updated = { ...existing, title: String(validUpdate.title) }; const fetchQuery = { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: existing, error: null }), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: existing, error: null }), } as any; const updateQuery = { - update: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - select: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: updated, error: null }), + update: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + select: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: updated, error: null }), } as any; const supabase = { auth: { - getUser: jest.fn().mockResolvedValue({ data: { user: { id: 'u1' } }, error: null }), + getUser: vi.fn().mockResolvedValue({ data: { user: { id: 'u1' } }, error: null }), }, - from: jest + from: vi .fn() .mockImplementationOnce(() => fetchQuery) .mockImplementationOnce(() => updateQuery), }; - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); - const request = { json: jest.fn().mockResolvedValue(validUpdate) }; + const request = { json: vi.fn().mockResolvedValue(validUpdate) }; const response = await putHandler(request as any, { params: { id: '00000000-0000-0000-0000-000000000001' }, }); @@ -202,7 +204,7 @@ describe('Entity [id] CRUD workflows (service/product/cause)', () => { }); it('PUT rejects update from non-owner', async () => { - (checkOwnership as jest.Mock).mockResolvedValueOnce(false); + (checkOwnership as Mock).mockResolvedValueOnce(false); const existing = { id: '00000000-0000-0000-0000-000000000001', user_id: 'someone-else', @@ -211,21 +213,21 @@ describe('Entity [id] CRUD workflows (service/product/cause)', () => { }; const fetchQuery = { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: existing, error: null }), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: existing, error: null }), } as any; const supabase = { auth: { - getUser: jest.fn().mockResolvedValue({ data: { user: { id: 'u1' } }, error: null }), + getUser: vi.fn().mockResolvedValue({ data: { user: { id: 'u1' } }, error: null }), }, - from: jest.fn().mockImplementation(() => fetchQuery), + from: vi.fn().mockImplementation(() => fetchQuery), }; - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); - const request = { json: jest.fn().mockResolvedValue(validUpdate) }; + const request = { json: vi.fn().mockResolvedValue(validUpdate) }; const response = await putHandler(request as any, { params: { id: '00000000-0000-0000-0000-000000000001' }, }); diff --git a/__tests__/unit/api/payment-reconcile-cron.test.ts b/__tests__/unit/api/payment-reconcile-cron.test.ts index 3794641f7..39e2ba635 100644 --- a/__tests__/unit/api/payment-reconcile-cron.test.ts +++ b/__tests__/unit/api/payment-reconcile-cron.test.ts @@ -12,34 +12,36 @@ import { GET } from '@/app/api/cron/payment-reconcile/route'; import { reconcilePaymentIntent } from '@/domain/payments/paymentFlowService'; import { STATUS } from '@/config/database-constants'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { MockedFunction } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); // The response helpers wrap NextResponse, which needs the Next runtime; the // established convention in route tests is to stub them (see projects-id-api). -jest.mock('@/lib/api/standardResponse', () => ({ - apiSuccess: jest.fn((data: unknown) => ({ +vi.mock('@/lib/api/standardResponse', () => ({ + apiSuccess: vi.fn((data: unknown) => ({ status: 200, json: async () => ({ success: true, data }), })), - apiUnauthorized: jest.fn(() => ({ + apiUnauthorized: vi.fn(() => ({ status: 401, json: async () => ({ success: false }), })), - apiInternalError: jest.fn(() => ({ + apiInternalError: vi.fn(() => ({ status: 500, json: async () => ({ success: false }), })), })); -jest.mock('@/domain/payments/paymentFlowService', () => ({ - reconcilePaymentIntent: jest.fn(), +vi.mock('@/domain/payments/paymentFlowService', () => ({ + reconcilePaymentIntent: vi.fn(), })); const candidates: Array> = []; const polled: string[] = []; const orFilters: string[] = []; -jest.mock('@/lib/supabase/admin', () => ({ +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: () => ({ from: () => { const builder: Record = {}; @@ -52,27 +54,27 @@ jest.mock('@/lib/supabase/admin', () => ({ let isUpdate = false; let isIncompleteCheck = false; for (const m of ['select', 'in', 'order']) { - builder[m] = jest.fn(() => builder); + builder[m] = vi.fn(() => builder); } - builder.or = jest.fn((filter: string) => { + builder.or = vi.fn((filter: string) => { orFilters.push(filter); return builder; }); - builder.is = jest.fn(() => { + builder.is = vi.fn(() => { isIncompleteCheck = true; return builder; }); - builder.lt = jest.fn(() => builder); + builder.lt = vi.fn(() => builder); // Nothing half-settled in these fixtures: the incomplete check finds none, // so the assertions below stay about reconciliation. - builder.limit = jest.fn(() => + builder.limit = vi.fn(() => Promise.resolve({ data: isIncompleteCheck ? [] : candidates, error: null }) ); - builder.update = jest.fn(() => { + builder.update = vi.fn(() => { isUpdate = true; return builder; }); - builder.eq = jest.fn((_col: string, id: string) => { + builder.eq = vi.fn((_col: string, id: string) => { if (!isUpdate) { return builder; } @@ -84,7 +86,7 @@ jest.mock('@/lib/supabase/admin', () => ({ }), })); -const reconcileMock = reconcilePaymentIntent as jest.MockedFunction; +const reconcileMock = reconcilePaymentIntent as MockedFunction; /** * The jest env has no global web Request; the route only reads the @@ -101,11 +103,11 @@ function request(secret: string | null = 'right-secret'): Request { } async function body(res: unknown) { - return (await (res as { json: () => Promise<{ data?: Record }> }).json()); + return await (res as { json: () => Promise<{ data?: Record }> }).json(); } beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); candidates.length = 0; polled.length = 0; orFilters.length = 0; @@ -196,13 +198,14 @@ describe('payment reconciliation sweep', () => { }); it('keeps sweeping when one rail throws', async () => { - candidates.push({ id: 'pi-bad', payment_method: 'nwc' }, { id: 'pi-good', payment_method: 'nwc' }); - reconcileMock - .mockRejectedValueOnce(new Error('provider down')) - .mockResolvedValueOnce({ - status: STATUS.PAYMENT_INTENTS.PAID, - paid_at: new Date().toISOString(), - }); + candidates.push( + { id: 'pi-bad', payment_method: 'nwc' }, + { id: 'pi-good', payment_method: 'nwc' } + ); + reconcileMock.mockRejectedValueOnce(new Error('provider down')).mockResolvedValueOnce({ + status: STATUS.PAYMENT_INTENTS.PAID, + paid_at: new Date().toISOString(), + }); const res = await GET(request()); diff --git a/__tests__/unit/api/projects-id-api.test.ts b/__tests__/unit/api/projects-id-api.test.ts index 51e7f7e83..f0f59ef29 100644 --- a/__tests__/unit/api/projects-id-api.test.ts +++ b/__tests__/unit/api/projects-id-api.test.ts @@ -1,65 +1,65 @@ import { GET, PUT } from '@/app/api/projects/[id]/route'; -jest.mock('@/lib/supabase/server', () => ({ - createServerClient: jest.fn(), +vi.mock('@/lib/supabase/server', () => ({ + createServerClient: vi.fn(), })); -jest.mock('@/lib/api/standardResponse', () => ({ - apiSuccess: jest.fn((data: unknown) => ({ +vi.mock('@/lib/api/standardResponse', () => ({ + apiSuccess: vi.fn((data: unknown) => ({ status: 200, json: async () => ({ success: true, data }), })), - apiUnauthorized: jest.fn((message = 'Unauthorized') => ({ + apiUnauthorized: vi.fn((message = 'Unauthorized') => ({ status: 401, json: async () => ({ success: false, error: { message } }), })), - apiNotFound: jest.fn((message = 'Not found') => ({ + apiNotFound: vi.fn((message = 'Not found') => ({ status: 404, json: async () => ({ success: false, error: { message } }), })), - apiValidationError: jest.fn((message = 'Validation failed') => ({ + apiValidationError: vi.fn((message = 'Validation failed') => ({ status: 400, json: async () => ({ success: false, error: { message } }), })), - handleApiError: jest.fn(() => ({ + handleApiError: vi.fn(() => ({ status: 500, json: async () => ({ success: false, error: { message: 'Internal error' } }), })), - handleSupabaseError: jest.fn(() => ({ + handleSupabaseError: vi.fn(() => ({ status: 500, json: async () => ({ success: false, error: { message: 'DB error' } }), })), - apiForbidden: jest.fn((message = 'Forbidden') => ({ + apiForbidden: vi.fn((message = 'Forbidden') => ({ status: 403, json: async () => ({ success: false, error: { message } }), })), - apiRateLimited: jest.fn(() => ({ + apiRateLimited: vi.fn(() => ({ status: 429, json: async () => ({ success: false, error: { message: 'Rate limited' } }), })), - apiBadRequest: jest.fn((message = 'Bad request') => ({ + apiBadRequest: vi.fn((message = 'Bad request') => ({ status: 400, json: async () => ({ success: false, error: { message } }), })), })); -jest.mock('@/lib/rate-limit', () => ({ - rateLimit: jest.fn(), - rateLimitWriteAsync: jest.fn(), - createRateLimitResponse: jest.fn(() => new Response('rate limited', { status: 429 })), - applyRateLimitHeaders: jest.fn((response: Response) => response), +vi.mock('@/lib/rate-limit', () => ({ + rateLimit: vi.fn(), + rateLimitWriteAsync: vi.fn(), + createRateLimitResponse: vi.fn(() => new Response('rate limited', { status: 429 })), + applyRateLimitHeaders: vi.fn((response: Response) => response), })); -jest.mock('@/services/actors', () => ({ - checkOwnership: jest.fn(), +vi.mock('@/services/actors', () => ({ + checkOwnership: vi.fn(), })); -jest.mock('@/services/actors/getOrCreateUserActor', () => ({ - getOrCreateUserActor: jest.fn().mockResolvedValue({ id: 'a1' }), +vi.mock('@/services/actors/getOrCreateUserActor', () => ({ + getOrCreateUserActor: vi.fn().mockResolvedValue({ id: 'a1' }), })); -jest.mock('@/lib/api/auditLog', () => ({ - auditSuccess: jest.fn().mockResolvedValue(undefined), +vi.mock('@/lib/api/auditLog', () => ({ + auditSuccess: vi.fn().mockResolvedValue(undefined), AUDIT_ACTIONS: { PROJECT_CREATED: 'project_created', }, @@ -69,15 +69,17 @@ import { createServerClient } from '@/lib/supabase/server'; import { checkOwnership } from '@/services/actors'; import { rateLimit, rateLimitWriteAsync } from '@/lib/rate-limit'; +import type { Mock } from 'vitest'; + describe('Project [id] API workflow', () => { beforeEach(() => { - jest.clearAllMocks(); - (rateLimit as jest.Mock).mockResolvedValue({ success: true }); - (rateLimitWriteAsync as jest.Mock).mockResolvedValue({ + vi.clearAllMocks(); + (rateLimit as Mock).mockResolvedValue({ success: true }); + (rateLimitWriteAsync as Mock).mockResolvedValue({ success: true, resetTime: Date.now() + 60000, }); - (checkOwnership as jest.Mock).mockResolvedValue(true); + (checkOwnership as Mock).mockResolvedValue(true); }); it('GET returns project detail with profile mapping', async () => { @@ -97,31 +99,33 @@ describe('Project [id] API workflow', () => { }; const projectQuery = { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: project, error: null }), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: project, error: null }), } as any; const profileQuery = { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - maybeSingle: jest.fn().mockResolvedValue({ data: profile, error: null }), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + maybeSingle: vi.fn().mockResolvedValue({ data: profile, error: null }), } as any; const supabase = { auth: { - getUser: jest.fn().mockResolvedValue({ data: { user: null } }), + getUser: vi.fn().mockResolvedValue({ data: { user: null } }), }, - from: jest + from: vi .fn() .mockImplementationOnce(() => projectQuery) .mockImplementationOnce(() => profileQuery), }; - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); const request = {}; - const response = await GET(request as any, { params: { id: '00000000-0000-0000-0000-000000000001' } }); + const response = await GET(request as any, { + params: { id: '00000000-0000-0000-0000-000000000001' }, + }); const body = await response.json(); expect(response.status).toBe(200); @@ -145,38 +149,40 @@ describe('Project [id] API workflow', () => { }; const fetchQuery = { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: existing, error: null }), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: existing, error: null }), } as any; const updateQuery = { - update: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - select: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: updated, error: null }), + update: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + select: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: updated, error: null }), } as any; const supabase = { auth: { - getUser: jest.fn().mockResolvedValue({ data: { user: { id: 'u1' } }, error: null }), + getUser: vi.fn().mockResolvedValue({ data: { user: { id: 'u1' } }, error: null }), }, - from: jest + from: vi .fn() .mockImplementationOnce(() => fetchQuery) .mockImplementationOnce(() => updateQuery), }; - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); const request = { - json: jest.fn().mockResolvedValue({ + json: vi.fn().mockResolvedValue({ title: 'Updated Title', description: 'Updated description', }), }; - const response = await PUT(request as any, { params: { id: '00000000-0000-0000-0000-000000000001' } }); + const response = await PUT(request as any, { + params: { id: '00000000-0000-0000-0000-000000000001' }, + }); const body = await response.json(); expect(response.status).toBe(200); @@ -185,7 +191,7 @@ describe('Project [id] API workflow', () => { }); it('PUT rejects updates to project owned by another user', async () => { - (checkOwnership as jest.Mock).mockResolvedValueOnce(false); + (checkOwnership as Mock).mockResolvedValueOnce(false); const existing = { id: '00000000-0000-0000-0000-000000000001', user_id: 'someone-else', @@ -194,25 +200,27 @@ describe('Project [id] API workflow', () => { }; const fetchQuery = { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: existing, error: null }), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: existing, error: null }), } as any; const supabase = { auth: { - getUser: jest.fn().mockResolvedValue({ data: { user: { id: 'u1' } }, error: null }), + getUser: vi.fn().mockResolvedValue({ data: { user: { id: 'u1' } }, error: null }), }, - from: jest.fn().mockImplementation(() => fetchQuery), + from: vi.fn().mockImplementation(() => fetchQuery), }; - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); const request = { - json: jest.fn().mockResolvedValue({ title: 'Should Not Update' }), + json: vi.fn().mockResolvedValue({ title: 'Should Not Update' }), }; - const response = await PUT(request as any, { params: { id: '00000000-0000-0000-0000-000000000001' } }); + const response = await PUT(request as any, { + params: { id: '00000000-0000-0000-0000-000000000001' }, + }); const body = await response.json(); expect(response.status).toBe(403); diff --git a/__tests__/unit/api/receive-request.test.ts b/__tests__/unit/api/receive-request.test.ts index 692c6285c..3c2a359de 100644 --- a/__tests__/unit/api/receive-request.test.ts +++ b/__tests__/unit/api/receive-request.test.ts @@ -17,47 +17,49 @@ import { import { initiateTip } from '@/domain/payments/paymentFlowService'; import { RECEIVE_MAX_BTC } from '@/config/receive'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/api/withAuth', () => ({ +vi.mock('@/lib/api/withAuth', () => ({ withAuth: (handler: (req: unknown) => Promise) => (req: unknown): Promise => handler(Object.assign(req as object, { user: { id: 'owner-1' }, supabase: {} })), })); -jest.mock('@/lib/rate-limit', () => ({ - rateLimitWriteAsync: jest.fn().mockResolvedValue({ success: true }), +vi.mock('@/lib/rate-limit', () => ({ + rateLimitWriteAsync: vi.fn().mockResolvedValue({ success: true }), retryAfterSeconds: () => 0, })); -jest.mock('@/lib/api/standardResponse', () => ({ - apiSuccess: jest.fn((data: unknown) => ({ status: 200, data })), - apiBadRequest: jest.fn((error: string) => ({ status: 400, error })), - apiRateLimited: jest.fn(() => ({ status: 429 })), - apiInternalError: jest.fn(() => ({ status: 500 })), +vi.mock('@/lib/api/standardResponse', () => ({ + apiSuccess: vi.fn((data: unknown) => ({ status: 200, data })), + apiBadRequest: vi.fn((error: string) => ({ status: 400, error })), + apiRateLimited: vi.fn(() => ({ status: 429 })), + apiInternalError: vi.fn(() => ({ status: 500 })), })); -jest.mock('@/lib/supabase/admin', () => ({ - getAdminClient: jest.fn(() => ({ - from: jest.fn(() => ({ - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - maybeSingle: jest +vi.mock('@/lib/supabase/admin', () => ({ + getAdminClient: vi.fn(() => ({ + from: vi.fn(() => ({ + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + maybeSingle: vi .fn() .mockResolvedValue({ data: { username: 'lena', display_name: 'Lena' }, error: null }), })), })), })); -jest.mock('@/domain/payments/walletResolutionService', () => ({ - resolveUserWallet: jest.fn(), - resolveSpecificUserWallet: jest.fn(), +vi.mock('@/domain/payments/walletResolutionService', () => ({ + resolveUserWallet: vi.fn(), + resolveSpecificUserWallet: vi.fn(), })); -jest.mock('@/domain/payments/paymentFlowService', () => ({ - initiateTip: jest.fn(), +vi.mock('@/domain/payments/paymentFlowService', () => ({ + initiateTip: vi.fn(), })); -const resolvePrimaryMock = resolveUserWallet as jest.Mock; -const resolveSpecificMock = resolveSpecificUserWallet as jest.Mock; -const initiateTipMock = initiateTip as jest.Mock; +const resolvePrimaryMock = resolveUserWallet as Mock; +const resolveSpecificMock = resolveSpecificUserWallet as Mock; +const initiateTipMock = initiateTip as Mock; const WALLET = { method: 'lightning_address', wallet_id: 'w1', lightning_address: 'a@b.c' }; const TIP_RESULT = { @@ -73,7 +75,7 @@ function makeRequest(body: unknown) { } beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); initiateTipMock.mockResolvedValue(TIP_RESULT); }); diff --git a/__tests__/unit/api/research-id-api.test.ts b/__tests__/unit/api/research-id-api.test.ts index a67219c93..5400475f8 100644 --- a/__tests__/unit/api/research-id-api.test.ts +++ b/__tests__/unit/api/research-id-api.test.ts @@ -8,43 +8,43 @@ import { GET, PUT, DELETE } from '@/app/api/research/[id]/route'; -jest.mock('@/lib/supabase/server', () => ({ - createServerClient: jest.fn(), +vi.mock('@/lib/supabase/server', () => ({ + createServerClient: vi.fn(), })); -jest.mock('@/lib/api/standardResponse', () => ({ - apiSuccess: jest.fn((data: unknown) => ({ +vi.mock('@/lib/api/standardResponse', () => ({ + apiSuccess: vi.fn((data: unknown) => ({ status: 200, json: async () => ({ success: true, data }), })), - apiUnauthorized: jest.fn((message = 'Unauthorized') => ({ + apiUnauthorized: vi.fn((message = 'Unauthorized') => ({ status: 401, json: async () => ({ success: false, error: { message } }), })), - apiNotFound: jest.fn((message = 'Not found') => ({ + apiNotFound: vi.fn((message = 'Not found') => ({ status: 404, json: async () => ({ success: false, error: { message } }), })), - apiForbidden: jest.fn((message = 'Forbidden') => ({ + apiForbidden: vi.fn((message = 'Forbidden') => ({ status: 403, json: async () => ({ success: false, error: { message } }), })), - apiBadRequest: jest.fn((message = 'Bad request') => ({ + apiBadRequest: vi.fn((message = 'Bad request') => ({ status: 400, json: async () => ({ success: false, error: { message } }), })), - apiRateLimited: jest.fn(() => ({ + apiRateLimited: vi.fn(() => ({ status: 429, json: async () => ({ success: false, error: { message: 'Rate limited' } }), })), - handleApiError: jest.fn(() => ({ + handleApiError: vi.fn(() => ({ status: 500, json: async () => ({ success: false, error: { message: 'Internal error' } }), })), })); -jest.mock('@/lib/rate-limit', () => ({ - rateLimitWriteAsync: jest.fn().mockResolvedValue({ +vi.mock('@/lib/rate-limit', () => ({ + rateLimitWriteAsync: vi.fn().mockResolvedValue({ success: true, resetTime: Date.now() + 60000, }), @@ -53,6 +53,8 @@ jest.mock('@/lib/rate-limit', () => ({ import { createServerClient } from '@/lib/supabase/server'; import { rateLimitWriteAsync } from '@/lib/rate-limit'; +import type { Mock } from 'vitest'; + const RESEARCH_ID = '00000000-0000-0000-0000-000000000001'; const OWNER_USER_ID = 'user-owner-001'; const OTHER_USER_ID = 'user-other-002'; @@ -73,22 +75,22 @@ function makeResearch(overrides: Record = {}) { /** Build a Supabase mock that returns the given research entity */ function makeSupabase(userId: string, entity: Record | null) { - const single = jest.fn().mockResolvedValue({ + const single = vi.fn().mockResolvedValue({ data: entity, error: entity ? null : { code: 'PGRST116' }, }); const query = { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - order: jest.fn().mockReturnThis(), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + order: vi.fn().mockReturnThis(), single, } as any; return { auth: { - getUser: jest.fn().mockResolvedValue({ data: { user: { id: userId } }, error: null }), + getUser: vi.fn().mockResolvedValue({ data: { user: { id: userId } }, error: null }), }, - from: jest.fn().mockReturnValue(query), + from: vi.fn().mockReturnValue(query), _query: query, }; } @@ -97,8 +99,8 @@ const makeParams = (id = RESEARCH_ID) => ({ params: Promise.resolve({ id }) }); describe('Research [id] API', () => { beforeEach(() => { - jest.clearAllMocks(); - (rateLimitWriteAsync as jest.Mock).mockResolvedValue({ + vi.clearAllMocks(); + (rateLimitWriteAsync as Mock).mockResolvedValue({ success: true, resetTime: Date.now() + 60000, }); @@ -111,16 +113,16 @@ describe('Research [id] API', () => { // GET uses withOptionalAuth — no user returned for anonymous const supabase = makeSupabase('', entity); // withOptionalAuth may return user: null; mock returns empty user - supabase.auth.getUser = jest.fn().mockResolvedValue({ data: { user: null }, error: null }); + supabase.auth.getUser = vi.fn().mockResolvedValue({ data: { user: null }, error: null }); // Also need related data mocks (progress_updates, votes, contributions) - supabase.from = jest.fn().mockReturnValue({ - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - order: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: entity, error: null }), + supabase.from = vi.fn().mockReturnValue({ + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + order: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: entity, error: null }), }); - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); const response = await GET({} as any, makeParams()); const body = await response.json(); @@ -132,14 +134,14 @@ describe('Research [id] API', () => { it('blocks access to private research for non-owner', async () => { const entity = makeResearch({ is_public: false, user_id: OWNER_USER_ID }); const supabase = makeSupabase(OTHER_USER_ID, entity); - supabase.from = jest.fn().mockReturnValue({ - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - order: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: entity, error: null }), + supabase.from = vi.fn().mockReturnValue({ + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + order: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: entity, error: null }), }); - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); const response = await GET({} as any, makeParams()); const body = await response.json(); @@ -150,13 +152,13 @@ describe('Research [id] API', () => { it('returns 404 when research does not exist', async () => { const supabase = makeSupabase(OWNER_USER_ID, null); - supabase.from = jest.fn().mockReturnValue({ - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: null, error: { code: 'PGRST116' } }), + supabase.from = vi.fn().mockReturnValue({ + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: null, error: { code: 'PGRST116' } }), }); - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); const response = await GET({} as any, makeParams()); const body = await response.json(); @@ -182,32 +184,34 @@ describe('Research [id] API', () => { let callCount = 0; const supabase = { auth: { - getUser: jest.fn().mockResolvedValue({ data: { user: { id: OWNER_USER_ID } }, error: null }), + getUser: vi + .fn() + .mockResolvedValue({ data: { user: { id: OWNER_USER_ID } }, error: null }), }, - from: jest.fn().mockImplementation(() => { + from: vi.fn().mockImplementation(() => { callCount++; if (callCount === 1) { // verifyResearchOwner: returns entity with user_id return { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: existing, error: null }), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: existing, error: null }), }; } // update call return { - update: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - select: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: updated, error: null }), + update: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + select: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: updated, error: null }), }; }), }; - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); const response = await PUT( - { json: jest.fn().mockResolvedValue(validUpdate) } as any, + { json: vi.fn().mockResolvedValue(validUpdate) } as any, makeParams() ); const body = await response.json(); @@ -222,19 +226,21 @@ describe('Research [id] API', () => { const supabase = { auth: { - getUser: jest.fn().mockResolvedValue({ data: { user: { id: OTHER_USER_ID } }, error: null }), + getUser: vi + .fn() + .mockResolvedValue({ data: { user: { id: OTHER_USER_ID } }, error: null }), }, - from: jest.fn().mockReturnValue({ - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: existing, error: null }), + from: vi.fn().mockReturnValue({ + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: existing, error: null }), }), }; - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); const response = await PUT( - { json: jest.fn().mockResolvedValue(validUpdate) } as any, + { json: vi.fn().mockResolvedValue(validUpdate) } as any, makeParams() ); const body = await response.json(); @@ -251,25 +257,27 @@ describe('Research [id] API', () => { let callCount = 0; const supabase = { auth: { - getUser: jest.fn().mockResolvedValue({ data: { user: { id: OWNER_USER_ID } }, error: null }), + getUser: vi + .fn() + .mockResolvedValue({ data: { user: { id: OWNER_USER_ID } }, error: null }), }, - from: jest.fn().mockImplementation(() => { + from: vi.fn().mockImplementation(() => { callCount++; if (callCount === 1) { return { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: existing, error: null }), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: existing, error: null }), }; } return { - delete: jest.fn().mockReturnThis(), - eq: jest.fn().mockResolvedValue({ error: null }), + delete: vi.fn().mockReturnThis(), + eq: vi.fn().mockResolvedValue({ error: null }), }; }), }; - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); const response = await DELETE({} as any, makeParams()); const body = await response.json(); @@ -283,16 +291,18 @@ describe('Research [id] API', () => { const supabase = { auth: { - getUser: jest.fn().mockResolvedValue({ data: { user: { id: OWNER_USER_ID } }, error: null }), + getUser: vi + .fn() + .mockResolvedValue({ data: { user: { id: OWNER_USER_ID } }, error: null }), }, - from: jest.fn().mockReturnValue({ - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: existing, error: null }), + from: vi.fn().mockReturnValue({ + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: existing, error: null }), }), }; - (createServerClient as jest.Mock).mockResolvedValue(supabase); + (createServerClient as Mock).mockResolvedValue(supabase); const response = await DELETE({} as any, makeParams()); const body = await response.json(); diff --git a/__tests__/unit/api/services-api.test.ts b/__tests__/unit/api/services-api.test.ts index 8fbe1d25c..ba09d2ae5 100644 --- a/__tests__/unit/api/services-api.test.ts +++ b/__tests__/unit/api/services-api.test.ts @@ -2,41 +2,41 @@ import { POST } from '@/app/api/services/route'; import { createService } from '@/domain/commerce/service'; // Mock the dependencies -jest.mock('@/lib/supabase/server', () => ({ - createServerClient: jest.fn(), +vi.mock('@/lib/supabase/server', () => ({ + createServerClient: vi.fn(), })); -jest.mock('@/domain/commerce/service', () => ({ - createService: jest.fn(), +vi.mock('@/domain/commerce/service', () => ({ + createService: vi.fn(), })); -jest.mock('@/lib/api/standardResponse', () => ({ - apiSuccess: jest.fn(), - apiUnauthorized: jest.fn(), - apiInternalError: jest.fn(), - apiRateLimited: jest.fn(), - apiValidationError: jest.fn(), - handleApiError: jest.fn(), +vi.mock('@/lib/api/standardResponse', () => ({ + apiSuccess: vi.fn(), + apiUnauthorized: vi.fn(), + apiInternalError: vi.fn(), + apiRateLimited: vi.fn(), + apiValidationError: vi.fn(), + handleApiError: vi.fn(), })); -jest.mock('@/utils/logger', () => ({ +vi.mock('@/utils/logger', () => ({ logger: { - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), }, })); -jest.mock('@/lib/rate-limit', () => ({ - rateLimitWriteAsync: jest.fn(), - applyRateLimitHeaders: jest.fn(response => response), +vi.mock('@/lib/rate-limit', () => ({ + rateLimitWriteAsync: vi.fn(), + applyRateLimitHeaders: vi.fn(response => response), })); // Handler now routes through resolveCreationActor (added in the actor-switcher // commit b17b2534). Mock it so the entity create path proceeds without needing // a real actors table. -jest.mock('@/services/actors/resolveCreationActor', () => ({ - resolveCreationActor: jest.fn().mockResolvedValue({ id: 'actor-123' }), +vi.mock('@/services/actors/resolveCreationActor', () => ({ + resolveCreationActor: vi.fn().mockResolvedValue({ id: 'actor-123' }), ActorNotPermittedError: class ActorNotPermittedError extends Error {}, })); @@ -49,9 +49,11 @@ import { } from '@/lib/api/standardResponse'; import { rateLimitWriteAsync, applyRateLimitHeaders } from '@/lib/rate-limit'; +import type { Mock } from 'vitest'; + const mockSupabase = { auth: { - getUser: jest.fn(), + getUser: vi.fn(), }, }; @@ -62,17 +64,17 @@ const mockRateLimit = { describe('Services API - POST', () => { beforeEach(() => { - jest.clearAllMocks(); - (createServerClient as jest.Mock).mockResolvedValue(mockSupabase); - (rateLimitWriteAsync as jest.Mock).mockResolvedValue(mockRateLimit); - (apiSuccess as jest.Mock).mockImplementation((data, options) => ({ + vi.clearAllMocks(); + (createServerClient as Mock).mockResolvedValue(mockSupabase); + (rateLimitWriteAsync as Mock).mockResolvedValue(mockRateLimit); + (apiSuccess as Mock).mockImplementation((data, options) => ({ data, options, status: 201, })); - (apiUnauthorized as jest.Mock).mockReturnValue({ error: 'Unauthorized', status: 401 }); - (apiRateLimited as jest.Mock).mockReturnValue({ error: 'Rate limited', status: 429 }); - (handleApiError as jest.Mock).mockImplementation(error => ({ + (apiUnauthorized as Mock).mockReturnValue({ error: 'Unauthorized', status: 401 }); + (apiRateLimited as Mock).mockReturnValue({ error: 'Rate limited', status: 429 }); + (handleApiError as Mock).mockImplementation(error => ({ error: error.message, status: 500, })); @@ -95,11 +97,11 @@ describe('Services API - POST', () => { mockSupabase.auth.getUser.mockResolvedValue({ data: { user: mockUser }, error: null }); // Mock service creation - (createService as jest.Mock).mockResolvedValue(mockCreatedService); + (createService as Mock).mockResolvedValue(mockCreatedService); // Create mock NextRequest with proper json method const mockRequest = { - json: jest.fn().mockResolvedValue(mockServiceData), + json: vi.fn().mockResolvedValue(mockServiceData), headers: new Headers(), } as any; @@ -117,7 +119,7 @@ describe('Services API - POST', () => { mockSupabase.auth.getUser.mockResolvedValue({ data: { user: null }, error: null }); const mockRequest = { - json: jest.fn().mockResolvedValue({ title: 'Test', category: 'Other', fixed_price: 1000 }), + json: vi.fn().mockResolvedValue({ title: 'Test', category: 'Other', fixed_price: 1000 }), headers: new Headers(), } as any; @@ -134,13 +136,13 @@ describe('Services API - POST', () => { mockSupabase.auth.getUser.mockResolvedValue({ data: { user: mockUser }, error: null }); // Mock rate limit exceeded - (rateLimitWriteAsync as jest.Mock).mockResolvedValue({ + (rateLimitWriteAsync as Mock).mockResolvedValue({ success: false, resetTime: Date.now() + 60000, // 1 minute from now }); const mockRequest = { - json: jest.fn().mockResolvedValue({ title: 'Test', category: 'Other', fixed_price: 1000 }), + json: vi.fn().mockResolvedValue({ title: 'Test', category: 'Other', fixed_price: 1000 }), headers: new Headers(), } as any; @@ -167,10 +169,10 @@ describe('Services API - POST', () => { mockSupabase.auth.getUser.mockResolvedValue({ data: { user: mockUser }, error: null }); // Mock service creation error - (createService as jest.Mock).mockRejectedValue(mockError); + (createService as Mock).mockRejectedValue(mockError); const mockRequest = { - json: jest.fn().mockResolvedValue(serviceData), + json: vi.fn().mockResolvedValue(serviceData), headers: new Headers(), } as any; @@ -187,7 +189,7 @@ describe('Services API - POST', () => { mockSupabase.auth.getUser.mockResolvedValue({ data: { user: null }, error: mockAuthError }); const mockRequest = { - json: jest.fn().mockResolvedValue({ title: 'Test', category: 'Other', fixed_price: 1000 }), + json: vi.fn().mockResolvedValue({ title: 'Test', category: 'Other', fixed_price: 1000 }), headers: new Headers(), } as any; diff --git a/__tests__/unit/api/services.test.ts b/__tests__/unit/api/services.test.ts index 5fd58ba6a..2d7e9c844 100644 --- a/__tests__/unit/api/services.test.ts +++ b/__tests__/unit/api/services.test.ts @@ -3,27 +3,29 @@ import { userServiceSchema } from '@/lib/validation'; import { PLATFORM_DEFAULT_CURRENCY } from '@/config/currencies'; // Mock the Supabase admin client (createService uses createAdminClient, not createServerClient) -jest.mock('@/lib/supabase/admin', () => ({ - createAdminClient: jest.fn(), +vi.mock('@/lib/supabase/admin', () => ({ + createAdminClient: vi.fn(), })); -jest.mock('@/services/actors/getOrCreateUserActor', () => ({ - getOrCreateUserActor: jest.fn().mockResolvedValue({ id: 'a1' }), +vi.mock('@/services/actors/getOrCreateUserActor', () => ({ + getOrCreateUserActor: vi.fn().mockResolvedValue({ id: 'a1' }), })); import { createAdminClient } from '@/lib/supabase/admin'; +import type { Mock } from 'vitest'; + const mockSupabase = { - from: jest.fn().mockReturnThis(), - insert: jest.fn().mockReturnThis(), - select: jest.fn().mockReturnThis(), - single: jest.fn(), + from: vi.fn().mockReturnThis(), + insert: vi.fn().mockReturnThis(), + select: vi.fn().mockReturnThis(), + single: vi.fn(), }; describe('Service Creation', () => { beforeEach(() => { - jest.clearAllMocks(); - (createAdminClient as jest.Mock).mockReturnValue(mockSupabase); + vi.clearAllMocks(); + (createAdminClient as Mock).mockReturnValue(mockSupabase); }); describe('userServiceSchema validation', () => { diff --git a/__tests__/unit/api/standardResponse.contract.test.ts b/__tests__/unit/api/standardResponse.contract.test.ts index 10ebb9b27..d42209038 100644 --- a/__tests__/unit/api/standardResponse.contract.test.ts +++ b/__tests__/unit/api/standardResponse.contract.test.ts @@ -15,9 +15,9 @@ */ // Provide a real-ish NextResponse.json so the helpers produce parseable objects. -// The global __mocks__/next-server.js mock returns jest.fn() (→ undefined), which +// The global __mocks__/next-server.js mock returns vi.fn() (→ undefined), which // prevents calling .json() on the result. Override it here with an implementation. -jest.mock('next/server', () => ({ +vi.mock('next/server', () => ({ NextResponse: { json: (data: unknown, init?: ResponseInit & { headers?: HeadersInit }) => { const headerMap = new Headers(init?.headers); @@ -27,13 +27,13 @@ jest.mock('next/server', () => ({ json: async () => data, }; }, - redirect: jest.fn(), - next: jest.fn(), + redirect: vi.fn(), + next: vi.fn(), }, })); -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); import { diff --git a/__tests__/unit/api/v1-pay-l402.test.ts b/__tests__/unit/api/v1-pay-l402.test.ts index d5e2e5758..d422a9158 100644 --- a/__tests__/unit/api/v1-pay-l402.test.ts +++ b/__tests__/unit/api/v1-pay-l402.test.ts @@ -12,13 +12,13 @@ import { buildL402ChallengeHeader, } from '@/domain/payments/l402-codec'; -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); // Route tests: mock the response layer (NextResponse unavailable in jest) and // the domain flows; exercise branch selection + status codes. -jest.mock('@/lib/api/standardResponse', () => ({ +vi.mock('@/lib/api/standardResponse', () => ({ apiSuccess: (data: unknown, _opts?: unknown) => ({ status: 200, json: async () => ({ success: true, data }), @@ -55,17 +55,17 @@ jest.mock('@/lib/api/standardResponse', () => ({ }, })); -const mockCreateChallenge = jest.fn(); -const mockVerify = jest.fn(); -jest.mock('@/domain/payments/l402', () => ({ +const mockCreateChallenge = vi.fn(); +const mockVerify = vi.fn(); +vi.mock('@/domain/payments/l402', () => ({ createL402Challenge: (...args: unknown[]) => mockCreateChallenge(...args), verifyL402Payment: (...args: unknown[]) => mockVerify(...args), })); -jest.mock('@/lib/supabase/public', () => ({ createPublicClient: () => ({ _kind: 'public' }) })); -jest.mock('@/lib/rate-limit', () => ({ - rateLimitWriteAsync: jest.fn().mockResolvedValue({ success: true }), - rateLimitPaymentRecipient: jest.fn().mockResolvedValue({ success: true }), - rateLimitL402Verify: jest.fn().mockResolvedValue({ success: true }), +vi.mock('@/lib/supabase/public', () => ({ createPublicClient: () => ({ _kind: 'public' }) })); +vi.mock('@/lib/rate-limit', () => ({ + rateLimitWriteAsync: vi.fn().mockResolvedValue({ success: true }), + rateLimitPaymentRecipient: vi.fn().mockResolvedValue({ success: true }), + rateLimitL402Verify: vi.fn().mockResolvedValue({ success: true }), retryAfterSeconds: () => 1, })); @@ -76,6 +76,8 @@ import { rateLimitWriteAsync, } from '@/lib/rate-limit'; +import type { Mock } from 'vitest'; + const ENTITY_ID = '11111111-2222-3333-4444-555555555555'; const params = Promise.resolve({ entity_type: 'product', entity_id: ENTITY_ID }); @@ -241,7 +243,7 @@ describe('GET /api/v1/pay/{type}/{id}', () => { */ describe('per-recipient invoice-spam limit', () => { beforeEach(() => { - (rateLimitPaymentRecipient as jest.Mock).mockResolvedValue({ success: true }); + (rateLimitPaymentRecipient as Mock).mockResolvedValue({ success: true }); }); it('keys the limit on the recipient, not only the caller', async () => { @@ -250,7 +252,7 @@ describe('per-recipient invoice-spam limit', () => { }); it('refuses with 429 when that recipient is already being hammered', async () => { - (rateLimitPaymentRecipient as jest.Mock).mockResolvedValue({ success: false }); + (rateLimitPaymentRecipient as Mock).mockResolvedValue({ success: false }); const res = await GET(makeRequest('https://x.test/api/v1/pay/product/' + ENTITY_ID), { params, }); @@ -275,8 +277,8 @@ describe('L402 verify-retry limit', () => { const AUTH = { authorization: `L402 ${ENTITY_ID}.tok_abc:${'a'.repeat(64)}` }; beforeEach(() => { - (rateLimitL402Verify as jest.Mock).mockResolvedValue({ success: true }); - (rateLimitWriteAsync as jest.Mock).mockResolvedValue({ success: true }); + (rateLimitL402Verify as Mock).mockResolvedValue({ success: true }); + (rateLimitWriteAsync as Mock).mockResolvedValue({ success: true }); mockVerify.mockResolvedValue({ ok: false, status: 'pending' }); }); @@ -286,7 +288,7 @@ describe('L402 verify-retry limit', () => { }); it('refuses with 429 once one token has hammered the relay', async () => { - (rateLimitL402Verify as jest.Mock).mockResolvedValue({ success: false }); + (rateLimitL402Verify as Mock).mockResolvedValue({ success: false }); const res = await GET(makeRequest('https://x.test/api/v1/pay/product/' + ENTITY_ID, AUTH), { params, }); diff --git a/__tests__/unit/api/v1-payments.test.ts b/__tests__/unit/api/v1-payments.test.ts index 83c198c42..fccde70ad 100644 --- a/__tests__/unit/api/v1-payments.test.ts +++ b/__tests__/unit/api/v1-payments.test.ts @@ -11,82 +11,84 @@ import { resolveRequestAuth } from '@/lib/api/resolveRequestAuth'; import { initiatePayment } from '@/domain/payments'; import type { NextRequest } from 'next/server'; -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/api/resolveRequestAuth', () => ({ - ...jest.requireActual('@/lib/api/resolveRequestAuth'), - resolveRequestAuth: jest.fn(), +vi.mock('@/lib/api/resolveRequestAuth', async () => ({ + ...((await vi.importActual('@/lib/api/resolveRequestAuth')) as object), + resolveRequestAuth: vi.fn(), })); // NextResponse is unavailable in the jest env — repo convention is to mock the // response helpers with plain status/json shims (see projects-id-api.test.ts). -jest.mock('@/lib/api/standardResponse', () => ({ - apiSuccess: jest.fn((data: unknown, opts?: { status?: number }) => ({ +vi.mock('@/lib/api/standardResponse', () => ({ + apiSuccess: vi.fn((data: unknown, opts?: { status?: number }) => ({ status: opts?.status ?? 200, json: async () => ({ success: true, data }), })), - apiUnauthorized: jest.fn(() => ({ + apiUnauthorized: vi.fn(() => ({ status: 401, json: async () => ({ success: false, error: { message: 'Unauthorized' } }), })), - apiForbidden: jest.fn((message = 'Forbidden') => ({ + apiForbidden: vi.fn((message = 'Forbidden') => ({ status: 403, json: async () => ({ success: false, error: { message } }), })), - apiNotFound: jest.fn((message = 'Not found') => ({ + apiNotFound: vi.fn((message = 'Not found') => ({ status: 404, json: async () => ({ success: false, error: { message } }), })), - apiBadRequest: jest.fn((message = 'Bad request') => ({ + apiBadRequest: vi.fn((message = 'Bad request') => ({ status: 400, json: async () => ({ success: false, error: { message } }), })), - apiRateLimited: jest.fn(() => ({ + apiRateLimited: vi.fn(() => ({ status: 429, json: async () => ({ success: false, error: { message: 'Rate limited' } }), })), - apiInternalError: jest.fn((message = 'Internal error') => ({ + apiInternalError: vi.fn((message = 'Internal error') => ({ status: 500, json: async () => ({ success: false, error: { message } }), })), })); -jest.mock('@/domain/payments', () => ({ - initiatePayment: jest.fn(), +vi.mock('@/domain/payments', () => ({ + initiatePayment: vi.fn(), })); -jest.mock('@/lib/rate-limit', () => ({ - rateLimitWriteAsync: jest.fn().mockResolvedValue({ success: true }), - rateLimitPaymentRecipient: jest.fn().mockResolvedValue({ success: true }), - rateLimitIntegrationKeyWrite: jest.fn().mockResolvedValue({ success: true }), - rateLimitIntegrationKeyRead: jest.fn().mockResolvedValue({ success: true }), - retryAfterSeconds: jest.fn().mockReturnValue(30), +vi.mock('@/lib/rate-limit', () => ({ + rateLimitWriteAsync: vi.fn().mockResolvedValue({ success: true }), + rateLimitPaymentRecipient: vi.fn().mockResolvedValue({ success: true }), + rateLimitIntegrationKeyWrite: vi.fn().mockResolvedValue({ success: true }), + rateLimitIntegrationKeyRead: vi.fn().mockResolvedValue({ success: true }), + retryAfterSeconds: vi.fn().mockReturnValue(30), })); // Public client controls the anonymous-visibility gate for key auth. -const mockPublicMaybeSingle = jest.fn(); -jest.mock('@/lib/supabase/public', () => ({ - createPublicClient: jest.fn(() => ({ - from: jest.fn(() => ({ - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), +const mockPublicMaybeSingle = vi.fn(); +vi.mock('@/lib/supabase/public', () => ({ + createPublicClient: vi.fn(() => ({ + from: vi.fn(() => ({ + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), maybeSingle: mockPublicMaybeSingle, })), })), })); -jest.mock('@/lib/supabase/server', () => ({ - createServerClient: jest.fn(async () => ({ _kind: 'session-client' })), +vi.mock('@/lib/supabase/server', () => ({ + createServerClient: vi.fn(async () => ({ _kind: 'session-client' })), })); -jest.mock('@/lib/supabase/admin', () => ({ - createAdminClient: jest.fn(() => ({ _kind: 'admin-client' })), +vi.mock('@/lib/supabase/admin', () => ({ + createAdminClient: vi.fn(() => ({ _kind: 'admin-client' })), })); -const mockResolveRequestAuth = resolveRequestAuth as jest.Mock; -const mockInitiatePayment = initiatePayment as jest.Mock; +const mockResolveRequestAuth = resolveRequestAuth as Mock; +const mockInitiatePayment = initiatePayment as Mock; const ENTITY_ID = '11111111-2222-3333-4444-555555555555'; @@ -110,7 +112,7 @@ function keyAuth(scopes: string[]) { describe('POST /api/v1/payments', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); mockPublicMaybeSingle.mockResolvedValue({ data: { id: ENTITY_ID } }); mockInitiatePayment.mockResolvedValue({ payment_intent: { id: 'pi-1', status: 'invoice_ready' }, @@ -209,7 +211,7 @@ describe('POST /api/v1/payments', () => { describe('OpenAPI spec — payment paths', () => { it('includes the machine-payable loop endpoints', async () => { // Imported lazily so the route-level mocks above don't interfere. - const { getOpenApiSpec } = jest.requireActual('@/lib/openapi/generator') as { + const { getOpenApiSpec } = (await vi.importActual('@/lib/openapi/generator')) as { getOpenApiSpec: () => { paths: Record> }; }; const spec = getOpenApiSpec(); diff --git a/__tests__/unit/billing/getUserPlan.test.ts b/__tests__/unit/billing/getUserPlan.test.ts index 6e5e71307..bdbe37887 100644 --- a/__tests__/unit/billing/getUserPlan.test.ts +++ b/__tests__/unit/billing/getUserPlan.test.ts @@ -5,10 +5,10 @@ import { getUserPlan } from '@/services/billing/getUserPlan'; * .eq('user_id', uid).maybeSingle()` to the given { data, error } pair. */ function mockSupabase(result: { data: unknown; error: unknown }) { - const maybeSingle = jest.fn().mockResolvedValue(result); - const eq = jest.fn().mockReturnValue({ maybeSingle }); - const select = jest.fn().mockReturnValue({ eq }); - const from = jest.fn().mockReturnValue({ select }); + const maybeSingle = vi.fn().mockResolvedValue(result); + const eq = vi.fn().mockReturnValue({ maybeSingle }); + const select = vi.fn().mockReturnValue({ eq }); + const from = vi.fn().mockReturnValue({ select }); // eslint-disable-next-line @typescript-eslint/no-explicit-any return { from } as any; } diff --git a/__tests__/unit/cat/__snapshots__/context-string-builder.snapshot.test.ts.snap b/__tests__/unit/cat/__snapshots__/context-string-builder.snapshot.test.ts.snap index 9356fb947..de599608a 100644 --- a/__tests__/unit/cat/__snapshots__/context-string-builder.snapshot.test.ts.snap +++ b/__tests__/unit/cat/__snapshots__/context-string-builder.snapshot.test.ts.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`buildFullContextString — full-output snapshot renders every section identically (byte-for-byte) 1`] = ` +exports[`buildFullContextString — full-output snapshot > renders every section identically (byte-for-byte) 1`] = ` "# User Context for Personalized Advice ## Current Session diff --git a/__tests__/unit/cat/action-executor-columns.test.ts b/__tests__/unit/cat/action-executor-columns.test.ts index bdab8fcc9..67fa03ff9 100644 --- a/__tests__/unit/cat/action-executor-columns.test.ts +++ b/__tests__/unit/cat/action-executor-columns.test.ts @@ -17,18 +17,23 @@ import { CatActionExecutor } from '@/services/cat/action-executor'; import { ENTITY_REGISTRY } from '@/config/entity-registry'; import { DATABASE_TABLES } from '@/config/database-tables'; +import type { Mock } from 'vitest'; + // ── Mock CatPermissionService ───────────────────────────────────────────────── // Auto-allow every action: allowed=true, requiresConfirmation=false -jest.mock('@/services/cat/permission-service', () => ({ - CatPermissionService: jest.fn().mockImplementation(() => ({ - checkPermission: jest.fn().mockResolvedValue({ allowed: true, requiresConfirmation: false }), - checkSpendCaps: jest.fn().mockResolvedValue({ allowed: true }), - })), +vi.mock('@/services/cat/permission-service', () => ({ + // function (not arrow): vitest constructs mock implementations with `new`. + CatPermissionService: vi.fn().mockImplementation(function () { + return { + checkPermission: vi.fn().mockResolvedValue({ allowed: true, requiresConfirmation: false }), + checkSpendCaps: vi.fn().mockResolvedValue({ allowed: true }), + }; + }), })); // ── Mock logger (suppress noise) ───────────────────────────────────────────── -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); // ── Supabase mock factory ───────────────────────────────────────────────────── @@ -41,38 +46,38 @@ function buildMockSupabase() { const chain: Record = {}; // Mutation trackers - chain.insert = jest.fn((payload: unknown) => { + chain.insert = vi.fn((payload: unknown) => { if (!insertsByTable[tableName]) insertsByTable[tableName] = []; insertsByTable[tableName].push(payload); return chain; }); - chain.update = jest.fn((payload: unknown) => { + chain.update = vi.fn((payload: unknown) => { if (!updatesByTable[tableName]) updatesByTable[tableName] = []; updatesByTable[tableName].push(payload); return chain; }); // Terminal resolvers — single returns a row, maybeSingle returns null for participant lookup - chain.single = jest + chain.single = vi .fn() .mockResolvedValue({ data: { id: 'mock-id', title: 'mock' }, error: null }); - chain.maybeSingle = jest.fn().mockResolvedValue({ data: null, error: null }); // no shared conv → create new + chain.maybeSingle = vi.fn().mockResolvedValue({ data: null, error: null }); // no shared conv → create new // Chainable filters / modifiers - chain.select = jest.fn().mockReturnThis(); - chain.eq = jest.fn().mockReturnThis(); - chain.neq = jest.fn().mockReturnThis(); - chain.or = jest.fn().mockReturnThis(); - chain.in = jest.fn().mockReturnThis(); - chain.not = jest.fn().mockReturnThis(); - chain.order = jest.fn().mockReturnThis(); - chain.limit = jest.fn().mockReturnThis(); + chain.select = vi.fn().mockReturnThis(); + chain.eq = vi.fn().mockReturnThis(); + chain.neq = vi.fn().mockReturnThis(); + chain.or = vi.fn().mockReturnThis(); + chain.in = vi.fn().mockReturnThis(); + chain.not = vi.fn().mockReturnThis(); + chain.order = vi.fn().mockReturnThis(); + chain.limit = vi.fn().mockReturnThis(); return chain; }; const supabase = { - from: jest.fn((table: string) => makeChain(table)), + from: vi.fn((table: string) => makeChain(table)), _insertsByTable: insertsByTable, _updatesByTable: updatesByTable, }; @@ -1078,28 +1083,28 @@ describe('Cat action-executor — correct DB column names', () => { }; const supabase = { - from: jest.fn((table: string) => { + from: vi.fn((table: string) => { const chain: Record = {}; - chain.insert = jest.fn((payload: unknown) => { + chain.insert = vi.fn((payload: unknown) => { if (!insertsByTable[table]) insertsByTable[table] = []; insertsByTable[table].push(payload); return chain; }); - chain.update = jest.fn().mockReturnThis(); - chain.select = jest.fn().mockReturnThis(); - chain.eq = jest.fn().mockReturnThis(); - chain.in = jest.fn().mockReturnThis(); - chain.order = jest.fn().mockReturnThis(); - chain.limit = jest.fn().mockReturnThis(); + chain.update = vi.fn().mockReturnThis(); + chain.select = vi.fn().mockReturnThis(); + chain.eq = vi.fn().mockReturnThis(); + chain.in = vi.fn().mockReturnThis(); + chain.order = vi.fn().mockReturnThis(); + chain.limit = vi.fn().mockReturnThis(); // Tasks select returns real task data; everything else returns a generic insert success - chain.single = jest + chain.single = vi .fn() .mockResolvedValue( table === DATABASE_TABLES.TASKS ? { data: taskRow, error: null } : { data: { id: 'new-id' }, error: null } ); - chain.maybeSingle = jest.fn().mockResolvedValue({ data: null, error: null }); + chain.maybeSingle = vi.fn().mockResolvedValue({ data: null, error: null }); return chain; }), _insertsByTable: insertsByTable, @@ -1180,27 +1185,27 @@ describe('Cat action-executor — correct DB column names', () => { }; const supabase = { - from: jest.fn((table: string) => { + from: vi.fn((table: string) => { const chain: Record = {}; - chain.insert = jest.fn().mockReturnThis(); - chain.update = jest.fn((payload: unknown) => { + chain.insert = vi.fn().mockReturnThis(); + chain.update = vi.fn((payload: unknown) => { if (!updatesByTable[table]) updatesByTable[table] = []; updatesByTable[table].push(payload); return chain; }); - chain.select = jest.fn().mockReturnThis(); - chain.eq = jest.fn().mockReturnThis(); - chain.order = jest.fn().mockReturnThis(); - chain.limit = jest.fn().mockReturnThis(); + chain.select = vi.fn().mockReturnThis(); + chain.eq = vi.fn().mockReturnThis(); + chain.order = vi.fn().mockReturnThis(); + chain.limit = vi.fn().mockReturnThis(); // Tasks select returns real task data; update single returns updated row - chain.single = jest + chain.single = vi .fn() .mockResolvedValue( table === DATABASE_TABLES.TASKS ? { data: { ...taskRow, due_date: null, priority: 'normal' }, error: null } : { data: { id: 'new-id' }, error: null } ); - chain.maybeSingle = jest.fn().mockResolvedValue({ data: null, error: null }); + chain.maybeSingle = vi.fn().mockResolvedValue({ data: null, error: null }); return chain; }), _updatesByTable: updatesByTable, @@ -1378,7 +1383,7 @@ describe('Cat action-executor — correct DB column names', () => { // eq is called on the chain — USER_ID should be used (not ACTOR_ID) // We verify via the mock's .eq call — the chain for profiles must be called // with eq('id', USER_ID). Since eq returns this, we verify via call order. - const profileCalls = (supabase.from as jest.Mock).mock.calls.filter( + const profileCalls = (supabase.from as Mock).mock.calls.filter( ([t]: [string]) => t === DATABASE_TABLES.PROFILES ); expect(profileCalls.length).toBeGreaterThan(0); @@ -1444,32 +1449,32 @@ describe('Cat action-executor — correct DB column names', () => { const chain: Record = {}; - chain.select = jest.fn(() => { + chain.select = vi.fn(() => { _operation = 'select'; return chain; }); - chain.insert = jest.fn((payload: unknown) => { + chain.insert = vi.fn((payload: unknown) => { _operation = 'insert'; if (!insertsByTable[tableName]) insertsByTable[tableName] = []; insertsByTable[tableName].push(payload); return chain; }); - chain.update = jest.fn(() => { + chain.update = vi.fn(() => { _operation = 'update'; return chain; }); - chain.eq = jest.fn().mockReturnThis(); - chain.not = jest.fn().mockReturnThis(); - chain.order = jest.fn().mockReturnThis(); - chain.limit = jest.fn().mockReturnThis(); - chain.neq = jest.fn().mockReturnThis(); - chain.or = jest.fn().mockReturnThis(); - chain.in = jest.fn().mockReturnThis(); - chain.maybeSingle = jest.fn().mockResolvedValue({ data: null, error: null }); + chain.eq = vi.fn().mockReturnThis(); + chain.not = vi.fn().mockReturnThis(); + chain.order = vi.fn().mockReturnThis(); + chain.limit = vi.fn().mockReturnThis(); + chain.neq = vi.fn().mockReturnThis(); + chain.or = vi.fn().mockReturnThis(); + chain.in = vi.fn().mockReturnThis(); + chain.maybeSingle = vi.fn().mockResolvedValue({ data: null, error: null }); // Make chain thenable so `await chain` (for list queries like .limit(1)) resolves correctly. // The wallets SELECT returns a list with the lightning address; inserts return the new row. - chain.then = jest.fn().mockImplementation((resolve: (v: unknown) => void) => { + chain.then = vi.fn().mockImplementation((resolve: (v: unknown) => void) => { if (tableName === DATABASE_TABLES.WALLETS && _operation === 'select') { resolve({ data: existingLightningAddress ? [{ lightning_address: existingLightningAddress }] : [], @@ -1481,7 +1486,7 @@ describe('Cat action-executor — correct DB column names', () => { }); // single() — used by INSERT .select().single() and by action log - chain.single = jest.fn().mockImplementation(() => { + chain.single = vi.fn().mockImplementation(() => { if (tableName === DATABASE_TABLES.WALLETS && _operation === 'insert') { return Promise.resolve({ data: { @@ -1504,7 +1509,7 @@ describe('Cat action-executor — correct DB column names', () => { }; const supabase = { - from: jest.fn((table: string) => makeChain(table)), + from: vi.fn((table: string) => makeChain(table)), _insertsByTable: insertsByTable, }; diff --git a/__tests__/unit/cat/connectWalletHandler.test.ts b/__tests__/unit/cat/connectWalletHandler.test.ts index f0f82d505..41784751d 100644 --- a/__tests__/unit/cat/connectWalletHandler.test.ts +++ b/__tests__/unit/cat/connectWalletHandler.test.ts @@ -21,24 +21,26 @@ import { paymentHandlers } from '@/services/cat/handlers/payments'; import { getOwnerReceiveStatus } from '@/domain/wallets/receiveStatus'; import { encrypt, isEncryptionConfigured } from '@/domain/payments/encryptionService'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/domain/wallets/receiveStatus', () => ({ getOwnerReceiveStatus: jest.fn() })); -jest.mock('@/domain/payments/encryptionService', () => ({ +vi.mock('@/domain/wallets/receiveStatus', () => ({ getOwnerReceiveStatus: vi.fn() })); +vi.mock('@/domain/payments/encryptionService', () => ({ // Opaque on purpose: an `enc:${plaintext}` stub would contain the secret and // make the "never stored in the clear" assertion below vacuous. - encrypt: jest.fn(() => 'ciphertext-blob'), - isEncryptionConfigured: jest.fn(() => true), + encrypt: vi.fn(() => 'ciphertext-blob'), + isEncryptionConfigured: vi.fn(() => true), })); -jest.mock('@/domain/payments/sendPaymentService', () => ({ - sendToRecipient: jest.fn(), - resolveSenderNwcUri: jest.fn(), +vi.mock('@/domain/payments/sendPaymentService', () => ({ + sendToRecipient: vi.fn(), + resolveSenderNwcUri: vi.fn(), })); -const receiveStatusMock = getOwnerReceiveStatus as jest.Mock; -const encryptMock = encrypt as jest.Mock; -const encryptionConfiguredMock = isEncryptionConfigured as jest.Mock; +const receiveStatusMock = getOwnerReceiveStatus as Mock; +const encryptMock = encrypt as Mock; +const encryptionConfiguredMock = isEncryptionConfigured as Mock; /** Captures what the handler tried to write, without a real Supabase. */ function makeSupabase(existingWallet: { id: string; label: string } | null) { @@ -81,7 +83,7 @@ const connect = ( }; beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); encryptionConfiguredMock.mockReturnValue(true); encryptMock.mockReturnValue('ciphertext-blob'); receiveStatusMock.mockResolvedValue({ diff --git a/__tests__/unit/cat/context-string-builder.snapshot.test.ts b/__tests__/unit/cat/context-string-builder.snapshot.test.ts index 9239b92b3..10e9100bb 100644 --- a/__tests__/unit/cat/context-string-builder.snapshot.test.ts +++ b/__tests__/unit/cat/context-string-builder.snapshot.test.ts @@ -166,10 +166,10 @@ const FULL_CTX = { describe('buildFullContextString — full-output snapshot', () => { beforeAll(() => { - jest.useFakeTimers({ now: new Date('2026-06-29T12:00:00Z'), doNotFake: ['nextTick'] }); + vi.useFakeTimers({ now: new Date('2026-06-29T12:00:00Z'), doNotFake: ['nextTick'] }); }); afterAll(() => { - jest.useRealTimers(); + vi.useRealTimers(); }); it('renders every section identically (byte-for-byte)', () => { diff --git a/__tests__/unit/cat/credit-metering.test.ts b/__tests__/unit/cat/credit-metering.test.ts index 94788a488..7ae30a3ce 100644 --- a/__tests__/unit/cat/credit-metering.test.ts +++ b/__tests__/unit/cat/credit-metering.test.ts @@ -18,20 +18,20 @@ import { } from '@/services/cat/credit-metering'; import { calculateCostBtc, getFreeModels, getAvailableModels } from '@/config/ai-models'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); // Registry estimates are priced in USD, so they need a BTC/USD rate. Pin it for // determinism — and let a test return null to prove we bill nothing without one. -const convertBtcToOrNull = jest.fn().mockResolvedValue(100000); // 1 BTC = 100k USD -jest.mock('@/services/currency/rates.server', () => ({ +const convertBtcToOrNull = vi.fn().mockResolvedValue(100000); // 1 BTC = 100k USD +vi.mock('@/services/currency/rates.server', () => ({ convertBtcToOrNull: (...a: unknown[]) => convertBtcToOrNull(...a), })); -const appendCreditEntry = jest.fn(); -const getCreditBalance = jest.fn(); -jest.mock('@/services/cat/credits', () => ({ +const appendCreditEntry = vi.fn(); +const getCreditBalance = vi.fn(); +vi.mock('@/services/cat/credits', () => ({ appendCreditEntry: (...a: unknown[]) => appendCreditEntry(...a), getCreditBalance: (...a: unknown[]) => getCreditBalance(...a), })); @@ -41,7 +41,7 @@ const PAID_MODEL = getAvailableModels().find(m => m.tier !== 'free')?.id as stri const FREE_MODEL = getFreeModels()[0]?.id as string; beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe('calculateCostBtc returns BTC, not satoshis', () => { diff --git a/__tests__/unit/cat/discovery.test.ts b/__tests__/unit/cat/discovery.test.ts index 5e4042e0b..469b9c6cd 100644 --- a/__tests__/unit/cat/discovery.test.ts +++ b/__tests__/unit/cat/discovery.test.ts @@ -12,13 +12,13 @@ import type { AnySupabaseClient } from '@/lib/supabase/types'; * what these tests pin. */ -jest.mock('@/services/ai/embeddings', () => ({ +vi.mock('@/services/ai/embeddings', () => ({ embeddingsEnabled: () => true, embedText: async () => new Array(1536).fill(0.01), embedTexts: async (xs: string[]) => xs.map(() => new Array(1536).fill(0.01)), })); -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); interface Row { diff --git a/__tests__/unit/cat/failure-alert.test.ts b/__tests__/unit/cat/failure-alert.test.ts index 5bdf5f243..5cedcc5eb 100644 --- a/__tests__/unit/cat/failure-alert.test.ts +++ b/__tests__/unit/cat/failure-alert.test.ts @@ -4,7 +4,9 @@ import { join } from 'path'; import { alertCatChatFailure } from '@/services/cat/failure-alert'; import { getAdminClient } from '@/lib/supabase/admin'; -jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); +import type { Mock } from 'vitest'; + +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: vi.fn() })); /** * Alerting a Cat chat failure must never make the failure worse. @@ -14,10 +16,10 @@ jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); * so "cannot write the alert" has to degrade to silence plus a log line. */ describe('Cat failure alerting', () => { - beforeEach(() => jest.clearAllMocks()); + beforeEach(() => vi.clearAllMocks()); it('never throws when the alert cannot be written', async () => { - (getAdminClient as jest.Mock).mockImplementation(() => { + (getAdminClient as Mock).mockImplementation(() => { throw new Error('no service key in this environment'); }); await expect( @@ -39,28 +41,28 @@ describe('Cat failure alerting', () => { maybeSingle: () => Promise.resolve({ data: null }), insert: () => Promise.reject(new Error('RLS denied')), }; - (getAdminClient as jest.Mock).mockReturnValue({ from: () => rejecting }); + (getAdminClient as Mock).mockReturnValue({ from: () => rejecting }); await expect( alertCatChatFailure({ userId: 'u1', code: 'STREAM_ERROR' }) ).resolves.toBeUndefined(); }); it('coalesces onto an existing unread alert for the same code instead of stacking rows', async () => { - const update = jest.fn().mockReturnValue({ eq: jest.fn().mockResolvedValue({}) }); - const insert = jest.fn().mockResolvedValue({}); + const update = vi.fn().mockReturnValue({ eq: vi.fn().mockResolvedValue({}) }); + const insert = vi.fn().mockResolvedValue({}); const chain = { select: () => chain, eq: () => chain, order: () => chain, limit: () => chain, - maybeSingle: jest + maybeSingle: vi .fn() .mockResolvedValueOnce({ data: { username: 'mao' } }) .mockResolvedValue({ data: { id: 'n1', metadata: { occurrences: 3 } } }), update, insert, }; - (getAdminClient as jest.Mock).mockReturnValue({ from: () => chain }); + (getAdminClient as Mock).mockReturnValue({ from: () => chain }); await alertCatChatFailure({ userId: 'u1', code: 'AI_RATE_LIMITED', provider: 'openrouter' }); @@ -72,20 +74,20 @@ describe('Cat failure alerting', () => { }); it('inserts a first alert when none is open', async () => { - const insert = jest.fn().mockResolvedValue({}); + const insert = vi.fn().mockResolvedValue({}); const chain = { select: () => chain, eq: () => chain, order: () => chain, limit: () => chain, - maybeSingle: jest + maybeSingle: vi .fn() .mockResolvedValueOnce({ data: { username: 'user_2dd6f19e' } }) .mockResolvedValue({ data: null }), - update: jest.fn(), + update: vi.fn(), insert, }; - (getAdminClient as jest.Mock).mockReturnValue({ from: () => chain }); + (getAdminClient as Mock).mockReturnValue({ from: () => chain }); await alertCatChatFailure({ userId: 'u1', @@ -108,17 +110,17 @@ describe('Cat failure alerting', () => { }); it('still alerts when the account cannot be named', async () => { - const insert = jest.fn().mockResolvedValue({}); + const insert = vi.fn().mockResolvedValue({}); const chain = { select: () => chain, eq: () => chain, order: () => chain, limit: () => chain, - maybeSingle: jest.fn().mockResolvedValue({ data: null }), - update: jest.fn(), + maybeSingle: vi.fn().mockResolvedValue({ data: null }), + update: vi.fn(), insert, }; - (getAdminClient as jest.Mock).mockReturnValue({ from: () => chain }); + (getAdminClient as Mock).mockReturnValue({ from: () => chain }); await alertCatChatFailure({ userId: 'u9', code: 'STREAM_ERROR' }); diff --git a/__tests__/unit/cat/forget-failure-is-not-no-match.test.ts b/__tests__/unit/cat/forget-failure-is-not-no-match.test.ts index ceac62a5a..36eb34ba2 100644 --- a/__tests__/unit/cat/forget-failure-is-not-no-match.test.ts +++ b/__tests__/unit/cat/forget-failure-is-not-no-match.test.ts @@ -16,14 +16,14 @@ import { forgetMemoriesMatching } from '@/services/cat/memory'; -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/services/ai/embeddings', () => ({ +vi.mock('@/services/ai/embeddings', () => ({ embeddingsEnabled: () => false, - embedText: jest.fn(), - embedTexts: jest.fn(), + embedText: vi.fn(), + embedTexts: vi.fn(), })); const FACTS = ['photography skills']; @@ -39,9 +39,7 @@ function makeClient(opts: { loadError?: unknown; deleteError?: unknown } = {}) { select: () => ({ eq: () => Promise.resolve( - opts.loadError - ? { data: null, error: opts.loadError } - : { data: [STORED], error: null } + opts.loadError ? { data: null, error: opts.loadError } : { data: [STORED], error: null } ), }), delete: () => ({ @@ -57,7 +55,7 @@ function makeClient(opts: { loadError?: unknown; deleteError?: unknown } = {}) { } describe('forgetMemoriesMatching — failure is its own channel', () => { - beforeEach(() => jest.clearAllMocks()); + beforeEach(() => vi.clearAllMocks()); it('deletes and reports it, when the store works', async () => { const result = await forgetMemoriesMatching(makeClient(), 'u1', FACTS); diff --git a/__tests__/unit/cat/forget-generic-stem-innocents.test.ts b/__tests__/unit/cat/forget-generic-stem-innocents.test.ts index e861eae0b..6f0ba105a 100644 --- a/__tests__/unit/cat/forget-generic-stem-innocents.test.ts +++ b/__tests__/unit/cat/forget-generic-stem-innocents.test.ts @@ -14,14 +14,14 @@ import { forgetMemoriesMatching } from '@/services/cat/memory'; import type { AnySupabaseClient } from '@/lib/supabase/types'; -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/services/ai/embeddings', () => ({ +vi.mock('@/services/ai/embeddings', () => ({ embeddingsEnabled: () => false, - embedText: jest.fn(), - embedTexts: jest.fn(), + embedText: vi.fn(), + embedTexts: vi.fn(), })); interface Row { diff --git a/__tests__/unit/cat/forget-reports-dropped-facts.test.ts b/__tests__/unit/cat/forget-reports-dropped-facts.test.ts index 4cfc13baa..ea67be706 100644 --- a/__tests__/unit/cat/forget-reports-dropped-facts.test.ts +++ b/__tests__/unit/cat/forget-reports-dropped-facts.test.ts @@ -23,14 +23,14 @@ import { selectForgetFacts } from '@/services/cat/memory'; import { contextHandlers } from '@/services/cat/handlers/context'; -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/services/ai/embeddings', () => ({ +vi.mock('@/services/ai/embeddings', () => ({ embeddingsEnabled: () => false, - embedText: jest.fn(), - embedTexts: jest.fn(), + embedText: vi.fn(), + embedTexts: vi.fn(), })); const MAX_FORGET_FACTS = 10; diff --git a/__tests__/unit/cat/forget-semantic-floor.test.ts b/__tests__/unit/cat/forget-semantic-floor.test.ts index f47d46a06..732c3b1dc 100644 --- a/__tests__/unit/cat/forget-semantic-floor.test.ts +++ b/__tests__/unit/cat/forget-semantic-floor.test.ts @@ -14,21 +14,23 @@ import { forgetMemoriesMatching } from '@/services/cat/memory'; import type { AnySupabaseClient } from '@/lib/supabase/types'; -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -const mockEmbedText = jest.fn(); -jest.mock('@/services/ai/embeddings', () => ({ +const mockEmbedText = vi.fn(); +vi.mock('@/services/ai/embeddings', () => ({ embeddingsEnabled: () => true, embedText: (...args: unknown[]) => mockEmbedText(...args), - embedTexts: jest.fn().mockResolvedValue([]), + embedTexts: vi.fn().mockResolvedValue([]), })); /** Corpus deliberately shares NO word with the phrase, forcing the RPC path. */ const STORED = { id: 's1', content: 'Knows French' }; -function makeClient(rpc: jest.Mock) { +function makeClient(rpc: Mock) { return { from: () => ({ select: () => ({ eq: async () => ({ data: [STORED], error: null }) }), @@ -42,12 +44,12 @@ function makeClient(rpc: jest.Mock) { describe('forget semantic fallback', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); mockEmbedText.mockResolvedValue([0.1, 0.2, 0.3]); }); it('passes the measured 0.45 floor to match_cat_memories', async () => { - const rpc = jest.fn().mockResolvedValue({ data: [], error: null }); + const rpc = vi.fn().mockResolvedValue({ data: [], error: null }); await forgetMemoriesMatching(makeClient(rpc), 'u1', ['speaking a second language']); expect(rpc).toHaveBeenCalledWith( @@ -57,7 +59,7 @@ describe('forget semantic fallback', () => { }); it('deletes what the semantic match returns when no word matched', async () => { - const rpc = jest.fn().mockResolvedValue({ data: [STORED], error: null }); + const rpc = vi.fn().mockResolvedValue({ data: [STORED], error: null }); const result = await forgetMemoriesMatching(makeClient(rpc), 'u1', [ 'speaking a second language', ]); @@ -67,7 +69,7 @@ describe('forget semantic fallback', () => { }); it('is a FALLBACK — a word match never reaches the RPC', async () => { - const rpc = jest.fn().mockResolvedValue({ data: [], error: null }); + const rpc = vi.fn().mockResolvedValue({ data: [], error: null }); await forgetMemoriesMatching(makeClient(rpc), 'u1', ['French']); expect(rpc).not.toHaveBeenCalled(); @@ -76,7 +78,7 @@ describe('forget semantic fallback', () => { it('reports no-match rather than failing when the RPC errors', async () => { // A dead embedding path must degrade to "nothing matched", never to a // half-truth about what was removed. - const rpc = jest.fn().mockRejectedValue(new Error('vector index offline')); + const rpc = vi.fn().mockRejectedValue(new Error('vector index offline')); const result = await forgetMemoriesMatching(makeClient(rpc), 'u1', [ 'speaking a second language', ]); diff --git a/__tests__/unit/cat/health-report-honesty.test.ts b/__tests__/unit/cat/health-report-honesty.test.ts index e2c680f78..69253f967 100644 --- a/__tests__/unit/cat/health-report-honesty.test.ts +++ b/__tests__/unit/cat/health-report-honesty.test.ts @@ -25,7 +25,7 @@ const RATE_LIMITED = { /** Groq up, OpenRouter out of daily quota — the exact production state. */ function mockFetch() { - return jest.fn(async (url: unknown) => { + return vi.fn(async (url: unknown) => { const u = String(url); if (u.includes('/models')) { return { ok: true, status: 200, json: async () => ({ data: [] }) }; diff --git a/__tests__/unit/cat/interests.test.ts b/__tests__/unit/cat/interests.test.ts index e09d7bb6b..70ff97bee 100644 --- a/__tests__/unit/cat/interests.test.ts +++ b/__tests__/unit/cat/interests.test.ts @@ -17,12 +17,12 @@ import type { AnySupabaseClient } from '@/lib/supabase/types'; * publishing can never happen without an explicit confirmation. */ -jest.mock('@/services/ai/embeddings', () => ({ +vi.mock('@/services/ai/embeddings', () => ({ embeddingsEnabled: () => true, embedText: async () => new Array(1536).fill(0.01), })); -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); interface Row { diff --git a/__tests__/unit/cat/openai-compat.test.ts b/__tests__/unit/cat/openai-compat.test.ts index 28f6bc086..384859381 100644 --- a/__tests__/unit/cat/openai-compat.test.ts +++ b/__tests__/unit/cat/openai-compat.test.ts @@ -63,7 +63,7 @@ describe('OpenAICompatibleService', () => { status: 200, json: async () => ({ choices: [], usage: {} }), } as unknown as Response; - const fetchSpy = jest.spyOn(global, 'fetch').mockResolvedValue(fakeResponse); + const fetchSpy = vi.spyOn(global, 'fetch').mockResolvedValue(fakeResponse); const svc = createOpenAICompatibleServiceWithByok({ apiKey: 'sk-test-1234567890abcdef\n', diff --git a/__tests__/unit/cat/platform-ceiling.test.ts b/__tests__/unit/cat/platform-ceiling.test.ts index 104d5ad9b..abba6e2a5 100644 --- a/__tests__/unit/cat/platform-ceiling.test.ts +++ b/__tests__/unit/cat/platform-ceiling.test.ts @@ -11,13 +11,13 @@ import type { CatPermissionService } from '@/services/cat/permission-service'; import { DATABASE_TABLES } from '@/config/database-tables'; -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -const { CatPermissionService: RealPermissionService } = jest.requireActual( +const { CatPermissionService: RealPermissionService } = (await vi.importActual( '@/services/cat/permission-service' -) as { CatPermissionService: typeof CatPermissionService }; +)) as { CatPermissionService: typeof CatPermissionService }; const USER_ID = 'user-1'; @@ -36,15 +36,13 @@ function buildSupabase(config: { const eqFilters: Record = {}; const chain: Record = {}; for (const method of ['select', 'in', 'gte', 'neq', 'order', 'limit']) { - chain[method] = jest.fn().mockReturnValue(chain); + chain[method] = vi.fn().mockReturnValue(chain); } - chain.eq = jest.fn((column: string, value: unknown) => { + chain.eq = vi.fn((column: string, value: unknown) => { eqFilters[column] = value; return chain; }); - chain.maybeSingle = jest - .fn() - .mockResolvedValue({ data: config.policyRow ?? null, error: null }); + chain.maybeSingle = vi.fn().mockResolvedValue({ data: config.policyRow ?? null, error: null }); chain.then = (resolve: (value: { data: unknown }) => unknown) => { let rows: unknown; if (table === DATABASE_TABLES.CAT_PERMISSIONS) { @@ -57,7 +55,7 @@ function buildSupabase(config: { }; return chain; }; - return { from: jest.fn((table: string) => makeChain(table)) }; + return { from: vi.fn((table: string) => makeChain(table)) }; } const POLICY = { diff --git a/__tests__/unit/cat/proactive.test.ts b/__tests__/unit/cat/proactive.test.ts index 64e093242..a2abdf6c1 100644 --- a/__tests__/unit/cat/proactive.test.ts +++ b/__tests__/unit/cat/proactive.test.ts @@ -7,14 +7,17 @@ import type { SupabaseClient } from '@supabase/supabase-js'; * per day, and a watch fires exactly once (marked fired BEFORE notifying). */ -const createNotificationMock = jest.fn().mockResolvedValue({ success: true, notificationId: 'n1' }); -jest.mock('@/lib/services/notifications', () => ({ - NotificationService: jest.fn().mockImplementation(() => ({ - createNotification: (...args: unknown[]) => createNotificationMock(...args), - })), +const createNotificationMock = vi.fn().mockResolvedValue({ success: true, notificationId: 'n1' }); +vi.mock('@/lib/services/notifications', () => ({ + // function (not arrow): vitest constructs mock implementations with `new`. + NotificationService: vi.fn().mockImplementation(function () { + return { + createNotification: (...args: unknown[]) => createNotificationMock(...args), + }; + }), })); -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); type QueryResponse = { data?: unknown; error?: unknown; count?: number | null }; diff --git a/__tests__/unit/cat/rename-handle.test.ts b/__tests__/unit/cat/rename-handle.test.ts index 8fb074537..e2660dc67 100644 --- a/__tests__/unit/cat/rename-handle.test.ts +++ b/__tests__/unit/cat/rename-handle.test.ts @@ -22,14 +22,16 @@ import { contextHandlers } from '@/services/cat/handlers/context'; import { ProfileServerService } from '@/services/profile/server'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/services/profile/server', () => ({ - ProfileServerService: { checkUsernameAvailability: jest.fn() }, +vi.mock('@/services/profile/server', () => ({ + ProfileServerService: { checkUsernameAvailability: vi.fn() }, })); -const availabilityMock = ProfileServerService.checkUsernameAvailability as jest.Mock; +const availabilityMock = ProfileServerService.checkUsernameAvailability as Mock; const USER = 'cec88bc9-0000-0000-0000-000000000001'; @@ -66,7 +68,7 @@ const run = (supabase: never, params: Record) => describe('update_profile — changing the @handle', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); availabilityMock.mockResolvedValue(true); }); diff --git a/__tests__/unit/cat/response-parser.test.ts b/__tests__/unit/cat/response-parser.test.ts index df61eb887..4802e234e 100644 --- a/__tests__/unit/cat/response-parser.test.ts +++ b/__tests__/unit/cat/response-parser.test.ts @@ -86,8 +86,8 @@ describe('parseActionsFromResponse — create_entity', () => { expect(actions).toHaveLength(0); }); - it('accepts all CAT_CREATABLE_ENTITY_TYPES including group', () => { - const { CAT_CREATABLE_ENTITY_TYPES } = require('@/types/cat'); + it('accepts all CAT_CREATABLE_ENTITY_TYPES including group', async () => { + const { CAT_CREATABLE_ENTITY_TYPES } = await import('@/types/cat'); expect(CAT_CREATABLE_ENTITY_TYPES).toContain('group'); expect(CAT_CREATABLE_ENTITY_TYPES).toContain('product'); expect(CAT_CREATABLE_ENTITY_TYPES).toContain('service'); diff --git a/__tests__/unit/cat/sendPaymentHandler.test.ts b/__tests__/unit/cat/sendPaymentHandler.test.ts index 0f801756c..8b9568df8 100644 --- a/__tests__/unit/cat/sendPaymentHandler.test.ts +++ b/__tests__/unit/cat/sendPaymentHandler.test.ts @@ -14,21 +14,23 @@ import { paymentHandlers } from '@/services/cat/handlers/payments'; import { sendToRecipient } from '@/domain/payments/sendPaymentService'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/domain/payments/sendPaymentService', () => ({ - sendToRecipient: jest.fn(), - resolveSenderNwcUri: jest.fn(), +vi.mock('@/domain/payments/sendPaymentService', () => ({ + sendToRecipient: vi.fn(), + resolveSenderNwcUri: vi.fn(), })); -const sendToRecipientMock = sendToRecipient as jest.Mock; +const sendToRecipientMock = sendToRecipient as Mock; const supabase = {} as never; const send = (params: Record) => paymentHandlers.send_payment(supabase, 'user-1', 'actor-1', params); beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe('cat send_payment', () => { diff --git a/__tests__/unit/cat/social-handlers.test.ts b/__tests__/unit/cat/social-handlers.test.ts index a9803526d..77e4a5280 100644 --- a/__tests__/unit/cat/social-handlers.test.ts +++ b/__tests__/unit/cat/social-handlers.test.ts @@ -7,19 +7,22 @@ import type { AnySupabaseClient } from '@/lib/supabase/types'; * verbs delegate to the booking service (integration-tested there). */ -const getUnreadCountMock = jest.fn(); -const markAllAsReadMock = jest.fn(); -jest.mock('@/lib/services/notifications', () => ({ - NotificationService: jest.fn().mockImplementation(() => ({ - getUnreadCount: (...args: unknown[]) => getUnreadCountMock(...args), - markAllAsRead: (...args: unknown[]) => markAllAsReadMock(...args), - })), +const getUnreadCountMock = vi.fn(); +const markAllAsReadMock = vi.fn(); +vi.mock('@/lib/services/notifications', () => ({ + // function (not arrow): vitest constructs mock implementations with `new`. + NotificationService: vi.fn().mockImplementation(function () { + return { + getUnreadCount: (...args: unknown[]) => getUnreadCountMock(...args), + markAllAsRead: (...args: unknown[]) => markAllAsReadMock(...args), + }; + }), })); -jest.mock('@/services/notifications/dispatcher', () => ({ - NotificationDispatcher: { dispatch: jest.fn().mockResolvedValue(undefined) }, +vi.mock('@/services/notifications/dispatcher', () => ({ + NotificationDispatcher: { dispatch: vi.fn().mockResolvedValue(undefined) }, })); -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); type QueryResponse = { data?: unknown; error?: unknown }; diff --git a/__tests__/unit/cat/spend-caps.test.ts b/__tests__/unit/cat/spend-caps.test.ts index 494d63fd4..7f394dbf3 100644 --- a/__tests__/unit/cat/spend-caps.test.ts +++ b/__tests__/unit/cat/spend-caps.test.ts @@ -12,26 +12,29 @@ import { CatPermissionService, effectiveSpendCaps } from '@/services/cat/permiss import { CatActionExecutor } from '@/services/cat/action-executor'; import { DATABASE_TABLES } from '@/config/database-tables'; -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); // Executor tests control permission behavior per-test via this mock instance. const mockPermissionService = { - checkPermission: jest.fn(), - checkSpendCaps: jest.fn(), + checkPermission: vi.fn(), + checkSpendCaps: vi.fn(), }; -jest.mock('@/services/cat/permission-service', () => { - const actual = jest.requireActual('@/services/cat/permission-service'); +vi.mock('@/services/cat/permission-service', async () => { + const actual = await vi.importActual('@/services/cat/permission-service'); return { ...actual, - CatPermissionService: jest.fn().mockImplementation(() => mockPermissionService), + // function (not arrow): vitest constructs mock implementations with `new`. + CatPermissionService: vi.fn().mockImplementation(function () { + return mockPermissionService; + }), }; }); // Keep the executor tests light — no real handlers (they import wallet/NWC code). -const mockSendPaymentHandler = jest.fn(); -jest.mock('@/services/cat/handlers', () => ({ +const mockSendPaymentHandler = vi.fn(); +vi.mock('@/services/cat/handlers', () => ({ ACTION_HANDLERS: { get send_payment() { return mockSendPaymentHandler; @@ -88,29 +91,27 @@ function buildCapsSupabase(config: { table === DATABASE_TABLES.CAT_PERMISSIONS ? config.permissionRows : (config.logRows ?? []); const chain: Record = {}; for (const method of ['select', 'eq', 'in', 'gte', 'order', 'limit']) { - chain[method] = jest.fn().mockReturnValue(chain); + chain[method] = vi.fn().mockReturnValue(chain); } - chain.neq = jest.fn((...args: unknown[]) => { + chain.neq = vi.fn((...args: unknown[]) => { neqCalls.push(args); return chain; }); - chain.maybeSingle = jest - .fn() - .mockResolvedValue({ data: config.policyRow ?? null, error: null }); + chain.maybeSingle = vi.fn().mockResolvedValue({ data: config.policyRow ?? null, error: null }); chain.then = (resolve: (value: { data: unknown }) => unknown) => Promise.resolve(resolve({ data: rows })); return chain; }; return { - from: jest.fn((table: string) => makeChain(table)), + from: vi.fn((table: string) => makeChain(table)), _neqCalls: neqCalls, }; } // checkSpendCaps tests need the REAL service class, not the module mock above. -const { CatPermissionService: RealPermissionService } = jest.requireActual( +const { CatPermissionService: RealPermissionService } = (await vi.importActual( '@/services/cat/permission-service' -) as { CatPermissionService: typeof CatPermissionService }; +)) as { CatPermissionService: typeof CatPermissionService }; describe('CatPermissionService.checkSpendCaps', () => { it('allows non-payment actions without querying permissions', async () => { @@ -193,25 +194,25 @@ function buildExecutorSupabase() { const updatesByTable: Record = {}; const makeChain = (table: string) => { const chain: Record = {}; - chain.insert = jest.fn((payload: unknown) => { + chain.insert = vi.fn((payload: unknown) => { (insertsByTable[table] ??= []).push(payload); return chain; }); - chain.update = jest.fn((payload: unknown) => { + chain.update = vi.fn((payload: unknown) => { (updatesByTable[table] ??= []).push(payload); return chain; }); for (const method of ['select', 'eq', 'in', 'gte', 'neq', 'order', 'limit']) { - chain[method] = jest.fn().mockReturnValue(chain); + chain[method] = vi.fn().mockReturnValue(chain); } - chain.single = jest.fn().mockResolvedValue({ data: { id: 'log-1' }, error: null }); - chain.maybeSingle = jest.fn().mockResolvedValue({ data: null, error: null }); + chain.single = vi.fn().mockResolvedValue({ data: { id: 'log-1' }, error: null }); + chain.maybeSingle = vi.fn().mockResolvedValue({ data: null, error: null }); chain.then = (resolve: (value: { data: unknown }) => unknown) => Promise.resolve(resolve({ data: [] })); return chain; }; return { - from: jest.fn((table: string) => makeChain(table)), + from: vi.fn((table: string) => makeChain(table)), _insertsByTable: insertsByTable, _updatesByTable: updatesByTable, }; @@ -219,7 +220,7 @@ function buildExecutorSupabase() { describe('CatActionExecutor spend-cap enforcement', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); mockPermissionService.checkPermission.mockResolvedValue({ allowed: true, requiresConfirmation: false, diff --git a/__tests__/unit/cat/suggestions.test.ts b/__tests__/unit/cat/suggestions.test.ts index 9906332c0..d56466743 100644 --- a/__tests__/unit/cat/suggestions.test.ts +++ b/__tests__/unit/cat/suggestions.test.ts @@ -16,14 +16,16 @@ import { STARTER_PROMPTS, getStarterPrompts } from '@/config/cat-prompts'; import { getEntitiesByCategory } from '@/config/entity-registry'; import type { FullUserContext } from '@/services/ai/document-context'; -jest.mock('@/services/cat/platform-llm', () => ({ - callPlatformJson: jest.fn(async () => null), - parseJsonLoose: jest.requireActual('@/services/cat/platform-llm').parseJsonLoose, +vi.mock('@/services/cat/platform-llm', async () => ({ + callPlatformJson: vi.fn(async () => null), + parseJsonLoose: ((await vi.importActual('@/services/cat/platform-llm')) as any).parseJsonLoose, })); import { callPlatformJson } from '@/services/cat/platform-llm'; -const mockedCall = callPlatformJson as jest.MockedFunction; +import type { MockedFunction } from 'vitest'; + +const mockedCall = callPlatformJson as MockedFunction; // ─── Helpers ────────────────────────────────────────────────────────────────── @@ -193,7 +195,9 @@ describe('detectGaps', () => { entities: [makeEntity('product', 'Blue Vase', { price_btc: 0 })], }); const gaps = detectGaps(ctx); - expect(gaps.some(g => g.prompt.includes('charge') && g.prompt.includes('Blue Vase'))).toBe(true); + expect(gaps.some(g => g.prompt.includes('charge') && g.prompt.includes('Blue Vase'))).toBe( + true + ); }); it('does not invent a price gap for entities that are not sold at a price', () => { diff --git a/__tests__/unit/cat/tool-executor-forget.test.ts b/__tests__/unit/cat/tool-executor-forget.test.ts index b3cef16ff..576171391 100644 --- a/__tests__/unit/cat/tool-executor-forget.test.ts +++ b/__tests__/unit/cat/tool-executor-forget.test.ts @@ -7,17 +7,17 @@ * pins the both-stores contract on the path that missed it. */ -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -const mockForgetMemories = jest.fn(); -jest.mock('@/services/cat/memory', () => ({ +const mockForgetMemories = vi.fn(); +vi.mock('@/services/cat/memory', () => ({ forgetMemoriesMatching: (...args: unknown[]) => mockForgetMemories(...args), })); -const mockRemoveProfile = jest.fn(); -jest.mock('@/services/cat/economic-profile', () => ({ +const mockRemoveProfile = vi.fn(); +vi.mock('@/services/cat/economic-profile', () => ({ removeFromEconomicProfile: (...args: unknown[]) => mockRemoveProfile(...args), })); diff --git a/__tests__/unit/cat/tool-use-bare-url.test.ts b/__tests__/unit/cat/tool-use-bare-url.test.ts index ef2560f34..ed50d5113 100644 --- a/__tests__/unit/cat/tool-use-bare-url.test.ts +++ b/__tests__/unit/cat/tool-use-bare-url.test.ts @@ -15,11 +15,13 @@ import { executeToolCall } from '@/services/cat/tool-executor'; import type { AnySupabaseClient } from '@/lib/supabase/types'; import type { RawToolCall, ToolAugmentedMessage } from '@/services/cat/tool-use-types'; -jest.mock('@/services/cat/tool-executor', () => ({ - executeToolCall: jest.fn(), +import type { MockedFunction } from 'vitest'; + +vi.mock('@/services/cat/tool-executor', () => ({ + executeToolCall: vi.fn(), })); -const mockExecuteToolCall = executeToolCall as jest.MockedFunction; +const mockExecuteToolCall = executeToolCall as MockedFunction; const supabase = {} as AnySupabaseClient; const USER_ID = 'user-1'; @@ -68,8 +70,8 @@ describe('maybeEnrichWithSearchResults — bare-URL message', () => { const originalFetch = global.fetch; beforeEach(() => { - jest.clearAllMocks(); - global.fetch = jest.fn(async () => stopResponse()) as unknown as typeof fetch; + vi.clearAllMocks(); + global.fetch = vi.fn(async () => stopResponse()) as unknown as typeof fetch; }); afterEach(() => { @@ -153,7 +155,7 @@ describe('maybeEnrichWithSearchResults — bare-URL message', () => { }); it('returns messages unchanged when the routing provider errors on a non-URL message', async () => { - global.fetch = jest.fn(async () => { + global.fetch = vi.fn(async () => { throw new Error('network down'); }) as unknown as typeof fetch; diff --git a/__tests__/unit/cat/tool-use-prefill-dedupe.test.ts b/__tests__/unit/cat/tool-use-prefill-dedupe.test.ts index ca8a18290..479dd64a5 100644 --- a/__tests__/unit/cat/tool-use-prefill-dedupe.test.ts +++ b/__tests__/unit/cat/tool-use-prefill-dedupe.test.ts @@ -12,11 +12,13 @@ import { executeToolCall } from '@/services/cat/tool-executor'; import type { AnySupabaseClient } from '@/lib/supabase/types'; import type { RawToolCall } from '@/services/cat/tool-use-types'; -jest.mock('@/services/cat/tool-executor', () => ({ - executeToolCall: jest.fn(), +import type { MockedFunction } from 'vitest'; + +vi.mock('@/services/cat/tool-executor', () => ({ + executeToolCall: vi.fn(), })); -const mockExecuteToolCall = executeToolCall as jest.MockedFunction; +const mockExecuteToolCall = executeToolCall as MockedFunction; const supabase = {} as AnySupabaseClient; const USER_ID = 'user-1'; @@ -76,7 +78,7 @@ describe('tool loop — cross-step prefill dedupe', () => { const originalFetch = global.fetch; beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); mockExecuteToolCall.mockImplementation(async (_sb, _uid, toolCall) => ({ role: 'tool', tool_call_id: toolCall.id, @@ -89,7 +91,7 @@ describe('tool loop — cross-step prefill dedupe', () => { }); it('drops a later-step prefill for an entity type already drafted', async () => { - global.fetch = jest + global.fetch = vi .fn() .mockResolvedValueOnce(toolCallsResponse([prefillCall('call_1', 'service')])) .mockResolvedValueOnce(toolCallsResponse([prefillCall('call_2', 'service')])) @@ -102,7 +104,7 @@ describe('tool loop — cross-step prefill dedupe', () => { }); it('still allows a DIFFERENT entity type in a later step', async () => { - global.fetch = jest + global.fetch = vi .fn() .mockResolvedValueOnce(toolCallsResponse([prefillCall('call_1', 'service')])) .mockResolvedValueOnce(toolCallsResponse([prefillCall('call_2', 'product')])) @@ -118,7 +120,7 @@ describe('tool loop — cross-step prefill dedupe', () => { }); it('keeps same-step multiples (the website flow chains several in one message)', async () => { - global.fetch = jest + global.fetch = vi .fn() .mockResolvedValueOnce( toolCallsResponse([prefillCall('call_1', 'service'), prefillCall('call_2', 'product')]) diff --git a/__tests__/unit/cat/track-record-setbacks.test.ts b/__tests__/unit/cat/track-record-setbacks.test.ts index 47ba9c5b6..6258a41ba 100644 --- a/__tests__/unit/cat/track-record-setbacks.test.ts +++ b/__tests__/unit/cat/track-record-setbacks.test.ts @@ -13,22 +13,25 @@ import { CatActionExecutor } from '@/services/cat/action-executor'; import { DATABASE_TABLES } from '@/config/database-tables'; import type { AnySupabaseClient } from '@/lib/supabase/types'; -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); const mockPermissionService = { - checkPermission: jest.fn(), - checkSpendCaps: jest.fn(), + checkPermission: vi.fn(), + checkSpendCaps: vi.fn(), }; -jest.mock('@/services/cat/permission-service', () => { - const actual = jest.requireActual('@/services/cat/permission-service'); +vi.mock('@/services/cat/permission-service', async () => { + const actual = await vi.importActual('@/services/cat/permission-service'); return { ...actual, - CatPermissionService: jest.fn().mockImplementation(() => mockPermissionService), + // function (not arrow): vitest constructs mock implementations with `new`. + CatPermissionService: vi.fn().mockImplementation(function () { + return mockPermissionService; + }), }; }); -jest.mock('@/services/cat/handlers', () => ({ ACTION_HANDLERS: {} })); +vi.mock('@/services/cat/handlers', () => ({ ACTION_HANDLERS: {} })); const USER_ID = 'user-1'; diff --git a/__tests__/unit/cat/website-analysis.test.ts b/__tests__/unit/cat/website-analysis.test.ts index c81274853..291c2d064 100644 --- a/__tests__/unit/cat/website-analysis.test.ts +++ b/__tests__/unit/cat/website-analysis.test.ts @@ -216,7 +216,7 @@ describe('validateTargetUrl', () => { describe('fetchWebsiteText SSRF rails', () => { it('rejects hosts that resolve to a private address without fetching', async () => { - const fetchFn = jest.fn(); + const fetchFn = vi.fn(); const result = await fetchWebsiteText('https://internal.example.com', { fetchFn, lookupFn: privateLookup, @@ -226,7 +226,7 @@ describe('fetchWebsiteText SSRF rails', () => { }); it('re-validates redirect hops and blocks a bounce to a private target', async () => { - const fetchFn = jest.fn().mockResolvedValueOnce(redirectResponse('http://127.0.0.1/steal')); + const fetchFn = vi.fn().mockResolvedValueOnce(redirectResponse('http://127.0.0.1/steal')); const result = await fetchWebsiteText('https://example.com', { fetchFn, lookupFn: publicLookup, @@ -236,11 +236,11 @@ describe('fetchWebsiteText SSRF rails', () => { }); it('re-resolves DNS on every redirect hop', async () => { - const lookupFn = jest + const lookupFn = vi .fn() .mockResolvedValueOnce([{ address: '93.184.216.34' }]) // hop 0: public .mockResolvedValueOnce([{ address: '10.0.0.5' }]); // hop 1: private → block - const fetchFn = jest + const fetchFn = vi .fn() .mockResolvedValueOnce(redirectResponse('https://internal.example.com/')); const result = await fetchWebsiteText('https://example.com', { fetchFn, lookupFn }); @@ -250,7 +250,7 @@ describe('fetchWebsiteText SSRF rails', () => { }); it('gives up after 3 redirects', async () => { - const fetchFn = jest.fn().mockResolvedValue(redirectResponse('https://example.com/next')); + const fetchFn = vi.fn().mockResolvedValue(redirectResponse('https://example.com/next')); const result = await fetchWebsiteText('https://example.com', { fetchFn, lookupFn: publicLookup, @@ -422,7 +422,7 @@ describe('analyze_website wiring', () => { describe('fetchWebsiteText with schemeless input', () => { it('normalizes a bare domain to https and fetches it', async () => { - const fetchFn: FetchLike = jest.fn(async () => + const fetchFn: FetchLike = vi.fn(async () => htmlResponse( 'RevampIT

We refurbish computers.

' ) @@ -436,14 +436,14 @@ describe('fetchWebsiteText with schemeless input', () => { }); it('still rejects a schemeless private IP literal', async () => { - const fetchFn = jest.fn(); + const fetchFn = vi.fn(); const result = await fetchWebsiteText('127.0.0.1', { fetchFn, lookupFn: publicLookup }); expect(result.ok).toBe(false); expect(fetchFn).not.toHaveBeenCalled(); }); it('still rejects a schemeless host that resolves to a private address', async () => { - const fetchFn = jest.fn(); + const fetchFn = vi.fn(); const result = await fetchWebsiteText('internal.example.com', { fetchFn, lookupFn: privateLookup, diff --git a/__tests__/unit/components/ai-assistant-free-messages.test.tsx b/__tests__/unit/components/ai-assistant-free-messages.test.tsx index 8e7a88c21..686e01bb3 100644 --- a/__tests__/unit/components/ai-assistant-free-messages.test.tsx +++ b/__tests__/unit/components/ai-assistant-free-messages.test.tsx @@ -17,7 +17,7 @@ import { render, screen } from '@testing-library/react'; -jest.mock('@/hooks/useDisplayCurrency', () => ({ +vi.mock('@/hooks/useDisplayCurrency', () => ({ useDisplayCurrency: () => ({ formatAmountBtc: (n: number) => `${n} BTC`, formatAmount: (n: number) => `${n}`, @@ -35,7 +35,11 @@ const paid = { describe('ai assistant free-message allowance', () => { it('shows the allowance when the assistant actually charges', () => { - render(
{aiAssistantDetailConfig.renderHeaderExtra?.({ ...paid, free_messages_per_day: 5 })}
); + render( +
+ {aiAssistantDetailConfig.renderHeaderExtra?.({ ...paid, free_messages_per_day: 5 })} +
+ ); expect(screen.getByText('First 5 free each day')).toBeInTheDocument(); }); @@ -69,7 +73,11 @@ describe('ai assistant free-message allowance', () => { }); it('hides it when the allowance is zero', () => { - render(
{aiAssistantDetailConfig.renderHeaderExtra?.({ ...paid, free_messages_per_day: 0 })}
); + render( +
+ {aiAssistantDetailConfig.renderHeaderExtra?.({ ...paid, free_messages_per_day: 0 })} +
+ ); expect(screen.queryByText(/free each day/)).not.toBeInTheDocument(); expect(screen.getByText(/0\.00001 BTC/)).toBeInTheDocument(); }); diff --git a/__tests__/unit/components/cat-chat-composer-resize.test.tsx b/__tests__/unit/components/cat-chat-composer-resize.test.tsx index 1fdaa2947..467485c41 100644 --- a/__tests__/unit/components/cat-chat-composer-resize.test.tsx +++ b/__tests__/unit/components/cat-chat-composer-resize.test.tsx @@ -15,7 +15,7 @@ import { render, screen, fireEvent } from '@testing-library/react'; import { ChatInput } from '@/components/ai-chat/ModernChatPanel/components/ChatInput'; -jest.mock('@/components/ui/DictationButton', () => ({ +vi.mock('@/components/ui/DictationButton', () => ({ DictationButton: ({ onTranscript }: { onTranscript: (t: string) => void }) => ( , })); -jest.mock('@/components/receive/SharePayLink', () => ({ +vi.mock('@/components/receive/SharePayLink', () => ({ SharePayLink: ({ username }: { username: string }) =>
share:{username}
, })); -const receiveInfoMock = fetchTipReceiveInfo as jest.Mock; +const receiveInfoMock = fetchTipReceiveInfo as Mock; -beforeEach(() => jest.clearAllMocks()); +beforeEach(() => vi.clearAllMocks()); describe('ProfileSupportSection', () => { it('asks the payment system, not the profile row', async () => { diff --git a/__tests__/unit/components/profile-wallet-section-public.test.tsx b/__tests__/unit/components/profile-wallet-section-public.test.tsx index 9a3765ddc..ea2af2628 100644 --- a/__tests__/unit/components/profile-wallet-section-public.test.tsx +++ b/__tests__/unit/components/profile-wallet-section-public.test.tsx @@ -22,7 +22,7 @@ import { render, screen } from '@testing-library/react'; -jest.mock('@/hooks/useDisplayCurrency', () => ({ +vi.mock('@/hooks/useDisplayCurrency', () => ({ useDisplayCurrency: () => ({ formatAmountBtc: (n: number) => `₿${n}`, formatPrice: (n: number, c: string) => `${c} ${n}`, @@ -30,11 +30,11 @@ jest.mock('@/hooks/useDisplayCurrency', () => ({ }), })); -jest.mock('@/hooks/useCurrencyConversion', () => ({ +vi.mock('@/hooks/useCurrencyConversion', () => ({ useCurrencyConversion: () => ({ convertFromBTC: () => 0, convertToBTC: () => 0 }), })); -jest.mock('qrcode.react', () => ({ QRCodeSVG: () => null })); +vi.mock('qrcode.react', () => ({ QRCodeSVG: () => null })); import ProfileWalletSection from '@/components/profile/ProfileWalletSection'; @@ -54,9 +54,7 @@ const publicWallet = { } as never; function renderSection(wallets: never[]) { - return render( - - ); + return render(); } describe('ProfileWalletSection with a visitor-shaped payload', () => { diff --git a/__tests__/unit/components/project-summary-rail-target-completion.test.tsx b/__tests__/unit/components/project-summary-rail-target-completion.test.tsx index 96359a666..82d501d36 100644 --- a/__tests__/unit/components/project-summary-rail-target-completion.test.tsx +++ b/__tests__/unit/components/project-summary-rail-target-completion.test.tsx @@ -14,14 +14,14 @@ import { render, screen } from '@testing-library/react'; -jest.mock('@/hooks/useDisplayCurrency', () => ({ +vi.mock('@/hooks/useDisplayCurrency', () => ({ useDisplayCurrency: () => ({ formatAmountBtc: (n: number) => `${n} BTC`, formatAmount: (n: number) => `${n}`, }), })); -jest.mock('@/lib/projectGoal', () => ({ +vi.mock('@/lib/projectGoal', () => ({ computeAmountRaised: async (btc: number) => btc, })); diff --git a/__tests__/unit/components/repost-reaches-the-timeline.test.tsx b/__tests__/unit/components/repost-reaches-the-timeline.test.tsx index a0f3cdd34..28be49c72 100644 --- a/__tests__/unit/components/repost-reaches-the-timeline.test.tsx +++ b/__tests__/unit/components/repost-reaches-the-timeline.test.tsx @@ -19,42 +19,40 @@ import { renderHook } from '@testing-library/react'; import { usePostCardActions } from '@/components/timeline/usePostCardActions'; import type { TimelineDisplayEvent } from '@/types/timeline'; -const usePostInteractions = jest.fn(() => ({ +const usePostInteractions = vi.fn(() => ({ isReposting: false, repostModalOpen: false, - handleRepostClick: jest.fn(), - handleRepostClose: jest.fn(), - handleSimpleRepost: jest.fn(), - handleQuoteRepost: jest.fn(), + handleRepostClick: vi.fn(), + handleRepostClose: vi.fn(), + handleSimpleRepost: vi.fn(), + handleQuoteRepost: vi.fn(), })); -jest.mock('@/hooks/usePostInteractions', () => ({ +vi.mock('@/hooks/usePostInteractions', () => ({ usePostInteractions: (args: unknown) => usePostInteractions(args as never), })); -jest.mock('next/navigation', () => ({ useRouter: () => ({ push: jest.fn() }) })); -jest.mock('@/services/timeline', () => ({ timelineService: {} })); +vi.mock('next/navigation', () => ({ useRouter: () => ({ push: vi.fn() }) })); +vi.mock('@/services/timeline', () => ({ timelineService: {} })); const event = { id: 'e1', actor: { id: 'a1' } } as TimelineDisplayEvent; describe('a quote repost reaches the timeline', () => { - beforeEach(() => jest.clearAllMocks()); + beforeEach(() => vi.clearAllMocks()); it('forwards onAddEvent, without which the new post is dropped', () => { - const onAddEvent = jest.fn(); + const onAddEvent = vi.fn(); renderHook(() => usePostCardActions({ event, user: { id: 'a1' } as never, profile: null, - onUpdate: jest.fn(), + onUpdate: vi.fn(), onAddEvent, }) ); - expect(usePostInteractions).toHaveBeenCalledWith( - expect.objectContaining({ onAddEvent }) - ); + expect(usePostInteractions).toHaveBeenCalledWith(expect.objectContaining({ onAddEvent })); }); it('still works for callers that do not want the new post', () => { @@ -63,7 +61,7 @@ describe('a quote repost reaches the timeline', () => { event, user: { id: 'a1' } as never, profile: null, - onUpdate: jest.fn(), + onUpdate: vi.fn(), }) ); diff --git a/__tests__/unit/components/repost-renders-as-a-post.test.tsx b/__tests__/unit/components/repost-renders-as-a-post.test.tsx index c5ff697ae..37e26d890 100644 --- a/__tests__/unit/components/repost-renders-as-a-post.test.tsx +++ b/__tests__/unit/components/repost-renders-as-a-post.test.tsx @@ -26,7 +26,7 @@ import { render, screen } from '@testing-library/react'; import { PostContent } from '@/components/timeline/PostContent'; import type { TimelineDisplayEvent } from '@/types/timeline'; -jest.mock('@/utils/markdown', () => ({ +vi.mock('@/utils/markdown', () => ({ renderMarkdownToReact: (text: string) => text, })); diff --git a/__tests__/unit/components/send/useRecipientCheck.test.tsx b/__tests__/unit/components/send/useRecipientCheck.test.tsx index 97d3e61cd..82f5213fd 100644 --- a/__tests__/unit/components/send/useRecipientCheck.test.tsx +++ b/__tests__/unit/components/send/useRecipientCheck.test.tsx @@ -11,12 +11,14 @@ import { renderHook, waitFor, act } from '@testing-library/react'; import { useRecipientCheck } from '@/components/send/useRecipientCheck'; import { fetchTipReceiveInfo } from '@/services/tips/tip-client'; -jest.mock('@/services/tips/tip-client', () => ({ fetchTipReceiveInfo: jest.fn() })); +import type { Mock } from 'vitest'; -const fetchMock = fetchTipReceiveInfo as jest.Mock; +vi.mock('@/services/tips/tip-client', () => ({ fetchTipReceiveInfo: vi.fn() })); + +const fetchMock = fetchTipReceiveInfo as Mock; beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe('useRecipientCheck', () => { @@ -67,7 +69,7 @@ describe('useRecipientCheck', () => { }); it('does not query on every keystroke', async () => { - jest.useFakeTimers(); + vi.useFakeTimers(); fetchMock.mockResolvedValue({ canReceive: true, recipientName: 'Lena' }); const { rerender } = renderHook(({ value }) => useRecipientCheck(value), { @@ -78,11 +80,11 @@ describe('useRecipientCheck', () => { rerender({ value: 'lena' }); await act(async () => { - jest.runAllTimers(); + vi.runAllTimers(); }); expect(fetchMock).toHaveBeenCalledTimes(1); expect(fetchMock).toHaveBeenCalledWith('lena'); - jest.useRealTimers(); + vi.useRealTimers(); }); }); diff --git a/__tests__/unit/components/sidebar/ContextSwitcher.collapsed.test.tsx b/__tests__/unit/components/sidebar/ContextSwitcher.collapsed.test.tsx index 6ab0735fb..73e4b4661 100644 --- a/__tests__/unit/components/sidebar/ContextSwitcher.collapsed.test.tsx +++ b/__tests__/unit/components/sidebar/ContextSwitcher.collapsed.test.tsx @@ -13,20 +13,20 @@ import '@testing-library/jest-dom'; import { ContextSwitcher } from '@/components/sidebar/ContextSwitcher'; import type { Profile } from '@/types/database'; -jest.mock('next/navigation', () => ({ useRouter: () => ({ push: jest.fn() }) })); -jest.mock('next/image', () => ({ +vi.mock('next/navigation', () => ({ useRouter: () => ({ push: vi.fn() }) })); +vi.mock('next/image', () => ({ __esModule: true, // eslint-disable-next-line @next/next/no-img-element, jsx-a11y/alt-text default: (props: React.ImgHTMLAttributes) => , })); -jest.mock('@/components/nostr/NWCStatusBadge', () => ({ NWCStatusBadge: () => null })); -jest.mock('@/hooks/useNavigationContext', () => ({ +vi.mock('@/components/nostr/NWCStatusBadge', () => ({ NWCStatusBadge: () => null })); +vi.mock('@/hooks/useNavigationContext', () => ({ useNavigationContext: () => ({ context: { type: 'individual' }, userGroups: [], loadingGroups: false, - switchToIndividual: jest.fn(), - switchToGroup: jest.fn(), + switchToIndividual: vi.fn(), + switchToGroup: vi.fn(), isGroupContext: false, }), })); @@ -40,7 +40,7 @@ const profile = { describe('ContextSwitcher — collapsed mode', () => { it('renders the avatar as a button that expands the sidebar', () => { - const onExpand = jest.fn(); + const onExpand = vi.fn(); render(); const avatarButton = screen.getByRole('button', { name: /switch context/i }); diff --git a/__tests__/unit/components/timeline-composer-tools-on-focus.test.tsx b/__tests__/unit/components/timeline-composer-tools-on-focus.test.tsx index 5a5adc975..d97eafa44 100644 --- a/__tests__/unit/components/timeline-composer-tools-on-focus.test.tsx +++ b/__tests__/unit/components/timeline-composer-tools-on-focus.test.tsx @@ -16,7 +16,7 @@ import { render, screen, fireEvent } from '@testing-library/react'; import TimelineComposer from '@/components/timeline/TimelineComposer'; -jest.mock('@/hooks/useAuth', () => ({ +vi.mock('@/hooks/useAuth', () => ({ useAuth: () => ({ user: { id: 'u1', email: 'a@b.c', user_metadata: {} }, profile: { username: 'mao', name: 'Mao', avatar_url: null }, @@ -25,46 +25,46 @@ jest.mock('@/hooks/useAuth', () => ({ const composerState = { content: '', - setContent: jest.fn(), + setContent: vi.fn(), isPosting: false, - handlePost: jest.fn(), + handlePost: vi.fn(), visibility: 'public' as const, - setVisibility: jest.fn(), + setVisibility: vi.fn(), image: null, - setImage: jest.fn(), + setImage: vi.fn(), error: null, postSuccess: false, userProjects: [], selectedProjects: [], - toggleProjectSelection: jest.fn(), + toggleProjectSelection: vi.fn(), }; -jest.mock('@/hooks/usePostComposerNew', () => ({ +vi.mock('@/hooks/usePostComposerNew', () => ({ usePostComposer: () => composerState, })); -jest.mock('@/hooks/useContentEditableEditor', () => ({ +vi.mock('@/hooks/useContentEditableEditor', () => ({ useContentEditableEditor: () => ({ editorRef: { current: null }, - handleInput: jest.fn(), - handlePaste: jest.fn(), - handleKeyDown: jest.fn(), - handleFormat: jest.fn(), + handleInput: vi.fn(), + handlePaste: vi.fn(), + handleKeyDown: vi.fn(), + handleFormat: vi.fn(), }), })); -jest.mock('@/components/mentions/useContentEditableMentions', () => ({ +vi.mock('@/components/mentions/useContentEditableMentions', () => ({ useContentEditableMentions: () => ({ editorProps: {}, menuProps: { suggestions: [] } }), })); -jest.mock('@/components/mentions/MentionSuggestions', () => ({ +vi.mock('@/components/mentions/MentionSuggestions', () => ({ __esModule: true, default: () => null, })); // The AI drafter stands in for "a toolbar button": focusing it must not // unmount the toolbar it lives in. -jest.mock('@/components/timeline/PostAiButton', () => ({ +vi.mock('@/components/timeline/PostAiButton', () => ({ __esModule: true, default: () => ( ), })); -jest.mock('@/components/timeline/ReplyAiButton', () => ({ __esModule: true, default: () => null })); -jest.mock('@/components/timeline/PostAiEditMenu', () => ({ __esModule: true, default: () => null })); +vi.mock('@/components/timeline/ReplyAiButton', () => ({ __esModule: true, default: () => null })); +vi.mock('@/components/timeline/PostAiEditMenu', () => ({ __esModule: true, default: () => null })); const AI_BUTTON = /write with ai/i; diff --git a/__tests__/unit/components/ui/SegmentedControl.test.tsx b/__tests__/unit/components/ui/SegmentedControl.test.tsx index cbe98d175..7ebe0dd2c 100644 --- a/__tests__/unit/components/ui/SegmentedControl.test.tsx +++ b/__tests__/unit/components/ui/SegmentedControl.test.tsx @@ -35,7 +35,12 @@ describe('SegmentedControl', () => { it('renders stateful segments as buttons that report being pressed', () => { render( - {}} /> + {}} + /> ); expect(screen.getByRole('button', { name: 'To a person' })).toHaveAttribute( @@ -49,9 +54,14 @@ describe('SegmentedControl', () => { }); it('reports the value that was chosen', () => { - const onChange = jest.fn(); + const onChange = vi.fn(); render( - + ); fireEvent.click(screen.getByRole('button', { name: 'Paste invoice' })); @@ -60,7 +70,12 @@ describe('SegmentedControl', () => { it('names the group so the choice is not an anonymous row of words', () => { render( - {}} /> + {}} + /> ); expect(screen.getByRole('group', { name: 'Send method' })).toBeInTheDocument(); @@ -68,7 +83,12 @@ describe('SegmentedControl', () => { it('keeps every segment at a thumb-sized touch target', () => { render( - {}} /> + {}} + /> ); for (const button of screen.getAllByRole('button')) { diff --git a/__tests__/unit/create/entityFormSubmitAction.test.ts b/__tests__/unit/create/entityFormSubmitAction.test.ts index 1babe8547..8369fa3bd 100644 --- a/__tests__/unit/create/entityFormSubmitAction.test.ts +++ b/__tests__/unit/create/entityFormSubmitAction.test.ts @@ -11,16 +11,18 @@ import { z } from 'zod'; import { executeEntityFormSubmit } from '@/components/create/EntityForm/hooks/entityFormSubmitAction'; import type { EntityConfig } from '@/components/create/types'; -jest.mock('sonner', () => ({ - toast: { success: jest.fn(), error: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('sonner', () => ({ + toast: { success: vi.fn(), error: vi.fn() }, })); -jest.mock('@/lib/analytics', () => ({ - entityEvents: { created: jest.fn() }, +vi.mock('@/lib/analytics', () => ({ + entityEvents: { created: vi.fn() }, })); -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn() }, })); -jest.mock('@/config/api-routes', () => ({ +vi.mock('@/config/api-routes', () => ({ API_ROUTES: { ENTITY_WALLETS: '/api/entity-wallets' }, })); @@ -51,11 +53,11 @@ function makeParams(overrides: Record = {}) { user: { id: 'user-1' }, onSuccess: undefined as ((data: TestData & { id: string }) => void) | undefined, onError: undefined, - clearDraft: jest.fn(), - setSubmitting: jest.fn(), - setErrors: jest.fn(), - onEntityCreated: jest.fn(), - router: { push: jest.fn() }, + clearDraft: vi.fn(), + setSubmitting: vi.fn(), + setErrors: vi.fn(), + onEntityCreated: vi.fn(), + router: { push: vi.fn() }, existingWalletLinkIdRef: { current: undefined as string | undefined }, wizardMode: undefined, actorId: undefined as string | null | undefined, @@ -64,7 +66,7 @@ function makeParams(overrides: Record = {}) { } function mockFetchOk(data: Record) { - return jest.fn().mockResolvedValue({ + return vi.fn().mockResolvedValue({ ok: true, json: () => Promise.resolve({ success: true, data }), clone() { @@ -75,7 +77,7 @@ function mockFetchOk(data: Record) { describe('executeEntityFormSubmit', () => { afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('create mode POSTs to config.apiEndpoint', async () => { @@ -88,7 +90,7 @@ describe('executeEntityFormSubmit', () => { '/api/causes', expect.objectContaining({ method: 'POST' }) ); - const body = JSON.parse((global.fetch as jest.Mock).mock.calls[0][1].body); + const body = JSON.parse((global.fetch as Mock).mock.calls[0][1].body); expect(body).toEqual({ title: 'My cause' }); expect(params.clearDraft).toHaveBeenCalled(); expect(params.onEntityCreated).toHaveBeenCalledWith({ id: 'new-1', title: 'My cause' }); @@ -100,13 +102,13 @@ describe('executeEntityFormSubmit', () => { await executeEntityFormSubmit(params); - const body = JSON.parse((global.fetch as jest.Mock).mock.calls[0][1].body); + const body = JSON.parse((global.fetch as Mock).mock.calls[0][1].body); expect(body.actor_id).toBe('actor-9'); }); it('edit mode PUTs to `${apiEndpoint}/${entityId}` and never sends actor_id', async () => { global.fetch = mockFetchOk({ id: 'e-42', title: 'My cause' }) as unknown as typeof fetch; - const onSuccess = jest.fn(); + const onSuccess = vi.fn(); const params = makeParams({ mode: 'edit' as const, entityId: 'e-42', @@ -120,7 +122,7 @@ describe('executeEntityFormSubmit', () => { '/api/causes/e-42', expect.objectContaining({ method: 'PUT' }) ); - const body = JSON.parse((global.fetch as jest.Mock).mock.calls[0][1].body); + const body = JSON.parse((global.fetch as Mock).mock.calls[0][1].body); expect(body.actor_id).toBeUndefined(); // Edit must NOT clear the create-draft or fire the created analytics event expect(params.clearDraft).not.toHaveBeenCalled(); @@ -141,7 +143,7 @@ describe('executeEntityFormSubmit', () => { }); it('does not fetch when validation fails; surfaces field errors', async () => { - global.fetch = jest.fn() as unknown as typeof fetch; + global.fetch = vi.fn() as unknown as typeof fetch; const params = makeParams({ formStateData: { title: '' } as TestData }); await executeEntityFormSubmit(params); @@ -153,7 +155,7 @@ describe('executeEntityFormSubmit', () => { }); it('surfaces API errors as a general error without redirecting', async () => { - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ ok: false, json: () => Promise.resolve({ error: 'You can only update your own causes' }), clone() { diff --git a/__tests__/unit/domain/commerce-list-workflows.test.ts b/__tests__/unit/domain/commerce-list-workflows.test.ts index 92c175650..989167108 100644 --- a/__tests__/unit/domain/commerce-list-workflows.test.ts +++ b/__tests__/unit/domain/commerce-list-workflows.test.ts @@ -1,18 +1,20 @@ import { listEntitiesPage } from '@/domain/commerce/service'; -jest.mock('@/lib/supabase/server', () => ({ - createServerClient: jest.fn(), +vi.mock('@/lib/supabase/server', () => ({ + createServerClient: vi.fn(), })); -jest.mock('@/services/actors/getOrCreateUserActor', () => ({ - getOrCreateUserActor: jest.fn().mockResolvedValue({ id: 'a1' }), +vi.mock('@/services/actors/getOrCreateUserActor', () => ({ + getOrCreateUserActor: vi.fn().mockResolvedValue({ id: 'a1' }), })); import { createServerClient } from '@/lib/supabase/server'; +import type { Mock } from 'vitest'; + describe('Commerce list workflows (services/products/causes)', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); function makeSupabaseForRows(rows: any[], totalCount: number) { @@ -20,21 +22,21 @@ describe('Commerce list workflows (services/products/causes)', () => { const countResult = { count: totalCount, error: null }; const itemsQuery = { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - order: jest.fn().mockReturnThis(), - range: jest.fn().mockReturnThis(), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + order: vi.fn().mockReturnThis(), + range: vi.fn().mockReturnThis(), then: (resolve: (v: any) => unknown) => Promise.resolve(resolve(itemsResult)), } as any; const countQuery = { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), then: (resolve: (v: any) => unknown) => Promise.resolve(resolve(countResult)), } as any; - const from = jest.fn().mockReturnValueOnce(itemsQuery).mockReturnValueOnce(countQuery); - (createServerClient as jest.Mock).mockResolvedValue({ from }); + const from = vi.fn().mockReturnValueOnce(itemsQuery).mockReturnValueOnce(countQuery); + (createServerClient as Mock).mockResolvedValue({ from }); return { itemsQuery, countQuery }; } diff --git a/__tests__/unit/domain/entity-create-financial.test.ts b/__tests__/unit/domain/entity-create-financial.test.ts index 9ec5867b8..ce44af8a9 100644 --- a/__tests__/unit/domain/entity-create-financial.test.ts +++ b/__tests__/unit/domain/entity-create-financial.test.ts @@ -10,30 +10,32 @@ import { createLoan } from '@/domain/loans/service'; import { createInvestment } from '@/domain/investments/service'; -jest.mock('@/lib/supabase/server', () => ({ - createServerClient: jest.fn(), +vi.mock('@/lib/supabase/server', () => ({ + createServerClient: vi.fn(), })); -jest.mock('@/services/actors/getOrCreateUserActor', () => ({ - getOrCreateUserActor: jest.fn().mockResolvedValue({ id: 'actor-001' }), +vi.mock('@/services/actors/getOrCreateUserActor', () => ({ + getOrCreateUserActor: vi.fn().mockResolvedValue({ id: 'actor-001' }), })); import { createServerClient } from '@/lib/supabase/server'; +import type { Mock } from 'vitest'; + describe('Financial entity create workflows (loan/investment)', () => { const mockChain = { - insert: jest.fn().mockReturnThis(), - select: jest.fn().mockReturnThis(), - single: jest.fn(), + insert: vi.fn().mockReturnThis(), + select: vi.fn().mockReturnThis(), + single: vi.fn(), }; const mockClient = { - from: jest.fn(() => mockChain), + from: vi.fn(() => mockChain), }; beforeEach(() => { - jest.clearAllMocks(); - (createServerClient as jest.Mock).mockResolvedValue(mockClient); + vi.clearAllMocks(); + (createServerClient as Mock).mockResolvedValue(mockClient); }); // ==================== LOAN ==================== @@ -95,11 +97,11 @@ describe('Financial entity create workflows (loan/investment)', () => { it('propagates a supabase client passed from the route handler', async () => { const externalChain = { - insert: jest.fn().mockReturnThis(), - select: jest.fn().mockReturnThis(), - single: jest.fn().mockResolvedValue({ data: { id: 'loan-3' }, error: null }), + insert: vi.fn().mockReturnThis(), + select: vi.fn().mockReturnThis(), + single: vi.fn().mockResolvedValue({ data: { id: 'loan-3' }, error: null }), }; - const externalClient = { from: jest.fn(() => externalChain) }; + const externalClient = { from: vi.fn(() => externalChain) }; await createLoan( 'user-1', diff --git a/__tests__/unit/domain/entity-create-workflows.test.ts b/__tests__/unit/domain/entity-create-workflows.test.ts index a9f6c2a56..9a1ca2604 100644 --- a/__tests__/unit/domain/entity-create-workflows.test.ts +++ b/__tests__/unit/domain/entity-create-workflows.test.ts @@ -1,46 +1,48 @@ import { createProject } from '@/domain/projects/service'; import { createProduct, createCause } from '@/domain/commerce/service'; -jest.mock('@/lib/supabase/server', () => ({ - createServerClient: jest.fn(), +vi.mock('@/lib/supabase/server', () => ({ + createServerClient: vi.fn(), })); -jest.mock('@/lib/supabase/admin', () => ({ - createAdminClient: jest.fn(), +vi.mock('@/lib/supabase/admin', () => ({ + createAdminClient: vi.fn(), })); -jest.mock('@/services/actors/getOrCreateUserActor', () => ({ - getOrCreateUserActor: jest.fn().mockResolvedValue({ id: 'a1' }), +vi.mock('@/services/actors/getOrCreateUserActor', () => ({ + getOrCreateUserActor: vi.fn().mockResolvedValue({ id: 'a1' }), })); import { createServerClient } from '@/lib/supabase/server'; import { createAdminClient } from '@/lib/supabase/admin'; +import type { Mock } from 'vitest'; + describe('Entity create workflows (project/product/cause)', () => { const mockServerChain = { - insert: jest.fn().mockReturnThis(), - select: jest.fn().mockReturnThis(), - single: jest.fn(), + insert: vi.fn().mockReturnThis(), + select: vi.fn().mockReturnThis(), + single: vi.fn(), }; const mockAdminChain = { - insert: jest.fn().mockReturnThis(), - select: jest.fn().mockReturnThis(), - single: jest.fn(), + insert: vi.fn().mockReturnThis(), + select: vi.fn().mockReturnThis(), + single: vi.fn(), }; const mockServerClient = { - from: jest.fn(() => mockServerChain), + from: vi.fn(() => mockServerChain), }; const mockAdminClient = { - from: jest.fn(() => mockAdminChain), + from: vi.fn(() => mockAdminChain), }; beforeEach(() => { - jest.clearAllMocks(); - (createServerClient as jest.Mock).mockResolvedValue(mockServerClient); - (createAdminClient as jest.Mock).mockReturnValue(mockAdminClient); + vi.clearAllMocks(); + (createServerClient as Mock).mockResolvedValue(mockServerClient); + (createAdminClient as Mock).mockReturnValue(mockAdminClient); }); it('creates a project with draft defaults and CHF currency fallback', async () => { diff --git a/__tests__/unit/domain/loans/obligation.test.ts b/__tests__/unit/domain/loans/obligation.test.ts index 6ccc4d251..9d59630a6 100644 --- a/__tests__/unit/domain/loans/obligation.test.ts +++ b/__tests__/unit/domain/loans/obligation.test.ts @@ -5,8 +5,8 @@ import { createObligationLoanSchema } from '@/config/loan-obligation'; import { createObligationLoan } from '@/domain/loans/obligation'; -jest.mock('@/domain/base/entityService', () => ({ - createEntity: jest.fn().mockResolvedValue({ id: 'new-loan-id', status: 'active' }), +vi.mock('@/domain/base/entityService', () => ({ + createEntity: vi.fn().mockResolvedValue({ id: 'new-loan-id', status: 'active' }), })); describe('createObligationLoanSchema', () => { @@ -42,10 +42,10 @@ describe('createObligationLoan domain', () => { function mockSupabase(sourceUserId: string | null) { return { - from: jest.fn().mockReturnValue({ - select: jest.fn().mockReturnValue({ - eq: jest.fn().mockReturnValue({ - maybeSingle: jest.fn().mockResolvedValue({ + from: vi.fn().mockReturnValue({ + select: vi.fn().mockReturnValue({ + eq: vi.fn().mockReturnValue({ + maybeSingle: vi.fn().mockResolvedValue({ data: sourceUserId ? { id: sourceLoanId, user_id: sourceUserId } : null, error: null, }), diff --git a/__tests__/unit/domain/loans/offers.test.ts b/__tests__/unit/domain/loans/offers.test.ts index 6dd7b0872..0b2dfc0cd 100644 --- a/__tests__/unit/domain/loans/offers.test.ts +++ b/__tests__/unit/domain/loans/offers.test.ts @@ -25,12 +25,12 @@ describe('createLoanOffer domain', () => { function createSupabase(minimumOfferAmount: number | null = null) { return { - from: jest.fn((table: string) => { + from: vi.fn((table: string) => { if (table === 'loans') { return { - select: jest.fn().mockReturnValue({ - eq: jest.fn().mockReturnValue({ - maybeSingle: jest.fn().mockResolvedValue({ + select: vi.fn().mockReturnValue({ + eq: vi.fn().mockReturnValue({ + maybeSingle: vi.fn().mockResolvedValue({ data: { id: loanId, user_id: ownerId, @@ -45,9 +45,9 @@ describe('createLoanOffer domain', () => { } return { - insert: jest.fn().mockReturnValue({ - select: jest.fn().mockReturnValue({ - single: jest.fn().mockResolvedValue({ + insert: vi.fn().mockReturnValue({ + select: vi.fn().mockReturnValue({ + single: vi.fn().mockResolvedValue({ data: { id: 'offer-1', loan_id: loanId, offerer_id: offererId }, error: null, }), @@ -94,12 +94,12 @@ describe('createLoanOffer domain', () => { describe('updateLoanOffer domain', () => { it('returns not_found when the offer does not belong to the caller', async () => { const supabase = { - from: jest.fn().mockReturnValue({ - update: jest.fn().mockReturnValue({ - eq: jest.fn().mockReturnValue({ - eq: jest.fn().mockReturnValue({ - select: jest.fn().mockReturnValue({ - maybeSingle: jest.fn().mockResolvedValue({ data: null, error: null }), + from: vi.fn().mockReturnValue({ + update: vi.fn().mockReturnValue({ + eq: vi.fn().mockReturnValue({ + eq: vi.fn().mockReturnValue({ + select: vi.fn().mockReturnValue({ + maybeSingle: vi.fn().mockResolvedValue({ data: null, error: null }), }), }), }), @@ -127,12 +127,12 @@ describe('respondToLoanOffer domain', () => { it('rejects responses to non-pending offers', async () => { const supabase = { - from: jest.fn((table: string) => { + from: vi.fn((table: string) => { if (table === 'loan_offers') { return { - select: jest.fn().mockReturnValue({ - eq: jest.fn().mockReturnValue({ - maybeSingle: jest.fn().mockResolvedValue({ + select: vi.fn().mockReturnValue({ + eq: vi.fn().mockReturnValue({ + maybeSingle: vi.fn().mockResolvedValue({ data: { id: 'offer-2', loan_id: 'loan-2', diff --git a/__tests__/unit/domain/loans/payments.test.ts b/__tests__/unit/domain/loans/payments.test.ts index 76285d452..16ae36065 100644 --- a/__tests__/unit/domain/loans/payments.test.ts +++ b/__tests__/unit/domain/loans/payments.test.ts @@ -6,8 +6,8 @@ import { createLoanPaymentSchema } from '@/config/loan-payments'; import { createLoanPayment, completeLoanPayment } from '@/domain/loans/payments'; import { STATUS } from '@/config/database-constants'; -jest.mock('@/domain/loans/obligation', () => ({ - createObligationLoan: jest.fn().mockResolvedValue({ +vi.mock('@/domain/loans/obligation', () => ({ + createObligationLoan: vi.fn().mockResolvedValue({ ok: true, loan: { id: 'obligation-loan-id', status: 'active' }, }), @@ -40,20 +40,20 @@ describe('createLoanPayment domain', () => { recipient_id: recipientId, }; return { - from: jest.fn((table: string) => { + from: vi.fn((table: string) => { if (table === 'loans') { return { - select: jest.fn().mockReturnValue({ - eq: jest.fn().mockReturnValue({ - maybeSingle: jest.fn().mockResolvedValue({ data: { id: loanId }, error: null }), + select: vi.fn().mockReturnValue({ + eq: vi.fn().mockReturnValue({ + maybeSingle: vi.fn().mockResolvedValue({ data: { id: loanId }, error: null }), }), }), }; } return { - insert: jest.fn().mockReturnValue({ - select: jest.fn().mockReturnValue({ - single: jest.fn().mockResolvedValue({ data: paymentRow, error: null }), + insert: vi.fn().mockReturnValue({ + select: vi.fn().mockReturnValue({ + single: vi.fn().mockResolvedValue({ data: paymentRow, error: null }), }), }), }; @@ -123,10 +123,10 @@ describe('completeLoanPayment domain', () => { it('forbids users who are not payment parties', async () => { const supabase = { - from: jest.fn().mockReturnValue({ - select: jest.fn().mockReturnValue({ - eq: jest.fn().mockReturnValue({ - maybeSingle: jest.fn().mockResolvedValue({ + from: vi.fn().mockReturnValue({ + select: vi.fn().mockReturnValue({ + eq: vi.fn().mockReturnValue({ + maybeSingle: vi.fn().mockResolvedValue({ data: { id: 'payment-1', payer_id: 'other-payer', diff --git a/__tests__/unit/domain/payments/buyerConfirmPayment.test.ts b/__tests__/unit/domain/payments/buyerConfirmPayment.test.ts index a2186b3d6..8557353fb 100644 --- a/__tests__/unit/domain/payments/buyerConfirmPayment.test.ts +++ b/__tests__/unit/domain/payments/buyerConfirmPayment.test.ts @@ -25,30 +25,32 @@ import { getAdminClient } from '@/lib/supabase/admin'; import { STATUS } from '@/config/database-constants'; import { NotificationDispatcher } from '@/services/notifications/dispatcher'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); // Break the resend/email import chain (ESM-only, not transformed by jest). -jest.mock('@/lib/email/send-seller-notification', () => ({ - sendSellerPaymentNotification: jest.fn().mockResolvedValue(undefined), +vi.mock('@/lib/email/send-seller-notification', () => ({ + sendSellerPaymentNotification: vi.fn().mockResolvedValue(undefined), })); -jest.mock('@/services/notifications/dispatcher', () => ({ - NotificationDispatcher: { dispatch: jest.fn().mockResolvedValue(undefined) }, +vi.mock('@/services/notifications/dispatcher', () => ({ + NotificationDispatcher: { dispatch: vi.fn().mockResolvedValue(undefined) }, })); -jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); -jest.mock('@/services/webhooks/paymentSettledWebhook', () => ({ - enqueuePaymentSettledWebhook: jest.fn().mockResolvedValue(undefined), +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: vi.fn() })); +vi.mock('@/services/webhooks/paymentSettledWebhook', () => ({ + enqueuePaymentSettledWebhook: vi.fn().mockResolvedValue(undefined), })); -jest.mock('@/services/fleetcrown/entitlement-notify', () => ({ - notifyFleetCrownEntitlement: jest.fn().mockResolvedValue(undefined), - notifyFleetCrownProjectFunding: jest.fn().mockResolvedValue(undefined), +vi.mock('@/services/fleetcrown/entitlement-notify', () => ({ + notifyFleetCrownEntitlement: vi.fn().mockResolvedValue(undefined), + notifyFleetCrownProjectFunding: vi.fn().mockResolvedValue(undefined), })); -jest.mock('@/services/supporter/grant', () => ({ - grantSupporterPlan: jest.fn().mockResolvedValue(undefined), +vi.mock('@/services/supporter/grant', () => ({ + grantSupporterPlan: vi.fn().mockResolvedValue(undefined), })); -const getAdminClientMock = getAdminClient as jest.Mock; -const dispatchMock = NotificationDispatcher.dispatch as jest.Mock; +const getAdminClientMock = getAdminClient as Mock; +const dispatchMock = NotificationDispatcher.dispatch as Mock; const PI_ID = 'pi-1'; const BUYER = 'buyer-1'; @@ -60,31 +62,31 @@ const BUYER = 'buyer-1'; function makeCallerSupabase(intent: Record | null) { const builder: Record = {}; for (const m of ['select', 'update', 'eq', 'neq', 'in']) { - builder[m] = jest.fn(() => builder); + builder[m] = vi.fn(() => builder); } - builder.single = jest.fn(() => Promise.resolve({ data: intent, error: null })); - builder.maybeSingle = jest.fn(() => Promise.resolve({ data: intent, error: null })); + builder.single = vi.fn(() => Promise.resolve({ data: intent, error: null })); + builder.maybeSingle = vi.fn(() => Promise.resolve({ data: intent, error: null })); // An awaited caller-client write behaves like RLS silently filtering the row: // zero rows, no error. If production code ever writes through this client // again, the assertions on the admin client below will catch it. builder.then = (resolve: (v: unknown) => unknown, reject: (e: unknown) => unknown) => Promise.resolve({ data: [], error: null }).then(resolve, reject); - return { supabase: { from: jest.fn(() => builder) } as never, builder }; + return { supabase: { from: vi.fn(() => builder) } as never, builder }; } /** Admin client: serves all status-transition writes, in call order. */ function makeAdmin(awaitQueue: Array<{ data?: unknown; error: unknown }>) { const builder: Record = {}; for (const m of ['select', 'update', 'eq', 'neq', 'in']) { - builder[m] = jest.fn(() => builder); + builder[m] = vi.fn(() => builder); } builder.then = (resolve: (v: unknown) => unknown, reject: (e: unknown) => unknown) => Promise.resolve(awaitQueue.shift() ?? { data: [{ id: PI_ID }], error: null }).then( resolve, reject ); - const rpc = jest.fn(() => Promise.resolve({ error: null })); - const admin = { from: jest.fn(() => builder), rpc }; + const rpc = vi.fn(() => Promise.resolve({ error: null })); + const admin = { from: vi.fn(() => builder), rpc }; return { admin, builder }; } @@ -100,7 +102,7 @@ const fixedPriceIntent = { }; beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); getAdminClientMock.mockReturnValue(makeAdmin([]).admin); }); diff --git a/__tests__/unit/domain/payments/checkPaymentStatus.test.ts b/__tests__/unit/domain/payments/checkPaymentStatus.test.ts index a6ee849ca..64a99e010 100644 --- a/__tests__/unit/domain/payments/checkPaymentStatus.test.ts +++ b/__tests__/unit/domain/payments/checkPaymentStatus.test.ts @@ -11,37 +11,39 @@ import { checkPaymentStatus } from '@/domain/payments/paymentFlowService'; import { STATUS } from '@/config/database-constants'; import { getAdminClient } from '@/lib/supabase/admin'; -const getAdminClientMock = getAdminClient as jest.Mock; +import type { Mock } from 'vitest'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +const getAdminClientMock = getAdminClient as Mock; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/email/send-seller-notification', () => ({ - sendSellerPaymentNotification: jest.fn().mockResolvedValue(undefined), +vi.mock('@/lib/email/send-seller-notification', () => ({ + sendSellerPaymentNotification: vi.fn().mockResolvedValue(undefined), })); -jest.mock('@/services/notifications/dispatcher', () => ({ - NotificationDispatcher: { dispatch: jest.fn().mockResolvedValue(undefined) }, +vi.mock('@/services/notifications/dispatcher', () => ({ + NotificationDispatcher: { dispatch: vi.fn().mockResolvedValue(undefined) }, })); -jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: vi.fn() })); const PI_ID = 'pi-1'; const BUYER = 'buyer-1'; const SELLER = 'seller-1'; function makeSupabase(intent: Record | null) { - const update = jest.fn(); + const update = vi.fn(); const builder: Record = {}; for (const m of ['select', 'update', 'eq', 'in']) { - builder[m] = jest.fn((...args: unknown[]) => { + builder[m] = vi.fn((...args: unknown[]) => { if (m === 'update') update(...args); return builder; }); } - builder.single = jest.fn(() => Promise.resolve({ data: intent, error: null })); + builder.single = vi.fn(() => Promise.resolve({ data: intent, error: null })); // Awaited update chains resolve cleanly. builder.then = (resolve: (v: unknown) => unknown, reject: (e: unknown) => unknown) => Promise.resolve({ error: null }).then(resolve, reject); - const client = { from: jest.fn(() => builder) } as never; + const client = { from: vi.fn(() => builder) } as never; getAdminClientMock.mockReturnValue(client); return { client, update }; } diff --git a/__tests__/unit/domain/payments/exactlyOncePaid.test.ts b/__tests__/unit/domain/payments/exactlyOncePaid.test.ts index bee198174..a33341aa6 100644 --- a/__tests__/unit/domain/payments/exactlyOncePaid.test.ts +++ b/__tests__/unit/domain/payments/exactlyOncePaid.test.ts @@ -18,25 +18,27 @@ import { STATUS } from '@/config/database-constants'; import { checkOnchainPaymentStatus } from '@/domain/payments/paymentStatusService'; import { NotificationDispatcher } from '@/services/notifications/dispatcher'; import { getAdminClient } from '@/lib/supabase/admin'; -const getAdminClientMock = getAdminClient as jest.Mock; +import type { Mock } from 'vitest'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +const getAdminClientMock = getAdminClient as Mock; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/email/send-seller-notification', () => ({ - sendSellerPaymentNotification: jest.fn().mockResolvedValue(undefined), +vi.mock('@/lib/email/send-seller-notification', () => ({ + sendSellerPaymentNotification: vi.fn().mockResolvedValue(undefined), })); -jest.mock('@/services/notifications/dispatcher', () => ({ - NotificationDispatcher: { dispatch: jest.fn().mockResolvedValue(undefined) }, +vi.mock('@/services/notifications/dispatcher', () => ({ + NotificationDispatcher: { dispatch: vi.fn().mockResolvedValue(undefined) }, })); -jest.mock('@/domain/payments/paymentStatusService', () => ({ - checkNWCPaymentStatus: jest.fn(), - checkOnchainPaymentStatus: jest.fn(), +vi.mock('@/domain/payments/paymentStatusService', () => ({ + checkNWCPaymentStatus: vi.fn(), + checkOnchainPaymentStatus: vi.fn(), })); -jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: vi.fn() })); -const onchainMock = checkOnchainPaymentStatus as jest.Mock; -const dispatchMock = NotificationDispatcher.dispatch as jest.Mock; +const onchainMock = checkOnchainPaymentStatus as Mock; +const dispatchMock = NotificationDispatcher.dispatch as Mock; const PI_ID = 'pi-race'; const SELLER = 'seller-1'; @@ -63,21 +65,21 @@ const intent = { * PostgREST returns an empty array, no error. */ function makeSupabase(claimWon: boolean) { - const rpc = jest.fn(() => Promise.resolve({ error: null })); + const rpc = vi.fn(() => Promise.resolve({ error: null })); const builder: Record = {}; for (const m of ['select', 'update', 'eq', 'neq', 'in']) { - builder[m] = jest.fn(() => builder); + builder[m] = vi.fn(() => builder); } - builder.single = jest.fn(() => Promise.resolve({ data: intent, error: null })); + builder.single = vi.fn(() => Promise.resolve({ data: intent, error: null })); builder.then = (resolve: (v: unknown) => unknown, reject: (e: unknown) => unknown) => Promise.resolve({ data: claimWon ? [{ id: PI_ID }] : [], error: null }).then(resolve, reject); - const client = { from: jest.fn(() => builder), rpc } as never; + const client = { from: vi.fn(() => builder), rpc } as never; getAdminClientMock.mockReturnValue(client); return client; } beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); onchainMock.mockResolvedValue('confirmed'); }); @@ -99,18 +101,18 @@ describe('exactly-once settlement', () => { // ...but nothing may fire a second time. expect(dispatchMock).not.toHaveBeenCalled(); // Above all: no second inventory decrement (that would oversell). - expect((supabase as unknown as { rpc: jest.Mock }).rpc).not.toHaveBeenCalled(); + expect((supabase as unknown as { rpc: Mock }).rpc).not.toHaveBeenCalled(); }); it('notifies once when two observers report the same payment concurrently', async () => { // First caller claims the row; the second finds it already paid. let claimed = false; - const rpc = jest.fn(() => Promise.resolve({ error: null })); + const rpc = vi.fn(() => Promise.resolve({ error: null })); const builder: Record = {}; for (const m of ['select', 'update', 'eq', 'neq', 'in']) { - builder[m] = jest.fn(() => builder); + builder[m] = vi.fn(() => builder); } - builder.single = jest.fn(() => Promise.resolve({ data: intent, error: null })); + builder.single = vi.fn(() => Promise.resolve({ data: intent, error: null })); builder.then = (resolve: (v: unknown) => unknown, reject: (e: unknown) => unknown) => { const won = !claimed; claimed = true; @@ -119,7 +121,7 @@ describe('exactly-once settlement', () => { reject ); }; - const supabase = { from: jest.fn(() => builder), rpc } as never; + const supabase = { from: vi.fn(() => builder), rpc } as never; getAdminClientMock.mockReturnValue(supabase); await Promise.all([ diff --git a/__tests__/unit/domain/payments/fiatPricedAmount.test.ts b/__tests__/unit/domain/payments/fiatPricedAmount.test.ts index 072707999..29f1d8222 100644 --- a/__tests__/unit/domain/payments/fiatPricedAmount.test.ts +++ b/__tests__/unit/domain/payments/fiatPricedAmount.test.ts @@ -16,33 +16,35 @@ import { resolveAmount } from '@/domain/payments/paymentFlowHelpers'; import { convertToBtcOrNull } from '@/services/currency/rates.server'; import { getAdminClient } from '@/lib/supabase/admin'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/services/currency/rates.server', () => ({ - convertToBtcOrNull: jest.fn(), +vi.mock('@/services/currency/rates.server', () => ({ + convertToBtcOrNull: vi.fn(), })); -jest.mock('@/lib/supabase/admin', () => ({ - getAdminClient: jest.fn(), +vi.mock('@/lib/supabase/admin', () => ({ + getAdminClient: vi.fn(), })); -const convertMock = convertToBtcOrNull as jest.Mock; -const adminMock = getAdminClient as jest.Mock; +const convertMock = convertToBtcOrNull as Mock; +const adminMock = getAdminClient as Mock; /** Admin client serving one priced entity row. */ function withEntity(row: Record | null) { const builder: Record = {}; for (const m of ['select', 'eq']) { - builder[m] = jest.fn(() => builder); + builder[m] = vi.fn(() => builder); } - builder.single = jest.fn(() => Promise.resolve({ data: row, error: null })); - adminMock.mockReturnValue({ from: jest.fn(() => builder) }); + builder.single = vi.fn(() => Promise.resolve({ data: row, error: null })); + adminMock.mockReturnValue({ from: vi.fn(() => builder) }); } const supabase = {} as never; beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe('resolveAmount — fiat-priced entities', () => { diff --git a/__tests__/unit/domain/payments/handlePaymentConfirmed.test.ts b/__tests__/unit/domain/payments/handlePaymentConfirmed.test.ts index 481df3907..2599bf4fc 100644 --- a/__tests__/unit/domain/payments/handlePaymentConfirmed.test.ts +++ b/__tests__/unit/domain/payments/handlePaymentConfirmed.test.ts @@ -13,37 +13,39 @@ import { logger } from '@/utils/logger'; import { checkOnchainPaymentStatus } from '@/domain/payments/paymentStatusService'; import { NotificationDispatcher } from '@/services/notifications/dispatcher'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/email/send-seller-notification', () => ({ - sendSellerPaymentNotification: jest.fn().mockResolvedValue(undefined), +vi.mock('@/lib/email/send-seller-notification', () => ({ + sendSellerPaymentNotification: vi.fn().mockResolvedValue(undefined), })); -jest.mock('@/services/notifications/dispatcher', () => ({ - NotificationDispatcher: { dispatch: jest.fn().mockResolvedValue(undefined) }, +vi.mock('@/services/notifications/dispatcher', () => ({ + NotificationDispatcher: { dispatch: vi.fn().mockResolvedValue(undefined) }, })); -jest.mock('@/domain/payments/paymentStatusService', () => ({ - checkNWCPaymentStatus: jest.fn(), - checkOnchainPaymentStatus: jest.fn(), +vi.mock('@/domain/payments/paymentStatusService', () => ({ + checkNWCPaymentStatus: vi.fn(), + checkOnchainPaymentStatus: vi.fn(), })); -jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); -jest.mock('@/services/webhooks/paymentSettledWebhook', () => ({ - enqueuePaymentSettledWebhook: jest.fn().mockResolvedValue(undefined), +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: vi.fn() })); +vi.mock('@/services/webhooks/paymentSettledWebhook', () => ({ + enqueuePaymentSettledWebhook: vi.fn().mockResolvedValue(undefined), })); -jest.mock('@/services/fleetcrown/entitlement-notify', () => ({ - notifyFleetCrownEntitlement: jest.fn().mockResolvedValue(undefined), - notifyFleetCrownProjectFunding: jest.fn().mockResolvedValue(undefined), +vi.mock('@/services/fleetcrown/entitlement-notify', () => ({ + notifyFleetCrownEntitlement: vi.fn().mockResolvedValue(undefined), + notifyFleetCrownProjectFunding: vi.fn().mockResolvedValue(undefined), })); -jest.mock('@/services/supporter/grant', () => ({ - grantSupporterPlan: jest.fn().mockResolvedValue(undefined), +vi.mock('@/services/supporter/grant', () => ({ + grantSupporterPlan: vi.fn().mockResolvedValue(undefined), })); import { getAdminClient } from '@/lib/supabase/admin'; -const getAdminClientMock = getAdminClient as jest.Mock; -const errorMock = logger.error as jest.Mock; -const onchainMock = checkOnchainPaymentStatus as jest.Mock; -const dispatchMock = NotificationDispatcher.dispatch as jest.Mock; +import type { Mock } from 'vitest'; + +const getAdminClientMock = getAdminClient as Mock; +const errorMock = logger.error as Mock; +const onchainMock = checkOnchainPaymentStatus as Mock; +const dispatchMock = NotificationDispatcher.dispatch as Mock; const PI_ID = 'pi-1'; const BUYER = 'buyer-1'; @@ -79,21 +81,21 @@ function makeSupabase(orderUpdateError: unknown, intent: unknown = onchainIntent ]; const adminBuilder: Record = {}; for (const m of ['select', 'update', 'eq', 'neq', 'in']) { - adminBuilder[m] = jest.fn(() => adminBuilder); + adminBuilder[m] = vi.fn(() => adminBuilder); } adminBuilder.then = (resolve: (v: unknown) => unknown, reject: (e: unknown) => unknown) => Promise.resolve(awaitQueue.shift() ?? { error: null }).then(resolve, reject); - const rpc = jest.fn(() => Promise.resolve({ error: null })); - getAdminClientMock.mockReturnValue({ from: jest.fn(() => adminBuilder), rpc }); + const rpc = vi.fn(() => Promise.resolve({ error: null })); + getAdminClientMock.mockReturnValue({ from: vi.fn(() => adminBuilder), rpc }); const builder: Record = {}; for (const m of ['select', 'update', 'eq', 'neq', 'in']) { - builder[m] = jest.fn(() => builder); + builder[m] = vi.fn(() => builder); } - builder.single = jest.fn(() => Promise.resolve({ data: intent, error: null })); + builder.single = vi.fn(() => Promise.resolve({ data: intent, error: null })); builder.then = (resolve: (v: unknown) => unknown, reject: (e: unknown) => unknown) => Promise.resolve({ data: [], error: null }).then(resolve, reject); - return { from: jest.fn(() => builder), rpc: jest.fn() } as never; + return { from: vi.fn(() => builder), rpc: vi.fn() } as never; } /** A tip intent: entity-less, kind='tip'. Confirming it must NOT touch orders or @@ -120,7 +122,7 @@ function makeSupabaseReturning(intent: unknown) { } beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); onchainMock.mockResolvedValue('confirmed'); }); diff --git a/__tests__/unit/domain/payments/initiatePayment.guards.test.ts b/__tests__/unit/domain/payments/initiatePayment.guards.test.ts index e53b50cff..1d87ccf4e 100644 --- a/__tests__/unit/domain/payments/initiatePayment.guards.test.ts +++ b/__tests__/unit/domain/payments/initiatePayment.guards.test.ts @@ -10,23 +10,25 @@ import { initiatePayment } from '@/domain/payments/paymentFlowService'; import { getSellerUserId, resolveSellerWallet } from '@/domain/payments/walletResolutionService'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/domain/payments/walletResolutionService', () => ({ - getSellerUserId: jest.fn(), - resolveSellerWallet: jest.fn(), +vi.mock('@/domain/payments/walletResolutionService', () => ({ + getSellerUserId: vi.fn(), + resolveSellerWallet: vi.fn(), })); // Break the resend/email import chain (ESM-only, not transformed by jest). -jest.mock('@/lib/email/send-seller-notification', () => ({ - sendSellerPaymentNotification: jest.fn().mockResolvedValue(undefined), +vi.mock('@/lib/email/send-seller-notification', () => ({ + sendSellerPaymentNotification: vi.fn().mockResolvedValue(undefined), })); -jest.mock('@/services/notifications/dispatcher', () => ({ - NotificationDispatcher: { dispatch: jest.fn().mockResolvedValue(undefined) }, +vi.mock('@/services/notifications/dispatcher', () => ({ + NotificationDispatcher: { dispatch: vi.fn().mockResolvedValue(undefined) }, })); -const getSellerUserIdMock = getSellerUserId as jest.Mock; -const resolveSellerWalletMock = resolveSellerWallet as jest.Mock; +const getSellerUserIdMock = getSellerUserId as Mock; +const resolveSellerWalletMock = resolveSellerWallet as Mock; /** * Caller-scoped client serving only the publication-gate read. `visible` @@ -35,19 +37,19 @@ const resolveSellerWalletMock = resolveSellerWallet as jest.Mock; function makeSupabase(visible: boolean) { const builder: Record = {}; for (const m of ['select', 'eq']) { - builder[m] = jest.fn(() => builder); + builder[m] = vi.fn(() => builder); } - builder.maybeSingle = jest.fn(() => + builder.maybeSingle = vi.fn(() => Promise.resolve({ data: visible ? { id: 'prod-1' } : null, error: null }) ); - return { from: jest.fn(() => builder) } as never; + return { from: vi.fn(() => builder) } as never; } const BUYER = 'buyer-1'; const input = { entity_type: 'product' as const, entity_id: 'prod-1' }; beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe('initiatePayment — guards', () => { diff --git a/__tests__/unit/domain/payments/lnurlVerify.test.ts b/__tests__/unit/domain/payments/lnurlVerify.test.ts index f745c5805..e908fff79 100644 --- a/__tests__/unit/domain/payments/lnurlVerify.test.ts +++ b/__tests__/unit/domain/payments/lnurlVerify.test.ts @@ -10,23 +10,25 @@ import { checkLnurlVerifyPaymentStatus } from '@/domain/payments/paymentStatusSe import { checkPaymentStatus } from '@/domain/payments/paymentFlowService'; import { STATUS } from '@/config/database-constants'; import { getAdminClient } from '@/lib/supabase/admin'; -const getAdminClientMock = getAdminClient as jest.Mock; +import type { Mock } from 'vitest'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +const getAdminClientMock = getAdminClient as Mock; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/email/send-seller-notification', () => ({ - sendSellerPaymentNotification: jest.fn().mockResolvedValue(undefined), +vi.mock('@/lib/email/send-seller-notification', () => ({ + sendSellerPaymentNotification: vi.fn().mockResolvedValue(undefined), })); -jest.mock('@/services/notifications/dispatcher', () => ({ - NotificationDispatcher: { dispatch: jest.fn().mockResolvedValue(undefined) }, +vi.mock('@/services/notifications/dispatcher', () => ({ + NotificationDispatcher: { dispatch: vi.fn().mockResolvedValue(undefined) }, })); -jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: vi.fn() })); const VERIFY_URL = 'https://getalby.com/lnurlp/oc/verify/abc123'; function mockFetchOnce(body: unknown, ok = true) { - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ ok, json: () => Promise.resolve(body), }) as unknown as typeof fetch; @@ -62,14 +64,14 @@ describe('checkLnurlVerifyPaymentStatus', () => { }); it('returns false (never throws) on network error', async () => { - global.fetch = jest.fn().mockRejectedValue(new Error('timeout')) as unknown as typeof fetch; + global.fetch = vi.fn().mockRejectedValue(new Error('timeout')) as unknown as typeof fetch; await expect( checkLnurlVerifyPaymentStatus({ id: 'pi-1', lnurl_verify_url: VERIFY_URL }) ).resolves.toBe(false); }); it('returns false when no verify URL is stored (pre-LUD-21 intents)', async () => { - global.fetch = jest.fn() as unknown as typeof fetch; + global.fetch = vi.fn() as unknown as typeof fetch; await expect( checkLnurlVerifyPaymentStatus({ id: 'pi-1', lnurl_verify_url: null }) ).resolves.toBe(false); @@ -94,20 +96,20 @@ describe('checkPaymentStatus — lightning_address + verify URL', () => { }; function makeSupabase(intent: Record) { - const update = jest.fn(); + const update = vi.fn(); const builder: Record = {}; for (const m of ['select', 'update', 'eq', 'neq', 'in']) { - builder[m] = jest.fn((...args: unknown[]) => { + builder[m] = vi.fn((...args: unknown[]) => { if (m === 'update') update(...args); return builder; }); } - builder.single = jest.fn(() => Promise.resolve({ data: intent, error: null })); + builder.single = vi.fn(() => Promise.resolve({ data: intent, error: null })); // The paid transition is a conditional UPDATE … .neq('status','paid').select('id'): // a returned row means THIS caller won the claim and owns the side-effects. builder.then = (resolve: (v: unknown) => unknown, reject: (e: unknown) => unknown) => Promise.resolve({ data: [{ id: intent.id }], error: null }).then(resolve, reject); - const client = { from: jest.fn(() => builder) } as never; + const client = { from: vi.fn(() => builder) } as never; getAdminClientMock.mockReturnValue(client); return { client, update }; } diff --git a/__tests__/unit/domain/payments/payableOnchainAddress.test.ts b/__tests__/unit/domain/payments/payableOnchainAddress.test.ts index ee5f9c4e7..4c139ce34 100644 --- a/__tests__/unit/domain/payments/payableOnchainAddress.test.ts +++ b/__tests__/unit/domain/payments/payableOnchainAddress.test.ts @@ -18,13 +18,13 @@ import { import type { ResolvedWallet } from '@/domain/payments/types'; import type { SupabaseClient } from '@supabase/supabase-js'; -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn() }, })); -jest.mock('@/domain/payments/encryptionService', () => ({ decrypt: (v: string) => v })); +vi.mock('@/domain/payments/encryptionService', () => ({ decrypt: (v: string) => v })); -const rpcMock = jest.fn(); -jest.mock('@/lib/supabase/admin', () => ({ +const rpcMock = vi.fn(); +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: () => ({ rpc: rpcMock }), })); @@ -32,10 +32,10 @@ jest.mock('@/lib/supabase/admin', () => ({ function clientReturning(wallets: Array>): SupabaseClient { const builder: Record = {}; for (const m of ['select', 'eq']) { - builder[m] = jest.fn(() => builder); + builder[m] = vi.fn(() => builder); } let orderCalls = 0; - builder.order = jest.fn(() => { + builder.order = vi.fn(() => { orderCalls += 1; // Second .order() resolves the query. return orderCalls >= 2 ? Promise.resolve({ data: wallets, error: null }) : builder; diff --git a/__tests__/unit/domain/payments/paymentRequestService.test.ts b/__tests__/unit/domain/payments/paymentRequestService.test.ts index bb0eaeddd..a46a4f5b3 100644 --- a/__tests__/unit/domain/payments/paymentRequestService.test.ts +++ b/__tests__/unit/domain/payments/paymentRequestService.test.ts @@ -19,16 +19,18 @@ import { NotificationDispatcher } from '@/services/notifications/dispatcher'; import { PAY_MAX_BTC } from '@/config/pay'; import type { SupabaseClient } from '@supabase/supabase-js'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); -jest.mock('@/services/notifications/dispatcher', () => ({ - NotificationDispatcher: { dispatch: jest.fn().mockResolvedValue(undefined) }, +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: vi.fn() })); +vi.mock('@/services/notifications/dispatcher', () => ({ + NotificationDispatcher: { dispatch: vi.fn().mockResolvedValue(undefined) }, })); -const adminMock = getAdminClient as jest.Mock; -const dispatchMock = NotificationDispatcher.dispatch as jest.Mock; +const adminMock = getAdminClient as Mock; +const dispatchMock = NotificationDispatcher.dispatch as Mock; const REQUESTER = 'requester-1'; const PAYER = 'payer-1'; @@ -67,7 +69,7 @@ function makeCallerClient(inserted: Record[]) { } as unknown as SupabaseClient; } -beforeEach(() => jest.clearAllMocks()); +beforeEach(() => vi.clearAllMocks()); describe('createPaymentRequest', () => { it('writes through the caller client so RLS enforces authorship', async () => { diff --git a/__tests__/unit/domain/payments/publicPaymentStatus.test.ts b/__tests__/unit/domain/payments/publicPaymentStatus.test.ts index 8d1b603e1..641f5612e 100644 --- a/__tests__/unit/domain/payments/publicPaymentStatus.test.ts +++ b/__tests__/unit/domain/payments/publicPaymentStatus.test.ts @@ -26,25 +26,27 @@ import { DATABASE_TABLES } from '@/config/database-tables'; import { NotificationDispatcher } from '@/services/notifications/dispatcher'; import { createFakeSupabase, type Row } from '../../../../test-utils/fakeSupabase'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/email/send-seller-notification', () => ({ - sendSellerPaymentNotification: jest.fn().mockResolvedValue(undefined), +vi.mock('@/lib/email/send-seller-notification', () => ({ + sendSellerPaymentNotification: vi.fn().mockResolvedValue(undefined), })); -jest.mock('@/services/notifications/dispatcher', () => ({ - NotificationDispatcher: { dispatch: jest.fn().mockResolvedValue(undefined) }, +vi.mock('@/services/notifications/dispatcher', () => ({ + NotificationDispatcher: { dispatch: vi.fn().mockResolvedValue(undefined) }, })); -jest.mock('@/domain/payments/paymentStatusService', () => ({ - checkNWCPaymentStatus: jest.fn().mockResolvedValue(false), - checkOnchainPaymentStatus: jest.fn().mockResolvedValue('none'), - checkLnurlVerifyPaymentStatus: jest.fn().mockResolvedValue(false), +vi.mock('@/domain/payments/paymentStatusService', () => ({ + checkNWCPaymentStatus: vi.fn().mockResolvedValue(false), + checkOnchainPaymentStatus: vi.fn().mockResolvedValue('none'), + checkLnurlVerifyPaymentStatus: vi.fn().mockResolvedValue(false), })); -jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: vi.fn() })); import { getAdminClient } from '@/lib/supabase/admin'; -const getAdminClientMock = getAdminClient as jest.Mock; -const dispatchMock = NotificationDispatcher.dispatch as jest.Mock; +import type { Mock } from 'vitest'; + +const getAdminClientMock = getAdminClient as Mock; +const dispatchMock = NotificationDispatcher.dispatch as Mock; const PI_ID = 'pi-1'; const TOKEN = 'token-abc'; @@ -85,7 +87,7 @@ function world(row: Row) { return fake; } -beforeEach(() => jest.clearAllMocks()); +beforeEach(() => vi.clearAllMocks()); describe('the token is the authorisation', () => { it('reveals nothing to a wrong token', async () => { @@ -255,8 +257,8 @@ describe('expiry bounds when a payment can be MADE, not when it can be REPORTED' * ship-the-goods-for-no-money. bitbaum/orangecat#563 finding 3. */ describe('claims are budgeted per recipient', () => { - const allow = jest.fn(async () => true); - const refuse = jest.fn(async () => false); + const allow = vi.fn(async () => true); + const refuse = vi.fn(async () => false); beforeEach(() => { allow.mockClear(); diff --git a/__tests__/unit/domain/payments/resolveSellerWallet.test.ts b/__tests__/unit/domain/payments/resolveSellerWallet.test.ts index 91923a1bc..f2ec0c913 100644 --- a/__tests__/unit/domain/payments/resolveSellerWallet.test.ts +++ b/__tests__/unit/domain/payments/resolveSellerWallet.test.ts @@ -11,14 +11,16 @@ import { resolveSellerWallet } from '@/domain/payments/walletResolutionService'; import { getAdminClient } from '@/lib/supabase/admin'; import { DATABASE_TABLES } from '@/config/database-tables'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: vi.fn() })); // decrypt is identity here — we only assert which wallet is chosen, not crypto. -jest.mock('@/domain/payments/encryptionService', () => ({ decrypt: (s: string) => s })); +vi.mock('@/domain/payments/encryptionService', () => ({ decrypt: (s: string) => s })); -const getAdminClientMock = getAdminClient as jest.Mock; +const getAdminClientMock = getAdminClient as Mock; interface Fixtures { entityWallets: Array<{ wallet_id: string; is_primary: boolean }>; @@ -94,7 +96,7 @@ function baseFixtures(): Fixtures { }; } -beforeEach(() => jest.clearAllMocks()); +beforeEach(() => vi.clearAllMocks()); describe('resolveSellerWallet — entity-linked wallet precedence', () => { it('uses the wallet tied to the entity over the profile default', async () => { diff --git a/__tests__/unit/domain/payments/resolveSpecificUserWallet.test.ts b/__tests__/unit/domain/payments/resolveSpecificUserWallet.test.ts index 8e29f4d61..b0ec98937 100644 --- a/__tests__/unit/domain/payments/resolveSpecificUserWallet.test.ts +++ b/__tests__/unit/domain/payments/resolveSpecificUserWallet.test.ts @@ -9,13 +9,13 @@ import { resolveSpecificUserWallet } from '@/domain/payments/walletResolutionService'; import type { SupabaseClient } from '@supabase/supabase-js'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); -jest.mock('@/domain/payments/encryptionService', () => ({ - decrypt: jest.fn((v: string) => `decrypted:${v}`), - canDecrypt: jest.fn(() => true), +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: vi.fn() })); +vi.mock('@/domain/payments/encryptionService', () => ({ + decrypt: vi.fn((v: string) => `decrypted:${v}`), + canDecrypt: vi.fn(() => true), })); const USER = 'user-1'; @@ -25,14 +25,14 @@ const WALLET = 'wallet-1'; function makeSupabase(row: Record | null) { const filters: Array<[string, unknown]> = []; const builder: Record = {}; - builder.select = jest.fn(() => builder); - builder.eq = jest.fn((col: string, val: unknown) => { + builder.select = vi.fn(() => builder); + builder.eq = vi.fn((col: string, val: unknown) => { filters.push([col, val]); return builder; }); - builder.maybeSingle = jest.fn(() => Promise.resolve({ data: row, error: null })); + builder.maybeSingle = vi.fn(() => Promise.resolve({ data: row, error: null })); return { - client: { from: jest.fn(() => builder) } as unknown as SupabaseClient, + client: { from: vi.fn(() => builder) } as unknown as SupabaseClient, filters, }; } diff --git a/__tests__/unit/domain/payments/sellerIdentityAndReceiveInfo.test.ts b/__tests__/unit/domain/payments/sellerIdentityAndReceiveInfo.test.ts index f790e9475..d45b166a5 100644 --- a/__tests__/unit/domain/payments/sellerIdentityAndReceiveInfo.test.ts +++ b/__tests__/unit/domain/payments/sellerIdentityAndReceiveInfo.test.ts @@ -21,14 +21,16 @@ import { DATABASE_TABLES } from '@/config/database-tables'; import { getEntityMetadata } from '@/config/entity-registry'; import { createFakeSupabase, type Row } from '../../../../test-utils/fakeSupabase'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); -jest.mock('@/domain/payments/encryptionService', () => ({ decrypt: (s: string) => s })); +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: vi.fn() })); +vi.mock('@/domain/payments/encryptionService', () => ({ decrypt: (s: string) => s })); import { getAdminClient } from '@/lib/supabase/admin'; -const getAdminClientMock = getAdminClient as jest.Mock; +import type { Mock } from 'vitest'; + +const getAdminClientMock = getAdminClient as Mock; const PRODUCT = getEntityMetadata('product'); const ENTITY_ID = 'prod-1'; @@ -63,7 +65,7 @@ function wallet(over: Row): Row { }; } -beforeEach(() => jest.clearAllMocks()); +beforeEach(() => vi.clearAllMocks()); describe('resolveSellerReceiveInfo — what the owner is shown', () => { it('shows the Lightning address that would receive the payment', async () => { diff --git a/__tests__/unit/domain/payments/sendPaymentService.test.ts b/__tests__/unit/domain/payments/sendPaymentService.test.ts index 89a7183b2..07277e8cb 100644 --- a/__tests__/unit/domain/payments/sendPaymentService.test.ts +++ b/__tests__/unit/domain/payments/sendPaymentService.test.ts @@ -13,27 +13,29 @@ import { getAdminClient } from '@/lib/supabase/admin'; import { decrypt, isEncryptionConfigured } from '@/domain/payments/encryptionService'; import { NWCClient } from '@/lib/nostr/nwc'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); -jest.mock('@/domain/payments/encryptionService', () => ({ - decrypt: jest.fn(), - isEncryptionConfigured: jest.fn(() => true), +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: vi.fn() })); +vi.mock('@/domain/payments/encryptionService', () => ({ + decrypt: vi.fn(), + isEncryptionConfigured: vi.fn(() => true), })); -jest.mock('@/domain/payments/walletResolutionService', () => ({ resolveUserWallet: jest.fn() })); -jest.mock('@/domain/payments/invoiceGenerationService', () => ({ generateInvoice: jest.fn() })); -jest.mock('@/lib/nostr/nwc', () => ({ NWCClient: jest.fn() })); +vi.mock('@/domain/payments/walletResolutionService', () => ({ resolveUserWallet: vi.fn() })); +vi.mock('@/domain/payments/invoiceGenerationService', () => ({ generateInvoice: vi.fn() })); +vi.mock('@/lib/nostr/nwc', () => ({ NWCClient: vi.fn() })); -const adminMock = getAdminClient as jest.Mock; -const decryptMock = decrypt as jest.Mock; -const isEncryptionConfiguredMock = isEncryptionConfigured as jest.Mock; -const resolveWalletMock = resolveUserWallet as jest.Mock; -const generateInvoiceMock = generateInvoice as jest.Mock; -const NWCClientMock = NWCClient as unknown as jest.Mock; +const adminMock = getAdminClient as Mock; +const decryptMock = decrypt as Mock; +const isEncryptionConfiguredMock = isEncryptionConfigured as Mock; +const resolveWalletMock = resolveUserWallet as Mock; +const generateInvoiceMock = generateInvoice as Mock; +const NWCClientMock = NWCClient as unknown as Mock; const MAINNET_INVOICE = 'lnbc100u1pabcdef'; -const payInvoiceSpy = jest.fn(); +const payInvoiceSpy = vi.fn(); /** Admin client whose wallets query yields the given NWC row. */ function mockAdmin({ nwc, profileId }: { nwc?: string | null; profileId?: string | null } = {}) { @@ -58,13 +60,16 @@ function mockAdmin({ nwc, profileId }: { nwc?: string | null; profileId?: string } beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); payInvoiceSpy.mockResolvedValue({ payment_hash: 'hash-1' }); - NWCClientMock.mockImplementation(() => ({ - connect: jest.fn().mockResolvedValue(undefined), - payInvoice: payInvoiceSpy, - disconnect: jest.fn(), - })); + // function (not arrow): vitest constructs mock implementations with `new`. + NWCClientMock.mockImplementation(function () { + return { + connect: vi.fn().mockResolvedValue(undefined), + payInvoice: payInvoiceSpy, + disconnect: vi.fn(), + }; + }); decryptMock.mockReturnValue('nostr+walletconnect://sender'); isEncryptionConfiguredMock.mockReturnValue(true); }); diff --git a/__tests__/unit/domain/payments/settlementRailDispatch.test.ts b/__tests__/unit/domain/payments/settlementRailDispatch.test.ts index 0a960dd65..4b6dfabd1 100644 --- a/__tests__/unit/domain/payments/settlementRailDispatch.test.ts +++ b/__tests__/unit/domain/payments/settlementRailDispatch.test.ts @@ -22,27 +22,29 @@ import { DATABASE_TABLES } from '@/config/database-tables'; import type { PaymentIntent } from '@/domain/payments/types'; import { createFakeSupabase, type Row } from '../../../../test-utils/fakeSupabase'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/email/send-seller-notification', () => ({ - sendSellerPaymentNotification: jest.fn().mockResolvedValue(undefined), +vi.mock('@/lib/email/send-seller-notification', () => ({ + sendSellerPaymentNotification: vi.fn().mockResolvedValue(undefined), })); -jest.mock('@/services/notifications/dispatcher', () => ({ - NotificationDispatcher: { dispatch: jest.fn().mockResolvedValue(undefined) }, +vi.mock('@/services/notifications/dispatcher', () => ({ + NotificationDispatcher: { dispatch: vi.fn().mockResolvedValue(undefined) }, })); -jest.mock('@/domain/payments/paymentStatusService', () => ({ - checkNWCPaymentStatus: jest.fn(), - checkOnchainPaymentStatus: jest.fn(), - checkLnurlVerifyPaymentStatus: jest.fn(), +vi.mock('@/domain/payments/paymentStatusService', () => ({ + checkNWCPaymentStatus: vi.fn(), + checkOnchainPaymentStatus: vi.fn(), + checkLnurlVerifyPaymentStatus: vi.fn(), })); -jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: vi.fn() })); import { getAdminClient } from '@/lib/supabase/admin'; -const getAdminClientMock = getAdminClient as jest.Mock; -const nwcMock = checkNWCPaymentStatus as jest.Mock; -const onchainMock = checkOnchainPaymentStatus as jest.Mock; -const lnurlMock = checkLnurlVerifyPaymentStatus as jest.Mock; +import type { Mock } from 'vitest'; + +const getAdminClientMock = getAdminClient as Mock; +const nwcMock = checkNWCPaymentStatus as Mock; +const onchainMock = checkOnchainPaymentStatus as Mock; +const lnurlMock = checkLnurlVerifyPaymentStatus as Mock; const ALIVE = new Date(Date.now() + 60 * 60 * 1000).toISOString(); const DEAD = new Date(Date.now() - 60 * 60 * 1000).toISOString(); @@ -82,7 +84,7 @@ function world(pi: PaymentIntent) { } beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); nwcMock.mockResolvedValue(false); lnurlMock.mockResolvedValue(false); onchainMock.mockResolvedValue('none'); diff --git a/__tests__/unit/domain/payments/undetectableIntentLifecycle.test.ts b/__tests__/unit/domain/payments/undetectableIntentLifecycle.test.ts index 598b07c4b..5a1c8310b 100644 --- a/__tests__/unit/domain/payments/undetectableIntentLifecycle.test.ts +++ b/__tests__/unit/domain/payments/undetectableIntentLifecycle.test.ts @@ -16,34 +16,36 @@ import { STATUS } from '@/config/database-constants'; import type { PaymentIntent } from '@/domain/payments/types'; import type { SupabaseClient } from '@supabase/supabase-js'; import { getAdminClient } from '@/lib/supabase/admin'; -const getAdminClientMock = getAdminClient as jest.Mock; +import type { Mock } from 'vitest'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +const getAdminClientMock = getAdminClient as Mock; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/email/send-seller-notification', () => ({ - sendSellerPaymentNotification: jest.fn().mockResolvedValue(undefined), +vi.mock('@/lib/email/send-seller-notification', () => ({ + sendSellerPaymentNotification: vi.fn().mockResolvedValue(undefined), })); -jest.mock('@/services/notifications/dispatcher', () => ({ - NotificationDispatcher: { dispatch: jest.fn().mockResolvedValue(undefined) }, +vi.mock('@/services/notifications/dispatcher', () => ({ + NotificationDispatcher: { dispatch: vi.fn().mockResolvedValue(undefined) }, })); -jest.mock('@/domain/payments/paymentStatusService', () => ({ - checkNWCPaymentStatus: jest.fn(), - checkOnchainPaymentStatus: jest.fn(), - checkLnurlVerifyPaymentStatus: jest.fn(), +vi.mock('@/domain/payments/paymentStatusService', () => ({ + checkNWCPaymentStatus: vi.fn(), + checkOnchainPaymentStatus: vi.fn(), + checkLnurlVerifyPaymentStatus: vi.fn(), })); -jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: vi.fn() })); const updates: Array> = []; function makeSupabase(): SupabaseClient { const builder: Record = {}; - builder.update = jest.fn((patch: Record) => { + builder.update = vi.fn((patch: Record) => { updates.push(patch); return builder; }); - builder.eq = jest.fn(() => Promise.resolve({ error: null })); - const client = { from: jest.fn(() => builder) } as unknown as SupabaseClient; + builder.eq = vi.fn(() => Promise.resolve({ error: null })); + const client = { from: vi.fn(() => builder) } as unknown as SupabaseClient; getAdminClientMock.mockReturnValue(client); return client; } @@ -62,7 +64,7 @@ function bareLightningIntent(expiresAt: string): PaymentIntent { } beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); updates.length = 0; }); @@ -86,7 +88,7 @@ describe('undetectable intent around expiry', () => { }); it('never asks any rail about an undetectable intent — there is nothing to ask', async () => { - const statusService = jest.requireMock('@/domain/payments/paymentStatusService'); + const statusService = await vi.importMock('@/domain/payments/paymentStatusService'); makeSupabase(); await reconcilePaymentIntent(bareLightningIntent(new Date(Date.now() + 600_000).toISOString())); diff --git a/__tests__/unit/domain/payments/walletResolutionQueries.test.ts b/__tests__/unit/domain/payments/walletResolutionQueries.test.ts index 5fe7f0d22..b171680da 100644 --- a/__tests__/unit/domain/payments/walletResolutionQueries.test.ts +++ b/__tests__/unit/domain/payments/walletResolutionQueries.test.ts @@ -24,19 +24,21 @@ import { DATABASE_TABLES } from '@/config/database-tables'; import { getEntityMetadata } from '@/config/entity-registry'; import { createFakeSupabase, type Row } from '../../../../test-utils/fakeSupabase'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/supabase/admin', () => ({ getAdminClient: jest.fn() })); +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: vi.fn() })); // Identity decrypt: these tests assert which wallet wins, not the crypto. -jest.mock('@/domain/payments/encryptionService', () => ({ - decrypt: jest.fn((s: string) => s), +vi.mock('@/domain/payments/encryptionService', () => ({ + decrypt: vi.fn((s: string) => s), })); import { getAdminClient } from '@/lib/supabase/admin'; import { decrypt } from '@/domain/payments/encryptionService'; -const getAdminClientMock = getAdminClient as jest.Mock; -const decryptMock = decrypt as jest.Mock; +import type { Mock } from 'vitest'; + +const getAdminClientMock = getAdminClient as Mock; +const decryptMock = decrypt as Mock; const OWNER = 'user-1'; const STRANGER = 'user-2'; @@ -57,7 +59,7 @@ function wallet(over: Row): Row { } beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); decryptMock.mockImplementation((s: string) => s); }); diff --git a/__tests__/unit/domain/projects-list-workflow.test.ts b/__tests__/unit/domain/projects-list-workflow.test.ts index 79c989b58..06a9c5006 100644 --- a/__tests__/unit/domain/projects-list-workflow.test.ts +++ b/__tests__/unit/domain/projects-list-workflow.test.ts @@ -1,22 +1,24 @@ import { listProjectsPage } from '@/domain/projects/service'; -jest.mock('@/lib/supabase/server', () => ({ - createServerClient: jest.fn(), +vi.mock('@/lib/supabase/server', () => ({ + createServerClient: vi.fn(), })); -jest.mock('@/services/actors/getOrCreateUserActor', () => ({ - getOrCreateUserActor: jest.fn().mockResolvedValue({ id: 'a1' }), +vi.mock('@/services/actors/getOrCreateUserActor', () => ({ + getOrCreateUserActor: vi.fn().mockResolvedValue({ id: 'a1' }), })); // Funding enrichment converts settled BTC totals via the currency service — // keep the test deterministic (identity conversion, no rate fetch). -jest.mock('@/services/currency', () => ({ - currencyConverter: { getRates: jest.fn().mockResolvedValue({}) }, +vi.mock('@/services/currency', () => ({ + currencyConverter: { getRates: vi.fn().mockResolvedValue({}) }, convertBtcTo: (amountBtc: number) => amountBtc, })); import { createServerClient } from '@/lib/supabase/server'; +import type { Mock } from 'vitest'; + describe('Project list workflow', () => { const dataRows = [ { @@ -50,11 +52,11 @@ describe('Project list workflow', () => { */ function makeChainableQuery(resolveValue: any) { const query: any = { - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - in: jest.fn().mockReturnThis(), - order: jest.fn().mockReturnThis(), - range: jest.fn().mockReturnThis(), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + in: vi.fn().mockReturnThis(), + order: vi.fn().mockReturnThis(), + range: vi.fn().mockReturnThis(), }; // Make query thenable so Promise.all resolves it query.then = (resolve: any, reject: any) => Promise.resolve(resolveValue).then(resolve, reject); @@ -62,22 +64,22 @@ describe('Project list workflow', () => { } beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('lists active projects and maps funding from the settled ledger, not the dead column', async () => { const dataQuery = makeChainableQuery({ data: dataRows, error: null }); const countQuery = makeChainableQuery({ count: 2, error: null }); - const from = jest.fn().mockReturnValueOnce(dataQuery).mockReturnValueOnce(countQuery); + const from = vi.fn().mockReturnValueOnce(dataQuery).mockReturnValueOnce(countQuery); // Settled funding stats: only p2 has real contributions. The raised_amount // column value (1200 on p2) must be IGNORED — nothing ever writes it. - const rpc = jest.fn().mockResolvedValue({ + const rpc = vi.fn().mockResolvedValue({ data: [{ entity_id: 'p2', total_btc: 0.01, contributor_count: 2, named_supporter_count: 1 }], error: null, }); - (createServerClient as jest.Mock).mockResolvedValue({ from, rpc }); + (createServerClient as Mock).mockResolvedValue({ from, rpc }); const result = await listProjectsPage(20, 0); @@ -96,9 +98,9 @@ describe('Project list workflow', () => { const dataQuery = makeChainableQuery({ data: [dataRows[0]], error: null }); const countQuery = makeChainableQuery({ count: 1, error: null }); - const from = jest.fn().mockReturnValueOnce(dataQuery).mockReturnValueOnce(countQuery); + const from = vi.fn().mockReturnValueOnce(dataQuery).mockReturnValueOnce(countQuery); - (createServerClient as jest.Mock).mockResolvedValue({ from }); + (createServerClient as Mock).mockResolvedValue({ from }); const result = await listProjectsPage(20, 0, 'u1'); diff --git a/__tests__/unit/domain/wallets/transferService.test.ts b/__tests__/unit/domain/wallets/transferService.test.ts index 6e6b5b44e..c5934748f 100644 --- a/__tests__/unit/domain/wallets/transferService.test.ts +++ b/__tests__/unit/domain/wallets/transferService.test.ts @@ -8,11 +8,11 @@ import { executeWalletTransfer } from '@/domain/wallets/transferService'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/lib/api/auditLog', () => ({ - auditSuccess: jest.fn().mockResolvedValue(undefined), +vi.mock('@/lib/api/auditLog', () => ({ + auditSuccess: vi.fn().mockResolvedValue(undefined), AUDIT_ACTIONS: { WALLET_BALANCE_REFRESHED: 'wallet.balance_refreshed' }, })); @@ -30,15 +30,15 @@ function makeSupabase(responses: Array<{ data?: unknown; error?: unknown }>) { const builder: Record = {}; for (const m of ['select', 'in', 'eq', 'insert', 'update']) { - builder[m] = jest.fn(() => builder); + builder[m] = vi.fn(() => builder); } - builder.single = jest.fn(() => Promise.resolve(next())); + builder.single = vi.fn(() => Promise.resolve(next())); // Make the builder thenable so `await from().select().in().eq()` resolves. builder.then = (resolve: (v: unknown) => unknown, reject: (e: unknown) => unknown) => Promise.resolve(next()).then(resolve, reject); - const rpc = jest.fn(() => Promise.resolve(next())); - return { client: { from: jest.fn(() => builder), rpc }, rpc }; + const rpc = vi.fn(() => Promise.resolve(next())); + return { client: { from: vi.fn(() => builder), rpc }, rpc }; } const twoWallets = () => [ diff --git a/__tests__/unit/hooks/messaging-live-writes.test.tsx b/__tests__/unit/hooks/messaging-live-writes.test.tsx index c9a3ab197..b606a9fbb 100644 --- a/__tests__/unit/hooks/messaging-live-writes.test.tsx +++ b/__tests__/unit/hooks/messaging-live-writes.test.tsx @@ -20,28 +20,32 @@ import { renderHook, act, waitFor } from '@testing-library/react'; -const upsert = jest.fn().mockResolvedValue({ error: null }); -const del = jest.fn(); -const eq2 = jest.fn().mockResolvedValue({ error: null }); -const eq1 = jest.fn(() => ({ eq: eq2 })); -const from = jest.fn(() => ({ upsert, delete: del })); +const upsert = vi.fn().mockResolvedValue({ error: null }); +const del = vi.fn(); +const eq2 = vi.fn().mockResolvedValue({ error: null }); +const eq1 = vi.fn(() => ({ eq: eq2 })); +const from = vi.fn(() => ({ upsert, delete: del })); del.mockImplementation(() => ({ eq: eq1 })); -jest.mock('@/lib/supabase/browser', () => ({ +vi.mock('@/lib/supabase/browser', () => ({ __esModule: true, - default: { from: (...a: unknown[]) => from(...(a as [])), channel: () => ({ on: () => ({ subscribe: () => ({}) }) }), removeChannel: () => {} }, + default: { + from: (...a: unknown[]) => from(...(a as [])), + channel: () => ({ on: () => ({ subscribe: () => ({}) }) }), + removeChannel: () => {}, + }, })); -jest.mock('@/hooks/useAuth', () => ({ +vi.mock('@/hooks/useAuth', () => ({ useAuth: () => ({ user: { id: 'user-1' } }), })); // The subscription half is a separate concern; keep this test on the writes. -jest.mock('@/features/messaging/hooks/useTypingSubscription', () => ({ +vi.mock('@/features/messaging/hooks/useTypingSubscription', () => ({ useTypingSubscription: () => [], })); -jest.mock('@/features/messaging/hooks/usePresenceActivity', () => ({ +vi.mock('@/features/messaging/hooks/usePresenceActivity', () => ({ usePresenceActivity: () => {}, })); diff --git a/__tests__/unit/hooks/useAwaitCatReply.test.ts b/__tests__/unit/hooks/useAwaitCatReply.test.ts index a10518ba9..7ac8bbaf3 100644 --- a/__tests__/unit/hooks/useAwaitCatReply.test.ts +++ b/__tests__/unit/hooks/useAwaitCatReply.test.ts @@ -18,8 +18,8 @@ import { renderHook, act } from '@testing-library/react'; import { useAwaitCatReply } from '@/hooks/useAwaitCatReply'; import type { TimelineDisplayEvent } from '@/types/timeline'; -const getReplies = jest.fn(); -jest.mock('@/services/timeline', () => ({ +const getReplies = vi.fn(); +vi.mock('@/services/timeline', () => ({ timelineService: { getReplies: (...a: unknown[]) => getReplies(...a) }, })); @@ -28,14 +28,14 @@ const reply = (description: string): TimelineDisplayEvent => describe('useAwaitCatReply', () => { beforeEach(() => { - jest.clearAllMocks(); - jest.useFakeTimers(); + vi.clearAllMocks(); + vi.useFakeTimers(); getReplies.mockResolvedValue({ replies: [] }); }); - afterEach(() => jest.useRealTimers()); + afterEach(() => vi.useRealTimers()); it('waits after a reply that tags the Cat', () => { - const { result } = renderHook(() => useAwaitCatReply({ onArrived: jest.fn() })); + const { result } = renderHook(() => useAwaitCatReply({ onArrived: vi.fn() })); act(() => result.current.watchIfTagged(reply('@cat what is this?'))); @@ -43,7 +43,7 @@ describe('useAwaitCatReply', () => { }); it('does not wait for a reply that never mentioned the Cat', () => { - const { result } = renderHook(() => useAwaitCatReply({ onArrived: jest.fn() })); + const { result } = renderHook(() => useAwaitCatReply({ onArrived: vi.fn() })); act(() => result.current.watchIfTagged(reply('just talking to people here'))); @@ -51,7 +51,7 @@ describe('useAwaitCatReply', () => { }); it('is not fooled by a handle that merely starts with cat', () => { - const { result } = renderHook(() => useAwaitCatReply({ onArrived: jest.fn() })); + const { result } = renderHook(() => useAwaitCatReply({ onArrived: vi.fn() })); act(() => result.current.watchIfTagged(reply('@catalogue is a different account'))); @@ -59,7 +59,7 @@ describe('useAwaitCatReply', () => { }); it('hands over the answer and stops waiting once it arrives', async () => { - const onArrived = jest.fn(); + const onArrived = vi.fn(); const catReply = { id: 'c1', metadata: { is_cat_reply: true } }; getReplies.mockResolvedValue({ replies: [catReply] }); @@ -77,7 +77,7 @@ describe('useAwaitCatReply', () => { }); it('ignores replies from anyone else while waiting', async () => { - const onArrived = jest.fn(); + const onArrived = vi.fn(); // Somebody else answering first must not end the wait — the Cat's answer is // what was asked for. getReplies.mockResolvedValue({ replies: [{ id: 'human', metadata: {} }] }); @@ -96,7 +96,7 @@ describe('useAwaitCatReply', () => { }); it('gives up rather than waiting forever', async () => { - const { result } = renderHook(() => useAwaitCatReply({ onArrived: jest.fn() })); + const { result } = renderHook(() => useAwaitCatReply({ onArrived: vi.fn() })); await act(async () => { result.current.watchIfTagged(reply('@cat explain')); @@ -107,7 +107,7 @@ describe('useAwaitCatReply', () => { // reply — so silence past the window means something upstream is wrong, and // a spinner that never resolves is worse than none. await act(async () => { - jest.advanceTimersByTime(65_000); + vi.advanceTimersByTime(65_000); await Promise.resolve(); }); diff --git a/__tests__/unit/hooks/useContentEditableEditor.test.tsx b/__tests__/unit/hooks/useContentEditableEditor.test.tsx index 8d139dfbc..6b2f10f00 100644 --- a/__tests__/unit/hooks/useContentEditableEditor.test.tsx +++ b/__tests__/unit/hooks/useContentEditableEditor.test.tsx @@ -18,11 +18,11 @@ import { renderHook, act } from '@testing-library/react'; import { useContentEditableEditor } from '@/hooks/useContentEditableEditor'; -jest.mock('@/utils/markdownEditor', () => ({ +vi.mock('@/utils/markdownEditor', () => ({ markdownToHtml: (md: string) => md, htmlToMarkdown: (html: string) => html, getSelectionRange: () => ({ start: 0, end: 0 }), - setSelectionRange: jest.fn(), + setSelectionRange: vi.fn(), })); /** @@ -38,7 +38,7 @@ function mount(initial: string) { const view = renderHook( ({ content }: { content: string }) => - useContentEditableEditor({ content, onContentChange: jest.fn() }), + useContentEditableEditor({ content, onContentChange: vi.fn() }), { initialProps: { content: initial } } ); diff --git a/__tests__/unit/hooks/useDisplayCurrency.test.ts b/__tests__/unit/hooks/useDisplayCurrency.test.ts index f7fe091da..a0201681b 100644 --- a/__tests__/unit/hooks/useDisplayCurrency.test.ts +++ b/__tests__/unit/hooks/useDisplayCurrency.test.ts @@ -15,10 +15,10 @@ let mockCurrency = 'CHF'; let mockIsLoading = false; const CHF_PER_BTC = 86000; -jest.mock('@/hooks/useUserCurrency', () => ({ +vi.mock('@/hooks/useUserCurrency', () => ({ useUserCurrency: () => mockCurrency, })); -jest.mock('@/hooks/useCurrencyConversion', () => ({ +vi.mock('@/hooks/useCurrencyConversion', () => ({ useCurrencyConversion: () => ({ isLoading: mockIsLoading, convertFromBTC: (btc: number, currency: string) => (currency === 'CHF' ? btc * CHF_PER_BTC : 0), diff --git a/__tests__/unit/hooks/useEntityCreateEdit.test.ts b/__tests__/unit/hooks/useEntityCreateEdit.test.ts index 23b8d639b..35c4d3014 100644 --- a/__tests__/unit/hooks/useEntityCreateEdit.test.ts +++ b/__tests__/unit/hooks/useEntityCreateEdit.test.ts @@ -8,7 +8,7 @@ import { renderHook, waitFor } from '@testing-library/react'; import { useEntityCreateEdit } from '@/hooks/useEntityCreateEdit'; let searchParams = new URLSearchParams(); -jest.mock('next/navigation', () => ({ +vi.mock('next/navigation', () => ({ useSearchParams: () => searchParams, })); @@ -16,32 +16,32 @@ const mockAuth: { user: { id: string } | null; hydrated: boolean } = { user: { id: 'user-1' }, hydrated: true, }; -jest.mock('@/hooks/useAuth', () => ({ +vi.mock('@/hooks/useAuth', () => ({ useAuth: () => mockAuth, })); const mockPrefill: { initialData: Record | undefined } = { initialData: undefined, }; -jest.mock('@/hooks/useCreatePrefill', () => ({ - useCreatePrefill: jest.fn(() => mockPrefill), +vi.mock('@/hooks/useCreatePrefill', () => ({ + useCreatePrefill: vi.fn(() => mockPrefill), })); -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn() }, })); import { useCreatePrefill } from '@/hooks/useCreatePrefill'; describe('useEntityCreateEdit', () => { afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); searchParams = new URLSearchParams(); mockPrefill.initialData = undefined; }); it('create mode (no ?edit): no fetch, prefill enabled, not loading', async () => { - global.fetch = jest.fn() as unknown as typeof fetch; + global.fetch = vi.fn() as unknown as typeof fetch; mockPrefill.initialData = { title: 'From Cat' }; const { result } = renderHook(() => useEntityCreateEdit('cause')); @@ -57,7 +57,7 @@ describe('useEntityCreateEdit', () => { it('edit mode: fetches `${apiEndpoint}/${id}` and exposes the entity for prefill', async () => { searchParams = new URLSearchParams('edit=cause-1'); const row = { id: 'cause-1', title: 'Clean water', target_amount: 500 }; - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ ok: true, json: () => Promise.resolve({ success: true, data: row }), }) as unknown as typeof fetch; @@ -79,7 +79,7 @@ describe('useEntityCreateEdit', () => { it('edit mode uses the registry apiEndpoint per entity type', async () => { searchParams = new URLSearchParams('edit=g-1'); - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ ok: true, json: () => Promise.resolve({ success: true, data: { id: 'g-1', name: 'DAO' } }), }) as unknown as typeof fetch; @@ -95,7 +95,7 @@ describe('useEntityCreateEdit', () => { it('edit mode: 404 → "not found" edit error, no entity data', async () => { searchParams = new URLSearchParams('edit=missing'); - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ ok: false, status: 404, json: () => Promise.resolve({ success: false }), @@ -111,7 +111,7 @@ describe('useEntityCreateEdit', () => { it('edit mode waits for auth hydration before fetching', () => { searchParams = new URLSearchParams('edit=cause-1'); mockAuth.hydrated = false; - global.fetch = jest.fn() as unknown as typeof fetch; + global.fetch = vi.fn() as unknown as typeof fetch; const { result } = renderHook(() => useEntityCreateEdit('cause')); diff --git a/__tests__/unit/hooks/useNavigation.test.ts b/__tests__/unit/hooks/useNavigation.test.ts index 22d9ae23c..4ed7c7e09 100644 --- a/__tests__/unit/hooks/useNavigation.test.ts +++ b/__tests__/unit/hooks/useNavigation.test.ts @@ -22,10 +22,10 @@ import type { NavSection } from '@/hooks/useNavigation'; let capturedOnStateLoaded: ((...args: unknown[]) => void) | undefined; let capturedOnLoadFailed: ((...args: unknown[]) => void) | undefined; -jest.mock('@/hooks/useNavigationStorage', () => ({ - buildInitialCollapsedSections: jest.fn(() => new Set()), - clearNavigationStorage: jest.fn(), - useNavigationStorage: jest.fn( +vi.mock('@/hooks/useNavigationStorage', () => ({ + buildInitialCollapsedSections: vi.fn(() => new Set()), + clearNavigationStorage: vi.fn(), + useNavigationStorage: vi.fn( ( _hydrated: boolean, _sections: NavSection[], @@ -37,29 +37,29 @@ jest.mock('@/hooks/useNavigationStorage', () => ({ capturedOnStateLoaded = onStateLoaded; capturedOnLoadFailed = onLoadFailed; return { - persistSidebarState: jest.fn(), - persistSidebarCollapsedState: jest.fn(), - persistCollapsedSections: jest.fn(), + persistSidebarState: vi.fn(), + persistSidebarCollapsedState: vi.fn(), + persistCollapsedSections: vi.fn(), }; } ), })); -jest.mock('@/hooks/useActiveNavItem', () => ({ - useActiveNavItem: jest.fn(() => ({ +vi.mock('@/hooks/useActiveNavItem', () => ({ + useActiveNavItem: vi.fn(() => ({ activeSection: null, activeItem: null, - isItemActive: jest.fn(() => false), + isItemActive: vi.fn(() => false), })), })); // Mock useAuth: hydrated by default, no user/profile. -const mockUseAuth = jest.fn(() => ({ +const mockUseAuth = vi.fn(() => ({ user: null, profile: null, hydrated: true, })); -jest.mock('@/hooks/useAuth', () => ({ +vi.mock('@/hooks/useAuth', () => ({ useAuth: (...args: unknown[]) => mockUseAuth(...args), })); @@ -87,7 +87,7 @@ describe('useNavigation — stable callback refs (regression: infinite loop fix) beforeEach(() => { capturedOnStateLoaded = undefined; capturedOnLoadFailed = undefined; - jest.clearAllMocks(); + vi.clearAllMocks(); mockUseAuth.mockReturnValue({ user: null, profile: null, hydrated: true }); }); @@ -142,7 +142,7 @@ describe('useNavigation — stable callback refs (regression: infinite loop fix) describe('useNavigation — getFilteredSections', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('returns empty array when not hydrated', () => { @@ -206,7 +206,7 @@ describe('useNavigation — getFilteredSections', () => { describe('useNavigation — toggle functions', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); mockUseAuth.mockReturnValue({ user: null, profile: null, hydrated: true }); }); diff --git a/__tests__/unit/hooks/useNavigationContext-hides-fixture-groups.test.ts b/__tests__/unit/hooks/useNavigationContext-hides-fixture-groups.test.ts index b44d94071..10c7430af 100644 --- a/__tests__/unit/hooks/useNavigationContext-hides-fixture-groups.test.ts +++ b/__tests__/unit/hooks/useNavigationContext-hides-fixture-groups.test.ts @@ -13,10 +13,10 @@ import { renderHook, waitFor } from '@testing-library/react'; import { useNavigationContext } from '@/hooks/useNavigationContext'; const mockStableAuth = { user: { id: 'user-1' } }; -jest.mock('@/hooks/useAuth', () => ({ +vi.mock('@/hooks/useAuth', () => ({ useAuth: () => mockStableAuth, })); -jest.mock('next/navigation', () => ({ +vi.mock('next/navigation', () => ({ usePathname: () => '/dashboard', })); @@ -28,7 +28,7 @@ const GROUPS = [ ]; beforeEach(() => { - global.fetch = jest.fn(() => + global.fetch = vi.fn(() => Promise.resolve({ ok: true, json: async () => ({ success: true, data: { groups: GROUPS } }), diff --git a/__tests__/unit/hooks/useNavigationStorage.test.ts b/__tests__/unit/hooks/useNavigationStorage.test.ts index 29d8c0faf..2e144a076 100644 --- a/__tests__/unit/hooks/useNavigationStorage.test.ts +++ b/__tests__/unit/hooks/useNavigationStorage.test.ts @@ -6,6 +6,8 @@ import { } from '@/hooks/useNavigationStorage'; import type { NavSection } from '@/hooks/useNavigation'; +import type { Mock } from 'vitest'; + // ─── helpers ──────────────────────────────────────────────────────────────── const STORAGE_KEYS = { @@ -45,16 +47,16 @@ const basicSections: NavSection[] = [ // We provide a real in-memory backing store per test. function setupLocalStorageMock() { const store: Record = {}; - jest - .spyOn(window.localStorage, 'getItem') - .mockImplementation(key => (key in store ? store[key] : null)); - jest.spyOn(window.localStorage, 'setItem').mockImplementation((key, val) => { + vi.spyOn(window.localStorage, 'getItem').mockImplementation(key => + key in store ? store[key] : null + ); + vi.spyOn(window.localStorage, 'setItem').mockImplementation((key, val) => { store[key] = val; }); - jest.spyOn(window.localStorage, 'removeItem').mockImplementation(key => { + vi.spyOn(window.localStorage, 'removeItem').mockImplementation(key => { delete store[key]; }); - jest.spyOn(window.localStorage, 'clear').mockImplementation(() => { + vi.spyOn(window.localStorage, 'clear').mockImplementation(() => { Object.keys(store).forEach(k => delete store[k]); }); return store; @@ -129,7 +131,7 @@ describe('clearNavigationStorage', () => { }); afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); it('removes all three storage keys', () => { @@ -152,17 +154,17 @@ describe('clearNavigationStorage', () => { // ─── useNavigationStorage ─────────────────────────────────────────────────── describe('useNavigationStorage', () => { - let onStateLoaded: jest.Mock; - let onLoadFailed: jest.Mock; + let onStateLoaded: Mock; + let onLoadFailed: Mock; beforeEach(() => { - onStateLoaded = jest.fn(); - onLoadFailed = jest.fn(); + onStateLoaded = vi.fn(); + onLoadFailed = vi.fn(); setupLocalStorageMock(); }); afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); it('does not call onStateLoaded when hydrated is false', () => { @@ -233,7 +235,7 @@ describe('useNavigationStorage', () => { }); it('calls onLoadFailed when localStorage throws', () => { - jest.spyOn(window.localStorage, 'getItem').mockImplementation(() => { + vi.spyOn(window.localStorage, 'getItem').mockImplementation(() => { throw new Error('storage error'); }); @@ -248,17 +250,17 @@ describe('useNavigationStorage', () => { // (stable ref pattern) remains necessary. it('re-fires the effect when a new callback reference is passed', () => { const { rerender } = renderHook( - ({ cb }: { cb: jest.Mock }) => + ({ cb }: { cb: Mock }) => useNavigationStorage(true, basicSections, { onStateLoaded: cb, - onLoadFailed: jest.fn(), + onLoadFailed: vi.fn(), }), { initialProps: { cb: onStateLoaded } } ); expect(onStateLoaded).toHaveBeenCalledTimes(1); - const newCb = jest.fn(); + const newCb = vi.fn(); act(() => { rerender({ cb: newCb }); }); diff --git a/__tests__/unit/hooks/useNotifications.test.ts b/__tests__/unit/hooks/useNotifications.test.ts index 71a9c93e6..ba2d8fd8d 100644 --- a/__tests__/unit/hooks/useNotifications.test.ts +++ b/__tests__/unit/hooks/useNotifications.test.ts @@ -17,24 +17,24 @@ import { API_ROUTES } from '@/config/api-routes'; // Stable references — real useAuth returns a stable user across renders, so the // mock must too (a fresh object each render would itself retrigger the effect). const mockStableAuth = { user: { id: 'user-1' } }; -jest.mock('@/hooks/useAuth', () => ({ +vi.mock('@/hooks/useAuth', () => ({ useAuth: () => mockStableAuth, })); -jest.mock('@/hooks/useNotificationsRealtime', () => ({ - useNotificationsRealtime: jest.fn(), +vi.mock('@/hooks/useNotificationsRealtime', () => ({ + useNotificationsRealtime: vi.fn(), })); -jest.mock('@/hooks/useNotificationsMutations', () => ({ +vi.mock('@/hooks/useNotificationsMutations', () => ({ useNotificationsMutations: () => ({ - markAsRead: jest.fn(), - deleteNotification: jest.fn(), - clearRead: jest.fn(), + markAsRead: vi.fn(), + deleteNotification: vi.fn(), + clearRead: vi.fn(), }), })); const listUrl = (url: string) => url.startsWith(API_ROUTES.NOTIFICATIONS.BASE + '?'); function mockFetch() { - return jest.fn((url: string) => { + return vi.fn((url: string) => { if (url === API_ROUTES.NOTIFICATIONS.UNREAD) { return Promise.resolve({ ok: true, @@ -49,7 +49,7 @@ function mockFetch() { } afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); describe('useNotifications — no double-fetch', () => { diff --git a/__tests__/unit/hooks/usePostComposerClears.test.ts b/__tests__/unit/hooks/usePostComposerClears.test.ts index 06a878889..1589caa80 100644 --- a/__tests__/unit/hooks/usePostComposerClears.test.ts +++ b/__tests__/unit/hooks/usePostComposerClears.test.ts @@ -19,23 +19,23 @@ import { renderHook, act } from '@testing-library/react'; import { usePostComposer } from '@/hooks/usePostComposerNew'; -const submitPost = jest.fn(); -const clearDraft = jest.fn(); +const submitPost = vi.fn(); +const clearDraft = vi.fn(); -jest.mock('@/hooks/useAuth', () => ({ useAuth: () => ({ user: { id: 'u1' } }) })); -jest.mock('@/hooks/usePostDraft', () => ({ +vi.mock('@/hooks/useAuth', () => ({ useAuth: () => ({ user: { id: 'u1' } }) })); +vi.mock('@/hooks/usePostDraft', () => ({ usePostDraft: () => ({ clearDraft: (...a: unknown[]) => clearDraft(...a) }), })); -jest.mock('@/services/timeline/utils/post-composer', () => ({ +vi.mock('@/services/timeline/utils/post-composer', () => ({ submitPost: (...a: unknown[]) => submitPost(...a), formatPostError: (e: Error) => e.message, - queueOfflinePost: jest.fn(), + queueOfflinePost: vi.fn(), fetchUserProjects: async () => [], })); describe('the composer after a successful post', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); submitPost.mockResolvedValue({ success: true, event: { id: 'e1' } }); }); @@ -55,7 +55,7 @@ describe('the composer after a successful post', () => { }); it('still calls the caller onSuccess', async () => { - const onSuccess = jest.fn(); + const onSuccess = vi.fn(); const { result } = renderHook(() => usePostComposer({ onSuccess })); act(() => result.current.setContent('hello')); diff --git a/__tests__/unit/hooks/usePostLikeDislike.test.ts b/__tests__/unit/hooks/usePostLikeDislike.test.ts index 705916e1b..abb9df1eb 100644 --- a/__tests__/unit/hooks/usePostLikeDislike.test.ts +++ b/__tests__/unit/hooks/usePostLikeDislike.test.ts @@ -15,9 +15,9 @@ import { renderHook, act } from '@testing-library/react'; import { usePostLikeDislike } from '@/hooks/usePostLikeDislike'; import type { TimelineDisplayEvent } from '@/types/timeline'; -const toggleLike = jest.fn(); -const toggleDislike = jest.fn(); -jest.mock('@/services/timeline', () => ({ +const toggleLike = vi.fn(); +const toggleDislike = vi.fn(); +vi.mock('@/services/timeline', () => ({ timelineService: { toggleLike: (...a: unknown[]) => toggleLike(...a), toggleDislike: (...a: unknown[]) => toggleDislike(...a), @@ -36,10 +36,10 @@ function eventWith(overrides: Partial): TimelineDisplayEve } describe('liking and disliking are exclusive', () => { - beforeEach(() => jest.clearAllMocks()); + beforeEach(() => vi.clearAllMocks()); it('clears the like when you dislike a post you had liked', async () => { - const onUpdate = jest.fn(); + const onUpdate = vi.fn(); toggleDislike.mockResolvedValue({ success: true, disliked: true, @@ -66,12 +66,17 @@ describe('liking and disliking are exclusive', () => { ); // Server pass: both totals come from the response. expect(onUpdate).toHaveBeenLastCalledWith( - expect.objectContaining({ userDisliked: true, dislikesCount: 1, userLiked: false, likesCount: 0 }) + expect.objectContaining({ + userDisliked: true, + dislikesCount: 1, + userLiked: false, + likesCount: 0, + }) ); }); it('clears the dislike when you like a post you had disliked', async () => { - const onUpdate = jest.fn(); + const onUpdate = vi.fn(); toggleLike.mockResolvedValue({ success: true, liked: true, @@ -98,7 +103,7 @@ describe('liking and disliking are exclusive', () => { }); it('leaves the opposite alone when simply un-liking', async () => { - const onUpdate = jest.fn(); + const onUpdate = vi.fn(); toggleLike.mockResolvedValue({ success: true, liked: false, likeCount: 0, dislikeCount: 0 }); const { result } = renderHook(() => @@ -116,7 +121,7 @@ describe('liking and disliking are exclusive', () => { }); it('restores both sides when the server refuses', async () => { - const onUpdate = jest.fn(); + const onUpdate = vi.fn(); toggleDislike.mockResolvedValue({ success: false, disliked: false, dislikeCount: 0 }); const { result } = renderHook(() => diff --git a/__tests__/unit/hooks/useRequireAuth.test.tsx b/__tests__/unit/hooks/useRequireAuth.test.tsx index cee3fa368..30734ed84 100644 --- a/__tests__/unit/hooks/useRequireAuth.test.tsx +++ b/__tests__/unit/hooks/useRequireAuth.test.tsx @@ -21,15 +21,15 @@ import { renderHook, act } from '@testing-library/react'; import { useRequireAuth } from '@/hooks/useAuthRedirects'; -const replace = jest.fn(); -const push = jest.fn(); -jest.mock('next/navigation', () => ({ +const replace = vi.fn(); +const push = vi.fn(); +vi.mock('next/navigation', () => ({ useRouter: () => ({ replace, push }), usePathname: () => '/timeline', })); let storeState: Record = {}; -jest.mock('@/stores/auth', () => ({ +vi.mock('@/stores/auth', () => ({ useAuthStore: () => storeState, })); @@ -47,11 +47,11 @@ function wedged(overrides: Record = {}) { describe('useRequireAuth hydration ceiling', () => { beforeEach(() => { - jest.clearAllMocks(); - jest.useFakeTimers(); + vi.clearAllMocks(); + vi.useFakeTimers(); }); afterEach(() => { - jest.useRealTimers(); + vi.useRealTimers(); }); it('lets a signed-in user through once the ceiling fires', () => { @@ -63,7 +63,7 @@ describe('useRequireAuth hydration ceiling', () => { expect(result.current.isAuthenticated).toBe(false); act(() => { - jest.advanceTimersByTime(4100); + vi.advanceTimersByTime(4100); }); // After it: the page must be able to render rather than sit on a spinner. @@ -78,7 +78,7 @@ describe('useRequireAuth hydration ceiling', () => { const { result } = renderHook(() => useRequireAuth()); act(() => { - jest.advanceTimersByTime(4100); + vi.advanceTimersByTime(4100); }); // The ceiling widens the exit; it must never invent a session. diff --git a/__tests__/unit/hooks/useThrottledLog.test.ts b/__tests__/unit/hooks/useThrottledLog.test.ts index bab271e8d..1ae2870a2 100644 --- a/__tests__/unit/hooks/useThrottledLog.test.ts +++ b/__tests__/unit/hooks/useThrottledLog.test.ts @@ -30,15 +30,15 @@ function useThrottledLog(logFn: () => void, delay: number = 10000) { describe('useThrottledLog', () => { beforeEach(() => { - jest.useFakeTimers(); + vi.useFakeTimers(); }); afterEach(() => { - jest.useRealTimers(); + vi.useRealTimers(); }); it('returns a stable function reference across re-renders', () => { - const logFn = jest.fn(); + const logFn = vi.fn(); const { result, rerender } = renderHook(() => useThrottledLog(logFn, 1000)); const ref1 = result.current; @@ -47,17 +47,17 @@ describe('useThrottledLog', () => { }); it('returns a stable reference even when logFn changes', () => { - let log = jest.fn(); + let log = vi.fn(); const { result, rerender } = renderHook(() => useThrottledLog(log, 1000)); const ref1 = result.current; - log = jest.fn(); // new function reference + log = vi.fn(); // new function reference rerender(); expect(result.current).toBe(ref1); // still same stable callback }); it('calls the latest logFn when invoked', () => { - const log1 = jest.fn(); + const log1 = vi.fn(); let activeLog = log1; const { result, rerender } = renderHook(() => useThrottledLog(activeLog, 1000)); @@ -66,12 +66,12 @@ describe('useThrottledLog', () => { }); expect(log1).toHaveBeenCalledTimes(1); - const log2 = jest.fn(); + const log2 = vi.fn(); activeLog = log2; rerender(); // Advance past throttle window - jest.advanceTimersByTime(1001); + vi.advanceTimersByTime(1001); act(() => { result.current(); @@ -81,7 +81,7 @@ describe('useThrottledLog', () => { }); it('throttles calls within the delay window', () => { - const logFn = jest.fn(); + const logFn = vi.fn(); const { result } = renderHook(() => useThrottledLog(logFn, 1000)); act(() => { @@ -98,13 +98,13 @@ describe('useThrottledLog', () => { }); it('allows a call after the delay window passes', () => { - const logFn = jest.fn(); + const logFn = vi.fn(); const { result } = renderHook(() => useThrottledLog(logFn, 1000)); act(() => { result.current(); }); // fires - jest.advanceTimersByTime(1001); + vi.advanceTimersByTime(1001); act(() => { result.current(); }); // fires again @@ -113,13 +113,13 @@ describe('useThrottledLog', () => { }); it('does not call logFn before the delay elapses', () => { - const logFn = jest.fn(); + const logFn = vi.fn(); const { result } = renderHook(() => useThrottledLog(logFn, 5000)); act(() => { result.current(); }); // fires - jest.advanceTimersByTime(4999); + vi.advanceTimersByTime(4999); act(() => { result.current(); }); // still throttled diff --git a/__tests__/unit/images/generate.test.ts b/__tests__/unit/images/generate.test.ts index cd4e6f368..f64550c81 100644 --- a/__tests__/unit/images/generate.test.ts +++ b/__tests__/unit/images/generate.test.ts @@ -47,10 +47,10 @@ describe('IMAGE_PROVIDER_RUNTIME', () => { }); describe('generateImageWithKey — images endpoint', () => { - afterEach(() => jest.restoreAllMocks()); + afterEach(() => vi.restoreAllMocks()); it('decodes b64_json and sniffs PNG, omitting response_format for gpt-image models', async () => { - const fetchSpy = jest + const fetchSpy = vi .spyOn(global, 'fetch') .mockResolvedValue(jsonResponse({ data: [{ b64_json: PNG_BYTES.toString('base64') }] })); @@ -74,7 +74,7 @@ describe('generateImageWithKey — images endpoint', () => { }); it('requests b64_json for non-gpt-image models and sniffs JPEG', async () => { - const fetchSpy = jest + const fetchSpy = vi .spyOn(global, 'fetch') .mockResolvedValue(jsonResponse({ data: [{ b64_json: JPEG_BYTES.toString('base64') }] })); @@ -95,9 +95,9 @@ describe('generateImageWithKey — images endpoint', () => { }); it('surfaces the provider error message on failure', async () => { - jest - .spyOn(global, 'fetch') - .mockResolvedValue(jsonResponse({ error: { message: 'billing hard limit reached' } }, 400)); + vi.spyOn(global, 'fetch').mockResolvedValue( + jsonResponse({ error: { message: 'billing hard limit reached' } }, 400) + ); const result = await generateImageWithKey({ apiKey: 'sk-test', @@ -112,11 +112,11 @@ describe('generateImageWithKey — images endpoint', () => { }); describe('generateImageWithKey — chat modalities (OpenRouter)', () => { - afterEach(() => jest.restoreAllMocks()); + afterEach(() => vi.restoreAllMocks()); it('asks for image modality and decodes the data-URI response', async () => { const dataUri = `data:image/png;base64,${PNG_BYTES.toString('base64')}`; - const fetchSpy = jest + const fetchSpy = vi .spyOn(global, 'fetch') .mockResolvedValue( jsonResponse({ choices: [{ message: { images: [{ image_url: { url: dataUri } }] } }] }) @@ -143,9 +143,9 @@ describe('generateImageWithKey — chat modalities (OpenRouter)', () => { }); it('errors when the model answers with text only', async () => { - jest - .spyOn(global, 'fetch') - .mockResolvedValue(jsonResponse({ choices: [{ message: { content: 'I cannot' } }] })); + vi.spyOn(global, 'fetch').mockResolvedValue( + jsonResponse({ choices: [{ message: { content: 'I cannot' } }] }) + ); const result = await generateImageWithKey({ apiKey: 'sk-or-test', diff --git a/__tests__/unit/lib/ai-assist-any-form.test.ts b/__tests__/unit/lib/ai-assist-any-form.test.ts index 31e4a7378..0bb62ef42 100644 --- a/__tests__/unit/lib/ai-assist-any-form.test.ts +++ b/__tests__/unit/lib/ai-assist-any-form.test.ts @@ -191,7 +191,7 @@ describe('generateFormPrefill — retries a transient provider failure', () => { }, ], }; - const fetchMock = jest + const fetchMock = vi .fn() .mockResolvedValueOnce({ ok: false, status: 503, text: async () => 'upstream hiccup' }) .mockResolvedValueOnce({ ok: true, json: async () => okBody }); @@ -208,7 +208,7 @@ describe('generateFormPrefill — retries a transient provider failure', () => { }); it('gives up after repeated failures with the same user-facing message', async () => { - const fetchMock = jest + const fetchMock = vi .fn() .mockResolvedValue({ ok: false, status: 503, text: async () => 'still down' }); global.fetch = fetchMock as unknown as typeof fetch; diff --git a/__tests__/unit/lib/api-owner-filter.test.ts b/__tests__/unit/lib/api-owner-filter.test.ts index 664bffbf0..df2ecadca 100644 --- a/__tests__/unit/lib/api-owner-filter.test.ts +++ b/__tests__/unit/lib/api-owner-filter.test.ts @@ -8,22 +8,22 @@ */ import { resolveOwnerFilter } from '@/lib/api/query'; -jest.mock('@/lib/supabase/server', () => ({ - createServerClient: jest.fn(), +vi.mock('@/lib/supabase/server', () => ({ + createServerClient: vi.fn(), })); import { createServerClient } from '@/lib/supabase/server'; -const mockedCreateServerClient = createServerClient as jest.MockedFunction< - typeof createServerClient ->; +import type { MockedFunction } from 'vitest'; + +const mockedCreateServerClient = createServerClient as MockedFunction; /** Minimal stub of the one query resolveOwnerFilter makes. */ function stubProfileLookup(result: { id: string } | null) { - const maybeSingle = jest.fn().mockResolvedValue({ data: result, error: null }); - const eq = jest.fn(() => ({ maybeSingle })); - const select = jest.fn(() => ({ eq })); - const from = jest.fn(() => ({ select })); + const maybeSingle = vi.fn().mockResolvedValue({ data: result, error: null }); + const eq = vi.fn(() => ({ maybeSingle })); + const select = vi.fn(() => ({ eq })); + const from = vi.fn(() => ({ select })); mockedCreateServerClient.mockResolvedValue({ from } as never); return { from, select, eq, maybeSingle }; } @@ -32,7 +32,7 @@ const URL_BASE = 'https://orangecat.ch/api/projects'; describe('resolveOwnerFilter', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('returns no filter when neither param is present', async () => { diff --git a/__tests__/unit/lib/haptics.test.ts b/__tests__/unit/lib/haptics.test.ts index 90b8eeac6..e73f4ae2c 100644 --- a/__tests__/unit/lib/haptics.test.ts +++ b/__tests__/unit/lib/haptics.test.ts @@ -12,7 +12,7 @@ function mockMatchMedia(reduced: boolean) { Object.defineProperty(window, 'matchMedia', { writable: true, configurable: true, - value: jest.fn().mockReturnValue({ matches: reduced }), + value: vi.fn().mockReturnValue({ matches: reduced }), }); } @@ -26,8 +26,12 @@ afterEach(() => { describe('haptic', () => { it('vibrates for a completed payment', () => { - const vibrate = jest.fn(); - Object.defineProperty(navigator, 'vibrate', { writable: true, configurable: true, value: vibrate }); + const vibrate = vi.fn(); + Object.defineProperty(navigator, 'vibrate', { + writable: true, + configurable: true, + value: vibrate, + }); mockMatchMedia(false); haptic('success'); @@ -37,8 +41,12 @@ describe('haptic', () => { }); it('stays silent when the user prefers reduced motion', () => { - const vibrate = jest.fn(); - Object.defineProperty(navigator, 'vibrate', { writable: true, configurable: true, value: vibrate }); + const vibrate = vi.fn(); + Object.defineProperty(navigator, 'vibrate', { + writable: true, + configurable: true, + value: vibrate, + }); mockMatchMedia(true); haptic('success'); diff --git a/__tests__/unit/lightning-address/lnurl-service.test.ts b/__tests__/unit/lightning-address/lnurl-service.test.ts index 46d7a386a..768070b0a 100644 --- a/__tests__/unit/lightning-address/lnurl-service.test.ts +++ b/__tests__/unit/lightning-address/lnurl-service.test.ts @@ -12,15 +12,17 @@ import { import { resolveUserWallet } from '@/domain/payments/walletResolutionService'; import { getAdminClient } from '@/lib/supabase/admin'; -jest.mock('@/domain/payments/walletResolutionService', () => ({ - resolveUserWallet: jest.fn(), +import type { MockedFunction } from 'vitest'; + +vi.mock('@/domain/payments/walletResolutionService', () => ({ + resolveUserWallet: vi.fn(), })); -jest.mock('@/lib/supabase/admin', () => ({ - getAdminClient: jest.fn(), +vi.mock('@/lib/supabase/admin', () => ({ + getAdminClient: vi.fn(), })); -const mockResolveWallet = resolveUserWallet as jest.MockedFunction; -const mockGetAdmin = getAdminClient as jest.MockedFunction; +const mockResolveWallet = resolveUserWallet as MockedFunction; +const mockGetAdmin = getAdminClient as MockedFunction; /** * Table-aware admin stub. @@ -64,7 +66,7 @@ function adminReturning( } beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe('a handle the profile no longer uses', () => { @@ -115,7 +117,7 @@ describe('a handle the profile no longer uses', () => { const recipient = await resolveLnurlRecipient('butaeff+ocauth2'); expect(recipient?.userId).toBe('user-1'); // Never a query-string filter — that is what mangled it. - expect(stub.calls.some((c) => c.table === 'profile_username_history')).toBe(false); + expect(stub.calls.some(c => c.table === 'profile_username_history')).toBe(false); expect(stub.rpcCalls[0].args).toEqual({ handle: 'butaeff+ocauth2' }); }); @@ -165,7 +167,11 @@ describe('resolveLnurlRecipient', () => { describe('resolveLnurlWallet', () => { it('returns null when the only wallet is on-chain (not a Lightning rail)', async () => { - mockResolveWallet.mockResolvedValue({ method: 'onchain', wallet_id: 'w1', onchain_address: 'bc1x' }); + mockResolveWallet.mockResolvedValue({ + method: 'onchain', + wallet_id: 'w1', + onchain_address: 'bc1x', + }); expect(await resolveLnurlWallet('u1')).toBeNull(); }); diff --git a/__tests__/unit/middleware.auth.test.ts b/__tests__/unit/middleware.auth.test.ts index 06d48d918..d13a8fe3a 100644 --- a/__tests__/unit/middleware.auth.test.ts +++ b/__tests__/unit/middleware.auth.test.ts @@ -15,7 +15,7 @@ const nextResponseNext = () => ({ }, }); -jest.mock('next/server', () => ({ +vi.mock('next/server', () => ({ NextResponse: { next: () => nextResponseNext(), redirect: (url: URL) => ({ @@ -37,7 +37,7 @@ let mockUser: { id: string } | null = null; const setMockUser = (user: { id: string } | null) => { mockUser = user; }; -jest.mock('@supabase/ssr', () => ({ +vi.mock('@supabase/ssr', () => ({ createServerClient: () => ({ auth: { getUser: async () => ({ data: { user: mockUser }, error: null }), @@ -72,7 +72,7 @@ describe('middleware auth protection', () => { const realEnv = process.env; beforeEach(() => { - jest.resetModules(); + vi.resetModules(); process.env = { ...realEnv }; setMockUser(null); }); diff --git a/__tests__/unit/offline/offline-queue-events.test.ts b/__tests__/unit/offline/offline-queue-events.test.ts index 4671a4bb5..373a40048 100644 --- a/__tests__/unit/offline/offline-queue-events.test.ts +++ b/__tests__/unit/offline/offline-queue-events.test.ts @@ -1,10 +1,10 @@ -/** @jest-environment jsdom */ +/** @vitest-environment jsdom */ import { queueUpdated } from '@/lib/offline-queue-events'; describe('offline-queue-events', () => { test('dispatches updated event (including legacy back-compat)', () => { - const updatedSpy = jest.fn(); - const legacySpy = jest.fn(); + const updatedSpy = vi.fn(); + const legacySpy = vi.fn(); window.addEventListener('offline-queue:updated', updatedSpy as EventListener); window.addEventListener('offline-queue-updated', legacySpy as EventListener); diff --git a/__tests__/unit/payments/incomplete-settlement.test.ts b/__tests__/unit/payments/incomplete-settlement.test.ts index 4feb9c15f..bafb45618 100644 --- a/__tests__/unit/payments/incomplete-settlement.test.ts +++ b/__tests__/unit/payments/incomplete-settlement.test.ts @@ -19,41 +19,43 @@ import { findIncompleteSettlements } from '@/services/payments/reconcile'; import { STATUS } from '@/config/database-constants'; -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn() }, })); import { logger } from '@/utils/logger'; +import type { Mock } from 'vitest'; + /** Records the filters applied, so the predicate itself can be asserted. */ function makeAdmin(result: { data: unknown; error: unknown }) { const calls: Record = {}; const chain = { - select: jest.fn().mockReturnThis(), - eq: jest.fn((col: string, val: unknown) => { + select: vi.fn().mockReturnThis(), + eq: vi.fn((col: string, val: unknown) => { calls[`eq:${col}`] = val; return chain; }), - is: jest.fn((col: string, val: unknown) => { + is: vi.fn((col: string, val: unknown) => { calls[`is:${col}`] = val; return chain; }), - lt: jest.fn((col: string, val: unknown) => { + lt: vi.fn((col: string, val: unknown) => { calls[`lt:${col}`] = val; return chain; }), - order: jest.fn().mockReturnThis(), - limit: jest.fn().mockResolvedValue(result), + order: vi.fn().mockReturnThis(), + limit: vi.fn().mockResolvedValue(result), }; return { - admin: { from: jest.fn(() => chain) } as never, + admin: { from: vi.fn(() => chain) } as never, calls, chain, }; } describe('findIncompleteSettlements', () => { - beforeEach(() => jest.clearAllMocks()); + beforeEach(() => vi.clearAllMocks()); it('asks for paid intents with no side-effects marker', async () => { const { admin, calls } = makeAdmin({ data: [], error: null }); @@ -86,7 +88,7 @@ describe('findIncompleteSettlements', () => { expect(result.ids).toEqual(['pi-1', 'pi-2']); // error, not warn: a buyer paid and their order never moved. expect(logger.error).toHaveBeenCalledTimes(1); - const [, payload] = (logger.error as jest.Mock).mock.calls[0]; + const [, payload] = (logger.error as Mock).mock.calls[0]; expect(payload.paymentIntentIds).toEqual(['pi-1', 'pi-2']); }); @@ -109,6 +111,6 @@ describe('findIncompleteSettlements', () => { await findIncompleteSettlements(admin); expect(chain).not.toHaveProperty('update'); - expect((chain.select as jest.Mock).mock.calls[0][0]).toBe('id'); + expect((chain.select as Mock).mock.calls[0][0]).toBe('id'); }); }); diff --git a/__tests__/unit/payments/l402-verify.test.ts b/__tests__/unit/payments/l402-verify.test.ts index d49a88958..e70c12ba8 100644 --- a/__tests__/unit/payments/l402-verify.test.ts +++ b/__tests__/unit/payments/l402-verify.test.ts @@ -13,23 +13,23 @@ import { createHash, randomBytes } from 'crypto'; import { STATUS } from '@/config/database-constants'; -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -const mockMaybeSingle = jest.fn(); -const queryChain: Record = {}; -queryChain.select = jest.fn(() => queryChain); -queryChain.eq = jest.fn(() => queryChain); +const mockMaybeSingle = vi.fn(); +const queryChain: Record = {}; +queryChain.select = vi.fn(() => queryChain); +queryChain.eq = vi.fn(() => queryChain); queryChain.maybeSingle = mockMaybeSingle; -jest.mock('@/lib/supabase/admin', () => ({ +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: () => ({ from: () => queryChain }), })); -const mockCheckStatus = jest.fn(); -const mockSettle = jest.fn(); -jest.mock('@/domain/payments/paymentFlowService', () => ({ - initiatePublicSupport: jest.fn(), +const mockCheckStatus = vi.fn(); +const mockSettle = vi.fn(); +vi.mock('@/domain/payments/paymentFlowService', () => ({ + initiatePublicSupport: vi.fn(), checkPublicPaymentStatus: (...args: unknown[]) => mockCheckStatus(...args), hashPublicStatusToken: (t: string) => `hashed:${t}`, settleVerifiedPayment: (...args: unknown[]) => mockSettle(...args), @@ -37,6 +37,8 @@ jest.mock('@/domain/payments/paymentFlowService', () => ({ import { verifyL402Payment } from '@/domain/payments/l402'; +import type { Mock } from 'vitest'; + const ENTITY_ID = '11111111-2222-3333-4444-555555555555'; const OTHER_ENTITY_ID = '99999999-8888-7777-6666-555555555555'; @@ -103,10 +105,7 @@ describe('verifyL402Payment — preimage branch settles', () => { it('falls back to settlement status on a wrong preimage', async () => { mockMaybeSingle.mockResolvedValue({ data: intentRow() }); mockCheckStatus.mockResolvedValue({ status: 'invoice_ready', paid_at: null }); - const result = await verifyL402Payment( - { ...creds, preimage: 'f'.repeat(64) }, - expected - ); + const result = await verifyL402Payment({ ...creds, preimage: 'f'.repeat(64) }, expected); expect(mockSettle).not.toHaveBeenCalled(); expect(result.ok).toBe(false); expect(result.verified_by).toBeUndefined(); diff --git a/__tests__/unit/profile/retired-handle-not-available.test.ts b/__tests__/unit/profile/retired-handle-not-available.test.ts index f8766aa4e..5f946f8e4 100644 --- a/__tests__/unit/profile/retired-handle-not-available.test.ts +++ b/__tests__/unit/profile/retired-handle-not-available.test.ts @@ -17,14 +17,16 @@ import { ProfileServerService } from '@/services/profile/server'; import { resolveHistoricalUsername } from '@/domain/lightning-address/username-history'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/domain/lightning-address/username-history', () => ({ - resolveHistoricalUsername: jest.fn(), +vi.mock('@/domain/lightning-address/username-history', () => ({ + resolveHistoricalUsername: vi.fn(), })); -const resolveHistoricalUsernameMock = resolveHistoricalUsername as jest.Mock; +const resolveHistoricalUsernameMock = resolveHistoricalUsername as Mock; const OWNER = 'cec88bc9-0000-0000-0000-000000000001'; const SOMEONE_ELSE = 'cec88bc9-0000-0000-0000-000000000002'; @@ -43,7 +45,7 @@ function makeSupabase() { } describe('checkUsernameAvailability', () => { - beforeEach(() => jest.clearAllMocks()); + beforeEach(() => vi.clearAllMocks()); it('refuses a handle another account retired', async () => { resolveHistoricalUsernameMock.mockResolvedValue(SOMEONE_ELSE); diff --git a/__tests__/unit/public-surface-filtering.test.ts b/__tests__/unit/public-surface-filtering.test.ts index 594e39960..608367caf 100644 --- a/__tests__/unit/public-surface-filtering.test.ts +++ b/__tests__/unit/public-surface-filtering.test.ts @@ -16,15 +16,15 @@ import { DATABASE_TABLES } from '@/config/database-tables'; import { getTableName } from '@/config/entity-registry'; import { STATUS, ENTITY_STATUS } from '@/config/database-constants'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); // Force searchPlatform onto its keyword path — the semantic path's guard lives // in SQL (match_content), which unit tests can't inspect. -jest.mock('@/services/ai/embeddings', () => ({ +vi.mock('@/services/ai/embeddings', () => ({ embeddingsEnabled: () => false, - embedText: jest.fn(), + embedText: vi.fn(), })); type Call = { method: string; args: unknown[] }; @@ -64,7 +64,7 @@ function recordingClient() { Promise.resolve({ data: [], count: 0, error: null }).then(resolve); return chain; }, - rpc: jest.fn(() => Promise.resolve({ data: [], error: null })), + rpc: vi.fn(() => Promise.resolve({ data: [], error: null })), }; return { client: client as never, queries }; } diff --git a/__tests__/unit/services/ai/assistant-charge.test.ts b/__tests__/unit/services/ai/assistant-charge.test.ts index f1e7f32cc..15c07823b 100644 --- a/__tests__/unit/services/ai/assistant-charge.test.ts +++ b/__tests__/unit/services/ai/assistant-charge.test.ts @@ -18,20 +18,20 @@ import { settleAssistantCharge, } from '@/services/ai/assistant-charge'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -const appendCreditEntry = jest.fn(); -const getCreditBalance = jest.fn(); -jest.mock('@/services/cat/credits', () => ({ +const appendCreditEntry = vi.fn(); +const getCreditBalance = vi.fn(); +vi.mock('@/services/cat/credits', () => ({ appendCreditEntry: (...a: unknown[]) => appendCreditEntry(...a), getCreditBalance: (...a: unknown[]) => getCreditBalance(...a), })); // bumpAssistantRevenue reads then updates a counter row; a chainable stub is enough. const revenueRow = { total_revenue: 0 }; -jest.mock('@/lib/supabase/untyped', () => ({ +vi.mock('@/lib/supabase/untyped', () => ({ fromTable: () => ({ select: () => ({ eq: () => ({ single: async () => ({ data: revenueRow }) }) }), update: () => ({ eq: async () => ({ data: null, error: null }) }), @@ -41,7 +41,7 @@ jest.mock('@/lib/supabase/untyped', () => ({ const admin = {} as never; beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); revenueRow.total_revenue = 0; }); diff --git a/__tests__/unit/services/ai/openrouter.test.ts b/__tests__/unit/services/ai/openrouter.test.ts index 2b49fa684..dcb7d8278 100644 --- a/__tests__/unit/services/ai/openrouter.test.ts +++ b/__tests__/unit/services/ai/openrouter.test.ts @@ -7,6 +7,8 @@ import { TextDecoder as NodeTextDecoder } from 'util'; import { OpenRouterService } from '@/services/ai/openrouter'; import { calculateCostBtc } from '@/config/ai-models'; +import type { MockInstance } from 'vitest'; + // @ts-expect-error Jest/node lacks Web TextDecoder global.TextDecoder = NodeTextDecoder; @@ -45,10 +47,10 @@ function completionBody(usage: Record) { } describe('OpenRouterService chatCompletion cost', () => { - let fetchSpy: jest.SpyInstance; + let fetchSpy: MockInstance; beforeEach(() => { - fetchSpy = jest.spyOn(global, 'fetch'); + fetchSpy = vi.spyOn(global, 'fetch'); }); afterEach(() => { @@ -124,10 +126,10 @@ describe('OpenRouterService chatCompletion cost', () => { }); describe('OpenRouterService streamChatCompletion cost', () => { - let fetchSpy: jest.SpyInstance; + let fetchSpy: MockInstance; beforeEach(() => { - fetchSpy = jest.spyOn(global, 'fetch'); + fetchSpy = vi.spyOn(global, 'fetch'); }); afterEach(() => { @@ -162,10 +164,10 @@ describe('OpenRouterService streamChatCompletion cost', () => { }); describe('OpenRouterService sampling-param gating', () => { - let fetchSpy: jest.SpyInstance; + let fetchSpy: MockInstance; beforeEach(() => { - fetchSpy = jest.spyOn(global, 'fetch'); + fetchSpy = vi.spyOn(global, 'fetch'); }); afterEach(() => { diff --git a/__tests__/unit/services/bookings.notifications.test.ts b/__tests__/unit/services/bookings.notifications.test.ts index 5b9e7ade5..7471bd9fc 100644 --- a/__tests__/unit/services/bookings.notifications.test.ts +++ b/__tests__/unit/services/bookings.notifications.test.ts @@ -10,11 +10,13 @@ import { createBookingService } from '@/services/bookings'; import { NotificationDispatcher } from '@/services/notifications/dispatcher'; -jest.mock('@/services/notifications/dispatcher', () => ({ - NotificationDispatcher: { dispatch: jest.fn().mockResolvedValue(undefined) }, +import type { Mock } from 'vitest'; + +vi.mock('@/services/notifications/dispatcher', () => ({ + NotificationDispatcher: { dispatch: vi.fn().mockResolvedValue(undefined) }, })); -const dispatchMock = NotificationDispatcher.dispatch as jest.Mock; +const dispatchMock = NotificationDispatcher.dispatch as Mock; const BOOKING = { id: 'booking-1', @@ -32,32 +34,32 @@ const BOOKING = { * booking row; the actors select→eq→single resolves the provider's user_id. */ function makeSupabaseStub(opts: { bookingRow: unknown; bookingError?: { message: string } }) { - const single = jest.fn().mockResolvedValue({ + const single = vi.fn().mockResolvedValue({ data: opts.bookingError ? null : opts.bookingRow, error: opts.bookingError ?? null, }); - const actorSingle = jest + const actorSingle = vi .fn() .mockResolvedValue({ data: { user_id: 'provider-user' }, error: null }); - const chain: Record = {}; + const chain: Record = {}; for (const method of ['update', 'eq', 'in', 'select']) { - chain[method] = jest.fn(() => chain); + chain[method] = vi.fn(() => chain); } chain.single = single; - const actorChain: Record = {}; + const actorChain: Record = {}; for (const method of ['select', 'eq']) { - actorChain[method] = jest.fn(() => actorChain); + actorChain[method] = vi.fn(() => actorChain); } actorChain.single = actorSingle; return { - from: jest.fn((table: string) => (table === 'actors' ? actorChain : chain)), + from: vi.fn((table: string) => (table === 'actors' ? actorChain : chain)), } as never; } -afterEach(() => jest.clearAllMocks()); +afterEach(() => vi.clearAllMocks()); describe('booking status-change notifications', () => { it('confirmBooking notifies the customer', async () => { diff --git a/__tests__/unit/services/cat-account.test.ts b/__tests__/unit/services/cat-account.test.ts index bcba5c3a0..455a64cf0 100644 --- a/__tests__/unit/services/cat-account.test.ts +++ b/__tests__/unit/services/cat-account.test.ts @@ -34,9 +34,9 @@ function adminWith({ profileAfterCreate?: Row; updateError?: { message: string }; }) { - const createUser = jest.fn().mockResolvedValue({ error: createError ?? null }); - const update = jest.fn(() => ({ - eq: jest.fn().mockResolvedValue({ error: updateError ?? null }), + const createUser = vi.fn().mockResolvedValue({ error: createError ?? null }); + const update = vi.fn(() => ({ + eq: vi.fn().mockResolvedValue({ error: updateError ?? null }), })); let lookups = 0; const lookupColumns: string[] = []; diff --git a/__tests__/unit/services/cat-mention-queue.test.ts b/__tests__/unit/services/cat-mention-queue.test.ts index 20599cd86..c11527fa2 100644 --- a/__tests__/unit/services/cat-mention-queue.test.ts +++ b/__tests__/unit/services/cat-mention-queue.test.ts @@ -13,9 +13,9 @@ import { enqueueMention, failMention, MAX_ATTEMPTS } from '@/services/mentions/q import { noteCatMention } from '@/services/mentions/note-mention'; function adminSpy(opts: { insertError?: { code?: string; message: string } } = {}) { - const insert = jest.fn().mockResolvedValue({ error: opts.insertError ?? null }); - const eq = jest.fn().mockResolvedValue({ error: null }); - const update = jest.fn(() => ({ eq })); + const insert = vi.fn().mockResolvedValue({ error: opts.insertError ?? null }); + const eq = vi.fn().mockResolvedValue({ error: null }); + const update = vi.fn(() => ({ eq })); const admin = { from: () => ({ insert, update }) }; return { admin: admin as never, insert, update }; } @@ -23,9 +23,14 @@ function adminSpy(opts: { insertError?: { code?: string; message: string } } = { describe('enqueueMention', () => { it('records the debt', async () => { const { admin, insert } = adminSpy(); - await expect(enqueueMention(admin, { - sourceType: 'message', sourceId: 'm1', requesterId: 'u1', conversationId: 'c1', - })).resolves.toBe(true); + await expect( + enqueueMention(admin, { + sourceType: 'message', + sourceId: 'm1', + requesterId: 'u1', + conversationId: 'c1', + }) + ).resolves.toBe(true); expect(insert).toHaveBeenCalledWith(expect.objectContaining({ source_id: 'm1' })); }); @@ -33,16 +38,26 @@ describe('enqueueMention', () => { // 23505 = unique violation. An at-least-once producer firing twice must not // look like a failure, or the caller retries forever. const { admin } = adminSpy({ insertError: { code: '23505', message: 'duplicate key' } }); - await expect(enqueueMention(admin, { - sourceType: 'message', sourceId: 'm1', requesterId: 'u1', conversationId: 'c1', - })).resolves.toBe(true); + await expect( + enqueueMention(admin, { + sourceType: 'message', + sourceId: 'm1', + requesterId: 'u1', + conversationId: 'c1', + }) + ).resolves.toBe(true); }); it('reports a real failure as a failure', async () => { const { admin } = adminSpy({ insertError: { code: '42P01', message: 'no such table' } }); - await expect(enqueueMention(admin, { - sourceType: 'message', sourceId: 'm1', requesterId: 'u1', conversationId: 'c1', - })).resolves.toBe(false); + await expect( + enqueueMention(admin, { + sourceType: 'message', + sourceId: 'm1', + requesterId: 'u1', + conversationId: 'c1', + }) + ).resolves.toBe(false); }); }); @@ -65,7 +80,7 @@ describe('failMention', () => { describe('noteCatMention', () => { /** Resolver + profile lookup + insert, in the shape the service chains them. */ function admin({ username = 'alice', mentionsCat = true } = {}) { - const insert = jest.fn().mockResolvedValue({ error: null }); + const insert = vi.fn().mockResolvedValue({ error: null }); return { insert, client: { @@ -82,7 +97,9 @@ describe('noteCatMention', () => { error: null, }), }), - eq: () => ({ maybeSingle: () => Promise.resolve({ data: { username }, error: null }) }), + eq: () => ({ + maybeSingle: () => Promise.resolve({ data: { username }, error: null }), + }), }), }; }, @@ -93,7 +110,10 @@ describe('noteCatMention', () => { it('queues a reply keyed on the MESSAGE, so a second question is also answered', async () => { const { client, insert } = admin(); await noteCatMention(client, { - conversationId: 'c1', messageId: 'm2', senderId: 'u1', content: '@cat and this?', + conversationId: 'c1', + messageId: 'm2', + senderId: 'u1', + content: '@cat and this?', }); // Keyed on the conversation, this row would collide with the first question // ever asked in c1 and be silently dropped. @@ -103,7 +123,10 @@ describe('noteCatMention', () => { it('skips messages with no @ at all without touching the database', async () => { const { client, insert } = admin(); const noted = await noteCatMention(client, { - conversationId: 'c1', messageId: 'm1', senderId: 'u1', content: 'just talking', + conversationId: 'c1', + messageId: 'm1', + senderId: 'u1', + content: 'just talking', }); expect(noted).toBe(false); expect(insert).not.toHaveBeenCalled(); @@ -114,7 +137,10 @@ describe('noteCatMention', () => { // another reply, forever. const { client, insert } = admin({ username: 'cat' }); const noted = await noteCatMention(client, { - conversationId: 'c1', messageId: 'm1', senderId: 'cat-id', content: 'as @cat I think', + conversationId: 'c1', + messageId: 'm1', + senderId: 'cat-id', + content: 'as @cat I think', }); expect(noted).toBe(false); expect(insert).not.toHaveBeenCalled(); @@ -123,17 +149,27 @@ describe('noteCatMention', () => { it('ignores a message that mentions someone else', async () => { const { client, insert } = admin({ mentionsCat: false }); const noted = await noteCatMention(client, { - conversationId: 'c1', messageId: 'm1', senderId: 'u1', content: 'hey @alice', + conversationId: 'c1', + messageId: 'm1', + senderId: 'u1', + content: 'hey @alice', }); expect(noted).toBe(false); expect(insert).not.toHaveBeenCalled(); }); it('never throws — a person’s message must be stored whatever the Cat does', async () => { - const exploding = { from: () => { throw new Error('db down'); } } as never; + const exploding = { + from: () => { + throw new Error('db down'); + }, + } as never; await expect( noteCatMention(exploding, { - conversationId: 'c1', messageId: 'm1', senderId: 'u1', content: '@cat hi', + conversationId: 'c1', + messageId: 'm1', + senderId: 'u1', + content: '@cat hi', }) ).resolves.toBe(false); }); diff --git a/__tests__/unit/services/cat-post-mentions.test.ts b/__tests__/unit/services/cat-post-mentions.test.ts index 4b788da8c..886530f7b 100644 --- a/__tests__/unit/services/cat-post-mentions.test.ts +++ b/__tests__/unit/services/cat-post-mentions.test.ts @@ -10,29 +10,29 @@ * exactly the kind of duplication that drifts silently. */ -const replyToPostMention = jest.fn().mockResolvedValue(true); -const resolveMentions = jest.fn(); -const notifyMentionedPeople = jest.fn().mockResolvedValue(0); -const claimMentions = jest.fn(); -const completeMention = jest.fn(); -const failMention = jest.fn(); +const replyToPostMention = vi.fn().mockResolvedValue(true); +const resolveMentions = vi.fn(); +const notifyMentionedPeople = vi.fn().mockResolvedValue(0); +const claimMentions = vi.fn(); +const completeMention = vi.fn(); +const failMention = vi.fn(); -jest.mock('@/services/mentions/cat-account', () => ({ - ensureCatAccount: jest.fn().mockResolvedValue({ id: 'cat-1', username: 'cat' }), +vi.mock('@/services/mentions/cat-account', () => ({ + ensureCatAccount: vi.fn().mockResolvedValue({ id: 'cat-1', username: 'cat' }), })); -jest.mock('@/services/mentions/cat-post-reply', () => ({ +vi.mock('@/services/mentions/cat-post-reply', () => ({ replyToPostMention: (...a: unknown[]) => replyToPostMention(...a), })); -jest.mock('@/services/mentions/cat-reply', () => ({ - replyToConversationMention: jest.fn().mockResolvedValue(true), +vi.mock('@/services/mentions/cat-reply', () => ({ + replyToConversationMention: vi.fn().mockResolvedValue(true), })); -jest.mock('@/services/mentions/resolve', () => ({ +vi.mock('@/services/mentions/resolve', () => ({ resolveMentions: (...a: unknown[]) => resolveMentions(...a), })); -jest.mock('@/services/mentions/notify-mentions', () => ({ +vi.mock('@/services/mentions/notify-mentions', () => ({ notifyMentionedPeople: (...a: unknown[]) => notifyMentionedPeople(...a), })); -jest.mock('@/services/mentions/queue', () => ({ +vi.mock('@/services/mentions/queue', () => ({ claimMentions: (...a: unknown[]) => claimMentions(...a), completeMention: (...a: unknown[]) => completeMention(...a), failMention: (...a: unknown[]) => failMention(...a), diff --git a/__tests__/unit/services/cat-worker-bootstrap.test.ts b/__tests__/unit/services/cat-worker-bootstrap.test.ts index 0260c7ad3..37f970b0e 100644 --- a/__tests__/unit/services/cat-worker-bootstrap.test.ts +++ b/__tests__/unit/services/cat-worker-bootstrap.test.ts @@ -13,20 +13,20 @@ * from being "tidied up" later. */ -const ensureCatAccount = jest.fn(); -const claimMentions = jest.fn(); +const ensureCatAccount = vi.fn(); +const claimMentions = vi.fn(); -jest.mock('@/services/mentions/cat-account', () => ({ +vi.mock('@/services/mentions/cat-account', () => ({ ensureCatAccount: (...a: unknown[]) => ensureCatAccount(...a), })); -jest.mock('@/services/mentions/queue', () => ({ +vi.mock('@/services/mentions/queue', () => ({ claimMentions: (...a: unknown[]) => claimMentions(...a), - completeMention: jest.fn(), - failMention: jest.fn(), + completeMention: vi.fn(), + failMention: vi.fn(), MAX_ATTEMPTS: 3, })); -jest.mock('@/services/mentions/cat-reply', () => ({ - replyToConversationMention: jest.fn().mockResolvedValue(true), +vi.mock('@/services/mentions/cat-reply', () => ({ + replyToConversationMention: vi.fn().mockResolvedValue(true), })); import { runCatMentions } from '@/services/mentions/worker'; @@ -69,7 +69,15 @@ describe('the mention worker bootstraps the Cat', () => { it('answers a claimed mention once the account exists', async () => { claimMentions.mockResolvedValue([ - { id: 'q1', source_type: 'message', source_id: 'm1', requester_id: 'u1', conversation_id: 'c1', parent_event_id: null, attempts: 1 }, + { + id: 'q1', + source_type: 'message', + source_id: 'm1', + requester_id: 'u1', + conversation_id: 'c1', + parent_event_id: null, + attempts: 1, + }, ]); await expect(runCatMentions({} as never)).resolves.toMatchObject({ claimed: 1, answered: 1 }); }); @@ -77,7 +85,15 @@ describe('the mention worker bootstraps the Cat', () => { it('fails claimed mentions rather than speaking as nobody', async () => { ensureCatAccount.mockResolvedValue(null); claimMentions.mockResolvedValue([ - { id: 'q1', source_type: 'message', source_id: 'm1', requester_id: 'u1', conversation_id: 'c1', parent_event_id: null, attempts: 1 }, + { + id: 'q1', + source_type: 'message', + source_id: 'm1', + requester_id: 'u1', + conversation_id: 'c1', + parent_event_id: null, + attempts: 1, + }, ]); await expect(runCatMentions({} as never)).resolves.toMatchObject({ failed: 1, answered: 0 }); }); diff --git a/__tests__/unit/services/cat/credit-topup.test.ts b/__tests__/unit/services/cat/credit-topup.test.ts index 110919579..e369c2681 100644 --- a/__tests__/unit/services/cat/credit-topup.test.ts +++ b/__tests__/unit/services/cat/credit-topup.test.ts @@ -21,26 +21,26 @@ import { getResumableTopUp, } from '@/services/cat/credit-topup'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -const platformReceiveEnabled = jest.fn(); -const getPlatformNwcClient = jest.fn(); -jest.mock('@/lib/bitcoin/platform-wallet', () => ({ +const platformReceiveEnabled = vi.fn(); +const getPlatformNwcClient = vi.fn(); +vi.mock('@/lib/bitcoin/platform-wallet', () => ({ platformReceiveEnabled: () => platformReceiveEnabled(), getPlatformNwcClient: () => getPlatformNwcClient(), })); -const appendCreditEntry = jest.fn(); -const getCreditBalance = jest.fn(); -jest.mock('@/services/cat/credits', () => ({ +const appendCreditEntry = vi.fn(); +const getCreditBalance = vi.fn(); +vi.mock('@/services/cat/credits', () => ({ appendCreditEntry: (...a: unknown[]) => appendCreditEntry(...a), getCreditBalance: (...a: unknown[]) => getCreditBalance(...a), })); -const adminFrom = jest.fn(); -jest.mock('@/lib/supabase/admin', () => ({ +const adminFrom = vi.fn(); +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: () => ({ from: (...a: unknown[]) => adminFrom(...a) }), })); @@ -88,15 +88,15 @@ function qb( function nwcClient(over: Record = {}) { return { - makeInvoice: jest.fn().mockResolvedValue({ invoice: 'lnbc1...', payment_hash: 'ph_abc' }), - lookupInvoice: jest.fn().mockResolvedValue({ settled_at: null }), - disconnect: jest.fn(), + makeInvoice: vi.fn().mockResolvedValue({ invoice: 'lnbc1...', payment_hash: 'ph_abc' }), + lookupInvoice: vi.fn().mockResolvedValue({ settled_at: null }), + disconnect: vi.fn(), ...over, }; } beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); qbCalls.length = 0; platformReceiveEnabled.mockReturnValue(true); }); @@ -230,7 +230,7 @@ describe('checkTopUp', () => { it('credits the OWNER (idempotent on payment_hash) when the invoice has settled', async () => { adminFrom.mockReturnValue(qb({ terminal: { data: pendingRow } })); getPlatformNwcClient.mockResolvedValue( - nwcClient({ lookupInvoice: jest.fn().mockResolvedValue({ settled_at: 1_700_000_000 }) }) + nwcClient({ lookupInvoice: vi.fn().mockResolvedValue({ settled_at: 1_700_000_000 }) }) ); // The new balance comes straight from the atomic append (no extra read). appendCreditEntry.mockResolvedValue(0.0005); @@ -269,7 +269,7 @@ describe('checkTopUp', () => { then: (resolve: (v: unknown) => unknown) => resolve({ data: null, error: null }), })); getPlatformNwcClient.mockResolvedValue( - nwcClient({ lookupInvoice: jest.fn().mockResolvedValue({ settled_at: 1_700_000_000 }) }) + nwcClient({ lookupInvoice: vi.fn().mockResolvedValue({ settled_at: 1_700_000_000 }) }) ); appendCreditEntry.mockResolvedValue(null); // crediting failed @@ -281,7 +281,7 @@ describe('checkTopUp', () => { it('stays pending on a transient lookup failure (client polls again)', async () => { adminFrom.mockReturnValue(qb({ terminal: { data: pendingRow } })); getPlatformNwcClient.mockResolvedValue( - nwcClient({ lookupInvoice: jest.fn().mockRejectedValue(new Error('relay timeout')) }) + nwcClient({ lookupInvoice: vi.fn().mockRejectedValue(new Error('relay timeout')) }) ); await expect(checkTopUp('owner', 'tp1')).resolves.toEqual({ status: 'pending' }); expect(appendCreditEntry).not.toHaveBeenCalled(); diff --git a/__tests__/unit/services/cat/credits.test.ts b/__tests__/unit/services/cat/credits.test.ts index 754c6f7de..a2c3f44af 100644 --- a/__tests__/unit/services/cat/credits.test.ts +++ b/__tests__/unit/services/cat/credits.test.ts @@ -10,14 +10,14 @@ import { getCreditBalance, appendCreditEntry } from '@/services/cat/credits'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -const rpc = jest.fn(); +const rpc = vi.fn(); const supabase = { rpc: (...a: unknown[]) => rpc(...a) } as never; -beforeEach(() => jest.clearAllMocks()); +beforeEach(() => vi.clearAllMocks()); describe('getCreditBalance', () => { it('reads the balance via cat_credit_balance', async () => { diff --git a/__tests__/unit/services/cat/platform-feedback.test.ts b/__tests__/unit/services/cat/platform-feedback.test.ts index e54163d93..b71e5562a 100644 --- a/__tests__/unit/services/cat/platform-feedback.test.ts +++ b/__tests__/unit/services/cat/platform-feedback.test.ts @@ -12,16 +12,18 @@ import { answerAndRecordFeedback } from '@/services/cat/platform-feedback'; import { callPlatformJson } from '@/services/cat/platform-llm'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -jest.mock('@/services/cat/platform-llm', () => { - const actual = jest.requireActual('@/services/cat/platform-llm'); - return { ...actual, callPlatformJson: jest.fn() }; +vi.mock('@/services/cat/platform-llm', async () => { + const actual = await vi.importActual('@/services/cat/platform-llm'); + return { ...actual, callPlatformJson: vi.fn() }; }); -const mockCall = callPlatformJson as jest.Mock; +const mockCall = callPlatformJson as Mock; interface RecallRow { message: string; diff --git a/__tests__/unit/services/cat/topup-reconcile.test.ts b/__tests__/unit/services/cat/topup-reconcile.test.ts index 67f8ad6e8..4dd717974 100644 --- a/__tests__/unit/services/cat/topup-reconcile.test.ts +++ b/__tests__/unit/services/cat/topup-reconcile.test.ts @@ -18,26 +18,26 @@ import { runTopUpReconcileSweep } from '@/services/cat/topup-reconcile'; import { TOPUP_EXPIRY_GRACE_MS } from '@/services/cat/credit-topup'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -const platformReceiveEnabled = jest.fn(); -const getPlatformNwcClient = jest.fn(); -jest.mock('@/lib/bitcoin/platform-wallet', () => ({ +const platformReceiveEnabled = vi.fn(); +const getPlatformNwcClient = vi.fn(); +vi.mock('@/lib/bitcoin/platform-wallet', () => ({ platformReceiveEnabled: () => platformReceiveEnabled(), getPlatformNwcClient: () => getPlatformNwcClient(), })); -const appendCreditEntry = jest.fn(); -const getCreditBalance = jest.fn(); -jest.mock('@/services/cat/credits', () => ({ +const appendCreditEntry = vi.fn(); +const getCreditBalance = vi.fn(); +vi.mock('@/services/cat/credits', () => ({ appendCreditEntry: (...a: unknown[]) => appendCreditEntry(...a), getCreditBalance: (...a: unknown[]) => getCreditBalance(...a), })); -const adminFrom = jest.fn(); -jest.mock('@/lib/supabase/admin', () => ({ +const adminFrom = vi.fn(); +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: () => ({ from: (...a: unknown[]) => adminFrom(...a) }), })); @@ -75,8 +75,8 @@ function row(over: Partial> = {}) { function nwcClient(over: Record = {}) { return { - lookupInvoice: jest.fn().mockResolvedValue({ settled_at: null }), - disconnect: jest.fn(), + lookupInvoice: vi.fn().mockResolvedValue({ settled_at: null }), + disconnect: vi.fn(), ...over, }; } @@ -87,7 +87,7 @@ function withRows(rows: unknown[]) { } beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); updates.length = 0; platformReceiveEnabled.mockReturnValue(true); appendCreditEntry.mockResolvedValue(0.0001); @@ -108,7 +108,7 @@ describe('runTopUpReconcileSweep', () => { it('credits a settled top-up nobody was watching, to the row OWNER', async () => { withRows([row()]); const client = nwcClient({ - lookupInvoice: jest.fn().mockResolvedValue({ settled_at: 1_700_000_000 }), + lookupInvoice: vi.fn().mockResolvedValue({ settled_at: 1_700_000_000 }), }); getPlatformNwcClient.mockResolvedValue(client); @@ -128,7 +128,7 @@ describe('runTopUpReconcileSweep', () => { withRows([row()]); appendCreditEntry.mockResolvedValue(null); getPlatformNwcClient.mockResolvedValue( - nwcClient({ lookupInvoice: jest.fn().mockResolvedValue({ settled_at: 1_700_000_000 }) }) + nwcClient({ lookupInvoice: vi.fn().mockResolvedValue({ settled_at: 1_700_000_000 }) }) ); const result = await runTopUpReconcileSweep(); @@ -175,7 +175,7 @@ describe('runTopUpReconcileSweep', () => { it('still checks a settled invoice that is past its window — payment wins over expiry', async () => { withRows([row({ expires_at: new Date(Date.now() - HOUR).toISOString() })]); getPlatformNwcClient.mockResolvedValue( - nwcClient({ lookupInvoice: jest.fn().mockResolvedValue({ settled_at: 1_700_000_000 }) }) + nwcClient({ lookupInvoice: vi.fn().mockResolvedValue({ settled_at: 1_700_000_000 }) }) ); const result = await runTopUpReconcileSweep(); @@ -186,7 +186,7 @@ describe('runTopUpReconcileSweep', () => { it('one failing row does not abort the sweep', async () => { withRows([row({ id: 'tu_bad' }), row({ id: 'tu_good', payment_hash: 'ph_2' })]); - const lookupInvoice = jest + const lookupInvoice = vi .fn() .mockRejectedValueOnce(new Error('relay down')) .mockResolvedValueOnce({ settled_at: 1_700_000_000 }); diff --git a/__tests__/unit/services/cat/track-record.test.ts b/__tests__/unit/services/cat/track-record.test.ts index ecc6b5b9a..68b245d86 100644 --- a/__tests__/unit/services/cat/track-record.test.ts +++ b/__tests__/unit/services/cat/track-record.test.ts @@ -10,8 +10,8 @@ import { getCatTrackRecord } from '@/services/cat/track-record'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); type Response = { data: unknown; error: { message: string } | null }; diff --git a/__tests__/unit/services/count-public-wallets.test.ts b/__tests__/unit/services/count-public-wallets.test.ts index 1e34ee6fb..aab1c35dc 100644 --- a/__tests__/unit/services/count-public-wallets.test.ts +++ b/__tests__/unit/services/count-public-wallets.test.ts @@ -19,14 +19,14 @@ * Gated by scripts/check-rpc-exists.mjs; this is the instance. */ -const from = jest.fn(); -jest.mock('@/lib/supabase/admin', () => ({ +const from = vi.fn(); +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: () => ({ from }), })); -const errorLog = jest.fn(); -jest.mock('@/utils/logger', () => ({ - logger: { error: (...args: unknown[]) => errorLog(...args), info: jest.fn(), warn: jest.fn() }, +const errorLog = vi.fn(); +vi.mock('@/utils/logger', () => ({ + logger: { error: (...args: unknown[]) => errorLog(...args), info: vi.fn(), warn: vi.fn() }, })); import { countActiveProfileWallets } from '@/services/wallets/countPublicWallets'; @@ -35,8 +35,8 @@ import { countActiveProfileWallets } from '@/services/wallets/countPublicWallets function mockQuery(result: { count?: number | null; error?: { message: string; code?: string } }) { const filters: Record = {}; const chain = { - select: jest.fn(() => chain), - eq: jest.fn((col: string, val: unknown) => { + select: vi.fn(() => chain), + eq: vi.fn((col: string, val: unknown) => { filters[col] = val; return chain; }), diff --git a/__tests__/unit/services/currency/conversion.test.ts b/__tests__/unit/services/currency/conversion.test.ts index f1ca01f29..611bb3a83 100644 --- a/__tests__/unit/services/currency/conversion.test.ts +++ b/__tests__/unit/services/currency/conversion.test.ts @@ -29,8 +29,8 @@ beforeEach(() => { }); // Silence the warn that the missing-rate path emits. -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); const SATS_PER_BTC = 100_000_000; diff --git a/__tests__/unit/services/current-user-id-cache.test.ts b/__tests__/unit/services/current-user-id-cache.test.ts index 8ce1e0d72..43efab6a0 100644 --- a/__tests__/unit/services/current-user-id-cache.test.ts +++ b/__tests__/unit/services/current-user-id-cache.test.ts @@ -12,16 +12,13 @@ * onto one request rather than racing to make several. */ -import { - getCurrentUserId, - __resetCurrentUserIdCache, -} from '@/services/supabase/auth/session'; +import { getCurrentUserId, __resetCurrentUserIdCache } from '@/services/supabase/auth/session'; // The timeline re-exports it rather than defining its own; both names must be // the same function, or the cache would only cover half the callers. import { getCurrentUserId as timelineGetCurrentUserId } from '@/services/timeline/processors/social-shared'; -const getUser = jest.fn(); -jest.mock('@/lib/supabase/browser', () => ({ +const getUser = vi.fn(); +vi.mock('@/lib/supabase/browser', () => ({ __esModule: true, default: { auth: { @@ -33,7 +30,7 @@ jest.mock('@/lib/supabase/browser', () => ({ describe('getCurrentUserId', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); __resetCurrentUserIdCache(); getUser.mockResolvedValue({ data: { user: { id: 'u1' } } }); }); diff --git a/__tests__/unit/services/domain-search.test.ts b/__tests__/unit/services/domain-search.test.ts index 880dbc954..84a6f97c1 100644 --- a/__tests__/unit/services/domain-search.test.ts +++ b/__tests__/unit/services/domain-search.test.ts @@ -45,7 +45,7 @@ function isBootstrapUrl(url: string): boolean { } function mockFetch(impl: (url: string) => Promise> | Partial) { - global.fetch = jest.fn(async (input: RequestInfo | URL) => + global.fetch = vi.fn(async (input: RequestInfo | URL) => impl(String(input)) ) as unknown as typeof fetch; } @@ -56,7 +56,7 @@ beforeEach(() => { afterEach(() => { global.fetch = originalFetch; - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); describe('parseDomain', () => { @@ -127,7 +127,7 @@ describe('availability — the rule that stops a false “available”', () => { }); it('rejects a malformed query without calling any registry', async () => { - const fetchSpy = jest.fn(); + const fetchSpy = vi.fn(); global.fetch = fetchSpy as unknown as typeof fetch; const result = await checkDomain('not a domain', RDAP_TLDS); @@ -136,7 +136,7 @@ describe('availability — the rule that stops a false “available”', () => { }); it('caches a result so a repeated lookup does not hit the registry twice', async () => { - const fetchSpy = jest.fn(async () => ({ status: 404, ok: false }) as Partial); + const fetchSpy = vi.fn(async () => ({ status: 404, ok: false }) as Partial); global.fetch = fetchSpy as unknown as typeof fetch; await checkDomain('substrataintel.com', RDAP_TLDS); diff --git a/__tests__/unit/services/notify-mentions.test.ts b/__tests__/unit/services/notify-mentions.test.ts index e67e5410a..c948c0e59 100644 --- a/__tests__/unit/services/notify-mentions.test.ts +++ b/__tests__/unit/services/notify-mentions.test.ts @@ -13,8 +13,8 @@ * in it, and part of what was said. */ -const dispatch = jest.fn().mockResolvedValue(undefined); -jest.mock('@/services/notifications/dispatcher', () => ({ +const dispatch = vi.fn().mockResolvedValue(undefined); +vi.mock('@/services/notifications/dispatcher', () => ({ NotificationDispatcher: { dispatch: (...a: unknown[]) => dispatch(...a) }, })); @@ -23,7 +23,10 @@ import { notifyMentionedPeople } from '@/services/mentions/notify-mentions'; const admin = { from: () => ({ select: () => ({ - eq: () => ({ maybeSingle: () => Promise.resolve({ data: { name: 'Georgy', username: 'g' }, error: null }) }), + eq: () => ({ + maybeSingle: () => + Promise.resolve({ data: { name: 'Georgy', username: 'g' }, error: null }), + }), }), }), } as never; diff --git a/__tests__/unit/services/project-funding-enrichment.test.ts b/__tests__/unit/services/project-funding-enrichment.test.ts index dcb1892a7..e1c4d2dc9 100644 --- a/__tests__/unit/services/project-funding-enrichment.test.ts +++ b/__tests__/unit/services/project-funding-enrichment.test.ts @@ -12,15 +12,15 @@ import { enrichProjectsWithSettledFunding } from '@/services/wallets/project-funding'; import type { AnySupabaseClient } from '@/lib/supabase/types'; -jest.mock('@/services/currency', () => ({ - currencyConverter: { getRates: jest.fn().mockResolvedValue({}) }, +vi.mock('@/services/currency', () => ({ + currencyConverter: { getRates: vi.fn().mockResolvedValue({}) }, convertBtcTo: (amountBtc: number, currency: string) => currency === 'BTC' ? amountBtc : amountBtc * 100_000, })); function clientWithRpc(rows: unknown, error: unknown = null): AnySupabaseClient { return { - rpc: jest.fn().mockResolvedValue({ data: rows, error }), + rpc: vi.fn().mockResolvedValue({ data: rows, error }), } as unknown as AnySupabaseClient; } @@ -34,7 +34,12 @@ describe('enrichProjectsWithSettledFunding', () => { it('attaches settled totals in BTC + project currency + supporter count', async () => { const client = clientWithRpc([ { entity_id: 'btc-project', total_btc: 0.5, contributor_count: 3, named_supporter_count: 2 }, - { entity_id: 'chf-project', total_btc: 0.001, contributor_count: 1, named_supporter_count: 1 }, + { + entity_id: 'chf-project', + total_btc: 0.001, + contributor_count: 1, + named_supporter_count: 1, + }, ]); const result = await enrichProjectsWithSettledFunding(client, [ @@ -72,7 +77,7 @@ describe('enrichProjectsWithSettledFunding', () => { expect(a).toMatchObject({ raised_amount: 0, settled_raised_btc: 0, supporters_count: 0 }); const throwingClient = { - rpc: jest.fn().mockRejectedValue(new Error('network down')), + rpc: vi.fn().mockRejectedValue(new Error('network down')), } as unknown as AnySupabaseClient; const [b] = await enrichProjectsWithSettledFunding(throwingClient, [ { id: 'y', currency: 'BTC' }, diff --git a/__tests__/unit/services/rate-refresh-outside-render.test.ts b/__tests__/unit/services/rate-refresh-outside-render.test.ts index 560914b3d..610e69823 100644 --- a/__tests__/unit/services/rate-refresh-outside-render.test.ts +++ b/__tests__/unit/services/rate-refresh-outside-render.test.ts @@ -22,14 +22,16 @@ import { __setSnapshotForTests, } from '@/services/currency/rateSource.server'; +import type { Mock } from 'vitest'; + const MINUTE = 60_000; describe('getCachedRateSnapshot refresh timing', () => { - let fetchMock: jest.Mock; + let fetchMock: Mock; beforeEach(() => { - jest.useFakeTimers(); - fetchMock = jest.fn().mockResolvedValue({ + vi.useFakeTimers(); + fetchMock = vi.fn().mockResolvedValue({ ok: true, json: async () => ({ bitcoin: { chf: 52199, usd: 58000, eur: 55000, gbp: 47000 } }), }); @@ -39,7 +41,7 @@ describe('getCachedRateSnapshot refresh timing', () => { afterEach(() => { __setSnapshotForTests(null); - jest.useRealTimers(); + vi.useRealTimers(); }); it('starts no fetch synchronously when the snapshot is stale', () => { @@ -52,7 +54,7 @@ describe('getCachedRateSnapshot refresh timing', () => { expect(snap?.rates.CHF).toBe(52199); expect(fetchMock).not.toHaveBeenCalled(); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); expect(fetchMock).toHaveBeenCalledTimes(1); }); @@ -62,7 +64,7 @@ describe('getCachedRateSnapshot refresh timing', () => { expect(getCachedRateSnapshot()).toBeNull(); expect(fetchMock).not.toHaveBeenCalled(); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); expect(fetchMock).toHaveBeenCalledTimes(1); }); @@ -72,7 +74,7 @@ describe('getCachedRateSnapshot refresh timing', () => { expect(getCachedRateSnapshot()).toBeNull(); expect(fetchMock).not.toHaveBeenCalled(); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); expect(fetchMock).toHaveBeenCalledTimes(1); }); @@ -80,7 +82,7 @@ describe('getCachedRateSnapshot refresh timing', () => { __setSnapshotForTests({ rates: { CHF: 52199 }, fetchedAt: Date.now() }); expect(getCachedRateSnapshot()?.rates.CHF).toBe(52199); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); expect(fetchMock).not.toHaveBeenCalled(); }); diff --git a/__tests__/unit/services/reaction-count.test.ts b/__tests__/unit/services/reaction-count.test.ts index b1489d774..3014acc33 100644 --- a/__tests__/unit/services/reaction-count.test.ts +++ b/__tests__/unit/services/reaction-count.test.ts @@ -18,10 +18,10 @@ import { toggleLike } from '@/services/timeline/processors/reactions'; -const rpc = jest.fn(); -const from = jest.fn(); +const rpc = vi.fn(); +const from = vi.fn(); -jest.mock('@/services/timeline/processors/social-shared', () => ({ +vi.mock('@/services/timeline/processors/social-shared', () => ({ db: { rpc: (...args: unknown[]) => rpc(...args), from: (...args: unknown[]) => from(...args), @@ -40,7 +40,7 @@ function noExistingReaction() { describe('reaction counts', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); noExistingReaction(); }); diff --git a/__tests__/unit/services/reaction-state.test.ts b/__tests__/unit/services/reaction-state.test.ts index d6edde9d9..6676622e6 100644 --- a/__tests__/unit/services/reaction-state.test.ts +++ b/__tests__/unit/services/reaction-state.test.ts @@ -15,8 +15,8 @@ import { fetchReactionState } from '@/services/timeline/processors/reaction-state'; -const from = jest.fn(); -jest.mock('@/services/timeline/processors/social-shared', () => ({ +const from = vi.fn(); +vi.mock('@/services/timeline/processors/social-shared', () => ({ db: { from: (...args: unknown[]) => from(...args) }, getCurrentUserId: async () => 'me', })); @@ -37,7 +37,7 @@ function withTables(tables: Record) { } describe('fetchReactionState', () => { - beforeEach(() => jest.clearAllMocks()); + beforeEach(() => vi.clearAllMocks()); it('reads counts from the stats table, not from timeline_events', async () => { withTables({ diff --git a/__tests__/unit/services/reply-tree-query-count.test.ts b/__tests__/unit/services/reply-tree-query-count.test.ts index 057a90135..b2eaa1fe0 100644 --- a/__tests__/unit/services/reply-tree-query-count.test.ts +++ b/__tests__/unit/services/reply-tree-query-count.test.ts @@ -14,21 +14,21 @@ import { getReplies } from '@/services/timeline/queries/eventQueries'; -const from = jest.fn(); -const enrich = jest.fn(); +const from = vi.fn(); +const enrich = vi.fn(); -jest.mock('@/lib/supabase/browser', () => ({ +vi.mock('@/lib/supabase/browser', () => ({ __esModule: true, default: { from: (...a: unknown[]) => from(...a) }, })); -jest.mock('@/services/timeline/processors/enrichment', () => ({ +vi.mock('@/services/timeline/processors/enrichment', () => ({ enrichEventsForDisplay: (...a: unknown[]) => enrich(...a), })); -jest.mock('@/services/timeline/processors/reaction-state', () => ({ - attachReactionState: async (x: T) => x, +vi.mock('@/services/timeline/processors/reaction-state', () => ({ + attachReactionState: async (x: T) => x, EMPTY_REACTION_STATE: {}, })); -jest.mock('@/lib/supabase/untyped', () => ({ callRpc: jest.fn() })); +vi.mock('@/lib/supabase/untyped', () => ({ callRpc: vi.fn() })); /** * A fake table that actually honours the parent filter. @@ -68,7 +68,7 @@ function tableOf(rows: Array>) { describe('getReplies query cost', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); // Enrichment echoes its input, mapped to the display shape the tree needs. enrich.mockImplementation(async (rows: Array>) => rows.map(r => ({ id: r.id, parentEventId: r.parent_event_id })) diff --git a/__tests__/unit/services/timeline-warms-reader.test.ts b/__tests__/unit/services/timeline-warms-reader.test.ts index e5c1b4a32..0fbf1fa5c 100644 --- a/__tests__/unit/services/timeline-warms-reader.test.ts +++ b/__tests__/unit/services/timeline-warms-reader.test.ts @@ -17,38 +17,44 @@ * table below: every read the facade exposes, not the one I happened to open. */ -const order: string[] = []; +// vi.hoisted: the vi.mock factories below are hoisted above module-level +// consts, so anything they close over must be hoisted with them. +const { order, warmCurrentUserId, queries } = vi.hoisted(() => { + const order: string[] = []; -const warmCurrentUserId = jest.fn(() => { - order.push('warm'); + const warmCurrentUserId = vi.fn(() => { + order.push('warm'); + }); + + const record = (name: string) => + vi.fn(async () => { + order.push(name); + return { success: true, events: [], posts: [], replies: [], pagination: {}, total: 0 }; + }); + + const queries = { + getUserFeed: record('getUserFeed'), + getProjectFeed: record('getProjectFeed'), + getProfileFeed: record('getProfileFeed'), + getFollowedUsersFeed: record('getFollowedUsersFeed'), + getCommunityFeed: record('getCommunityFeed'), + getEnrichedUserFeed: record('getEnrichedUserFeed'), + getEnrichedFollowingFeed: record('getEnrichedFollowingFeed'), + getEventById: record('getEventById'), + getReplies: record('getReplies'), + searchPosts: record('searchPosts'), + getThreadPosts: record('getThreadPosts'), + }; + + return { order, warmCurrentUserId, queries }; }); -jest.mock('@/services/supabase/auth/session', () => ({ +vi.mock('@/services/supabase/auth/session', () => ({ warmCurrentUserId: () => warmCurrentUserId(), - getCurrentUserId: jest.fn(async () => 'u1'), + getCurrentUserId: vi.fn(async () => 'u1'), })); -const record = (name: string) => - jest.fn(async () => { - order.push(name); - return { success: true, events: [], posts: [], replies: [], pagination: {}, total: 0 }; - }); - -const queries = { - getUserFeed: record('getUserFeed'), - getProjectFeed: record('getProjectFeed'), - getProfileFeed: record('getProfileFeed'), - getFollowedUsersFeed: record('getFollowedUsersFeed'), - getCommunityFeed: record('getCommunityFeed'), - getEnrichedUserFeed: record('getEnrichedUserFeed'), - getEnrichedFollowingFeed: record('getEnrichedFollowingFeed'), - getEventById: record('getEventById'), - getReplies: record('getReplies'), - searchPosts: record('searchPosts'), - getThreadPosts: record('getThreadPosts'), -}; - -jest.mock('@/services/timeline/queries', () => queries); +vi.mock('@/services/timeline/queries', () => queries); import { timelineService } from '@/services/timeline'; @@ -82,9 +88,13 @@ describe('timeline reads warm the reader id first', () => { it('covers every read the facade exposes', () => { // If a new read is added to the service without warming, this catches it // even when nobody thinks to add a case above. - const exposed = Object.getOwnPropertyNames( - Object.getPrototypeOf(timelineService) - ).filter(m => /^(get|search)/.test(m) && m !== 'getEventCounts' && m !== 'getEventComments' && m !== 'getCommentReplies'); + const exposed = Object.getOwnPropertyNames(Object.getPrototypeOf(timelineService)).filter( + m => + /^(get|search)/.test(m) && + m !== 'getEventCounts' && + m !== 'getEventComments' && + m !== 'getCommentReplies' + ); const covered = new Set(READS.map(([name]) => name as string)); expect([...exposed].filter(m => !covered.has(m))).toEqual([]); diff --git a/__tests__/unit/services/voice/intentRouter.test.ts b/__tests__/unit/services/voice/intentRouter.test.ts index 4bd5efa82..3d176918b 100644 --- a/__tests__/unit/services/voice/intentRouter.test.ts +++ b/__tests__/unit/services/voice/intentRouter.test.ts @@ -9,11 +9,11 @@ import { routeVoiceIntent, MIN_ROUTE_CONFIDENCE } from '@/services/voice/intent-router'; -jest.mock('@/utils/logger', () => ({ - logger: { warn: jest.fn(), error: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { warn: vi.fn(), error: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -const fetchMock = jest.fn(); +const fetchMock = vi.fn(); global.fetch = fetchMock as unknown as typeof fetch; /** Shapes a model reply the way the provider returns it. */ @@ -27,7 +27,7 @@ function modelReplies(payload: unknown) { const SENTENCE = 'sell my old road bike for 200 francs, a Cannondale in decent condition'; beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); process.env.GROQ_API_KEY = 'test-key'; }); diff --git a/__tests__/unit/services/warm-reader-is-browser-only.test.ts b/__tests__/unit/services/warm-reader-is-browser-only.test.ts index 5125b4fc4..9c429c50f 100644 --- a/__tests__/unit/services/warm-reader-is-browser-only.test.ts +++ b/__tests__/unit/services/warm-reader-is-browser-only.test.ts @@ -1,5 +1,5 @@ /** - * @jest-environment node + * @vitest-environment node * * Warming the reader's id must do NOTHING on the server. * @@ -21,9 +21,9 @@ * server path stayed broken — which is exactly how the bug shipped. */ -const getUser = jest.fn(); +const getUser = vi.fn(); -jest.mock('@/lib/supabase/browser', () => ({ +vi.mock('@/lib/supabase/browser', () => ({ __esModule: true, default: { auth: { diff --git a/__tests__/unit/services/weeklyDigest.email.test.ts b/__tests__/unit/services/weeklyDigest.email.test.ts index 76b6afcbd..caaf858f8 100644 --- a/__tests__/unit/services/weeklyDigest.email.test.ts +++ b/__tests__/unit/services/weeklyDigest.email.test.ts @@ -15,7 +15,7 @@ // emailService transitively imports the Resend client, which doesn't load in // the jest env (postal-mime); the pure mapper under test never touches it. -jest.mock('@/lib/email/client', () => ({ getEmailClient: jest.fn() })); +vi.mock('@/lib/email/client', () => ({ getEmailClient: vi.fn() })); import { buildWeeklyDigestEmail } from '@/services/notifications/emailService'; diff --git a/__tests__/unit/solon/allocation-policy.test.ts b/__tests__/unit/solon/allocation-policy.test.ts index 4abab8d1d..f05ddec58 100644 --- a/__tests__/unit/solon/allocation-policy.test.ts +++ b/__tests__/unit/solon/allocation-policy.test.ts @@ -13,8 +13,8 @@ import { canonicalJson, contentHashOf } from '@/services/solon/canonical'; import { activateVersion } from '@/services/solon/allocation-policy'; import { GENESIS_ALLOCATION_POLICY } from '@/config/solon'; -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); describe('canonical JSON (cross-repo contract with Solon)', () => { @@ -48,22 +48,22 @@ function buildPolicySupabase(row: Record | null) { const filters: unknown[][] = []; const chain: Record = {}; for (const method of ['select', 'order', 'in']) { - chain[method] = jest.fn().mockReturnValue(chain); + chain[method] = vi.fn().mockReturnValue(chain); } - chain.eq = jest.fn((...args: unknown[]) => { + chain.eq = vi.fn((...args: unknown[]) => { filters.push(args); return chain; }); - chain.update = jest.fn((values: Record) => { + chain.update = vi.fn((values: Record) => { updates.push({ values, filters }); return chain; }); - chain.maybeSingle = jest.fn().mockResolvedValue({ data: row, error: null }); + chain.maybeSingle = vi.fn().mockResolvedValue({ data: row, error: null }); chain.then = (resolve: (value: { data: unknown; error: null }) => unknown) => Promise.resolve(resolve({ data: row, error: null })); return chain; }; - return { from: jest.fn(() => makeChain()), _updates: updates }; + return { from: vi.fn(() => makeChain()), _updates: updates }; } describe('activateVersion', () => { diff --git a/__tests__/unit/solon/cat-proposer.test.ts b/__tests__/unit/solon/cat-proposer.test.ts index b4d55b814..b5186a5e7 100644 --- a/__tests__/unit/solon/cat-proposer.test.ts +++ b/__tests__/unit/solon/cat-proposer.test.ts @@ -1,5 +1,5 @@ /** - * @jest-environment node + * @vitest-environment node * * The Cat's proposer edge — "the Cat proposes; Solon disposes." * @@ -18,8 +18,10 @@ import { import { governanceHandlers } from '@/services/cat/handlers/governance'; import { contentHashOf } from '@/services/solon/canonical'; -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); const PRIV = '1111111111111111111111111111111111111111111111111111111111111111'; @@ -73,15 +75,15 @@ function buildSupabase() { const makeChain = () => { const chain: Record = {}; for (const method of ['select', 'eq', 'order', 'limit']) { - chain[method] = jest.fn().mockReturnValue(chain); + chain[method] = vi.fn().mockReturnValue(chain); } - chain.maybeSingle = jest.fn().mockResolvedValue({ data: { version: 1 }, error: null }); - chain.single = jest.fn().mockResolvedValue({ data: { id: 'draft-1' }, error: null }); - chain.insert = jest.fn((payload: unknown) => { + chain.maybeSingle = vi.fn().mockResolvedValue({ data: { version: 1 }, error: null }); + chain.single = vi.fn().mockResolvedValue({ data: { id: 'draft-1' }, error: null }); + chain.insert = vi.fn((payload: unknown) => { writes.push({ op: 'insert', payload }); return chain; }); - chain.update = jest.fn((payload: unknown) => { + chain.update = vi.fn((payload: unknown) => { writes.push({ op: 'update', payload }); return chain; }); @@ -89,7 +91,7 @@ function buildSupabase() { Promise.resolve(resolve({ data: null, error: null })); return chain; }; - return { from: jest.fn(() => makeChain()), _writes: writes }; + return { from: vi.fn(() => makeChain()), _writes: writes }; } const PARAMS = { @@ -103,7 +105,7 @@ describe('propose_governance_change handler', () => { const OLD_ENV = process.env; beforeEach(() => { process.env = { ...OLD_ENV, CAT_SOLON_PRIVKEY: PRIV, SOLON_AGENT_API_KEY: 'sk_solon_test' }; - global.fetch = jest.fn(); + global.fetch = vi.fn(); }); afterAll(() => { process.env = OLD_ENV; @@ -129,7 +131,7 @@ describe('propose_governance_change handler', () => { }); it('records a draft, files on Solon, and stores the proposal id', async () => { - (global.fetch as jest.Mock).mockResolvedValue({ + (global.fetch as Mock).mockResolvedValue({ json: async () => ({ created: true, verified: true, proposalId: 'prop-42' }), }); const supabase = buildSupabase(); @@ -151,7 +153,7 @@ describe('propose_governance_change handler', () => { expect(update.solon_proposal_id).toBe('prop-42'); // The POST body carried a signature Solon will accept. - const body = JSON.parse((global.fetch as jest.Mock).mock.calls[0][1].body as string); + const body = JSON.parse((global.fetch as Mock).mock.calls[0][1].body as string); expect( verifyBitcoinMessage( solonProposalMessage({ @@ -168,7 +170,7 @@ describe('propose_governance_change handler', () => { }); it('marks the draft rejected when Solon refuses the filing', async () => { - (global.fetch as jest.Mock).mockResolvedValue({ + (global.fetch as Mock).mockResolvedValue({ json: async () => ({ created: false, verified: true, diff --git a/__tests__/unit/solon/decision-verify.test.ts b/__tests__/unit/solon/decision-verify.test.ts index 5f9120121..29aea8e33 100644 --- a/__tests__/unit/solon/decision-verify.test.ts +++ b/__tests__/unit/solon/decision-verify.test.ts @@ -1,5 +1,5 @@ /** - * @jest-environment node + * @vitest-environment node * * Decision verification — the edge where Solon governance becomes OrangeCat * reality. Two layers under test: @@ -18,8 +18,10 @@ import { DATABASE_TABLES } from '@/config/database-tables'; import { SOLON_ORG_ID } from '@/config/solon'; import { contentHashOf } from '@/services/solon/canonical'; -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +import type { Mock } from 'vitest'; + +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); // Fixed vector generated by Solon's signMessage() with privkey 0x11…11. @@ -110,15 +112,15 @@ function buildSupabase(config: { const makeChain = (table: string) => { const chain: Record = {}; for (const method of ['select', 'eq', 'is', 'order', 'limit', 'in', 'gte']) { - chain[method] = jest.fn().mockReturnValue(chain); + chain[method] = vi.fn().mockReturnValue(chain); } - chain.maybeSingle = jest.fn().mockResolvedValue({ data: null, error: null }); - chain.single = jest.fn().mockResolvedValue({ data: { id: 'new-row' }, error: null }); - chain.insert = jest.fn((payload: unknown) => { + chain.maybeSingle = vi.fn().mockResolvedValue({ data: null, error: null }); + chain.single = vi.fn().mockResolvedValue({ data: { id: 'new-row' }, error: null }); + chain.insert = vi.fn((payload: unknown) => { writes.push({ table, op: 'insert', payload }); return chain; }); - chain.update = jest.fn((payload: unknown) => { + chain.update = vi.fn((payload: unknown) => { writes.push({ table, op: 'update', payload }); return chain; }); @@ -132,7 +134,7 @@ function buildSupabase(config: { }; return chain; }; - return { from: jest.fn((table: string) => makeChain(table)), _writes: writes }; + return { from: vi.fn((table: string) => makeChain(table)), _writes: writes }; } const PINNED = [{ bitcoin_address: VECTOR.address, voting_weight: 1 }]; @@ -266,12 +268,12 @@ describe('verifyAndApplyDecision', () => { // maybeSingle return the freshly inserted draft on later calls. let policyReads = 0; const origFrom = supabase.from; - supabase.from = jest.fn((table: string) => { + supabase.from = vi.fn((table: string) => { const chain = origFrom(table) as Record & { - maybeSingle: jest.Mock; + maybeSingle: Mock; }; if (table === DATABASE_TABLES.ALLOCATION_POLICIES) { - chain.maybeSingle = jest.fn(() => { + chain.maybeSingle = vi.fn(() => { policyReads += 1; // reads: 1=existing-decision check, 2=draft-by-hash, 3=latest version, // 4=activateVersion row load. diff --git a/__tests__/unit/tips/tip-service.test.ts b/__tests__/unit/tips/tip-service.test.ts index f6a30e9b2..4ead493d7 100644 --- a/__tests__/unit/tips/tip-service.test.ts +++ b/__tests__/unit/tips/tip-service.test.ts @@ -11,42 +11,42 @@ import { checkPublicPaymentStatus, } from '@/domain/payments/paymentFlowService'; -jest.mock('@/domain/payments/walletResolutionService', () => ({ - resolveUserWallet: jest.fn(), +vi.mock('@/domain/payments/walletResolutionService', () => ({ + resolveUserWallet: vi.fn(), })); -jest.mock('@/lib/supabase/admin', () => ({ - getAdminClient: jest.fn(() => ({})), +vi.mock('@/lib/supabase/admin', () => ({ + getAdminClient: vi.fn(() => ({})), })); -jest.mock('@/domain/payments/paymentFlowService', () => ({ - initiateTip: jest.fn(), - checkPublicPaymentStatus: jest.fn(), +vi.mock('@/domain/payments/paymentFlowService', () => ({ + initiateTip: vi.fn(), + checkPublicPaymentStatus: vi.fn(), })); // The dispatcher transitively imports the Resend email client, which cannot // load in the jest environment — and we want to assert dispatch calls anyway. -jest.mock('@/services/notifications/dispatcher', () => ({ - NotificationDispatcher: { dispatch: jest.fn().mockResolvedValue(undefined) }, +vi.mock('@/services/notifications/dispatcher', () => ({ + NotificationDispatcher: { dispatch: vi.fn().mockResolvedValue(undefined) }, })); // Dead-end dedup reads recent notifications through fromTable; default: none. -const mockDedupLimit = jest.fn().mockResolvedValue({ data: [] }); -jest.mock('@/lib/supabase/untyped', () => ({ - fromTable: jest.fn(() => ({ - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - gte: jest.fn().mockReturnThis(), +const mockDedupLimit = vi.fn().mockResolvedValue({ data: [] }); +vi.mock('@/lib/supabase/untyped', () => ({ + fromTable: vi.fn(() => ({ + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + gte: vi.fn().mockReturnThis(), limit: mockDedupLimit, })), })); import { NotificationDispatcher } from '@/services/notifications/dispatcher'; +import type { MockedFunction } from 'vitest'; + /** The dead-end notification is fire-and-forget — let its microtasks settle. */ const flush = () => new Promise(resolve => setTimeout(resolve, 0)); -const mockResolveWallet = resolveUserWallet as jest.MockedFunction; -const mockInitiateTipPayment = initiateTipPayment as jest.MockedFunction; -const mockCheckStatus = checkPublicPaymentStatus as jest.MockedFunction< - typeof checkPublicPaymentStatus ->; +const mockResolveWallet = resolveUserWallet as MockedFunction; +const mockInitiateTipPayment = initiateTipPayment as MockedFunction; +const mockCheckStatus = checkPublicPaymentStatus as MockedFunction; /** Minimal supabase stub whose profiles lookup resolves to `profile`. */ function supabaseWith(profile: Record | null) { @@ -62,7 +62,7 @@ function supabaseWith(profile: Record | null) { } beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe('getTipReceiveInfo', () => { diff --git a/__tests__/unit/wallets/receive-status.test.ts b/__tests__/unit/wallets/receive-status.test.ts index 07e405939..78ef4f23a 100644 --- a/__tests__/unit/wallets/receive-status.test.ts +++ b/__tests__/unit/wallets/receive-status.test.ts @@ -11,30 +11,32 @@ import { getOwnerReceiveStatus } from '@/domain/wallets/receiveStatus'; import { resolveUserWallet } from '@/domain/payments/walletResolutionService'; import { canDecrypt } from '@/domain/payments/encryptionService'; -jest.mock('@/domain/payments/walletResolutionService', () => ({ - resolveUserWallet: jest.fn(), +import type { MockedFunction } from 'vitest'; + +vi.mock('@/domain/payments/walletResolutionService', () => ({ + resolveUserWallet: vi.fn(), })); -jest.mock('@/domain/payments/encryptionService', () => ({ - canDecrypt: jest.fn(), +vi.mock('@/domain/payments/encryptionService', () => ({ + canDecrypt: vi.fn(), })); const nwcRows: Array<{ id: string; nwc_connection_uri: string | null }> = []; -jest.mock('@/lib/supabase/admin', () => ({ +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: () => ({ from: () => ({ - select: jest.fn().mockReturnThis(), - eq: jest.fn().mockReturnThis(), - not: jest.fn().mockResolvedValue({ data: nwcRows, error: null }), + select: vi.fn().mockReturnThis(), + eq: vi.fn().mockReturnThis(), + not: vi.fn().mockResolvedValue({ data: nwcRows, error: null }), }), }), })); -const mockResolve = resolveUserWallet as jest.MockedFunction; -const mockCanDecrypt = canDecrypt as jest.MockedFunction; +const mockResolve = resolveUserWallet as MockedFunction; +const mockCanDecrypt = canDecrypt as MockedFunction; beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); nwcRows.length = 0; mockCanDecrypt.mockReturnValue(true); }); diff --git a/__tests__/unit/wallets/wallet-update-handles.test.ts b/__tests__/unit/wallets/wallet-update-handles.test.ts index ecf5a604a..387dbaa68 100644 --- a/__tests__/unit/wallets/wallet-update-handles.test.ts +++ b/__tests__/unit/wallets/wallet-update-handles.test.ts @@ -12,8 +12,8 @@ import { walletUpdateSchema } from '@/lib/validation/finance'; import { buildWalletUpdates } from '@/domain/wallets/updateWallet'; import { encrypt } from '@/domain/payments/encryptionService'; -jest.mock('@/domain/payments/encryptionService', () => ({ - encrypt: jest.fn((plaintext: string) => `encrypted:${plaintext}`), +vi.mock('@/domain/payments/encryptionService', () => ({ + encrypt: vi.fn((plaintext: string) => `encrypted:${plaintext}`), })); type Parsed = ReturnType; @@ -65,13 +65,17 @@ describe('buildWalletUpdates', () => { }); it('rejects a connection string that is not an NWC URI', () => { - const { updates, error } = buildWalletUpdates(parse({ nwc_connection_uri: 'https://evil.example' })); + const { updates, error } = buildWalletUpdates( + parse({ nwc_connection_uri: 'https://evil.example' }) + ); expect(updates).toBeNull(); expect(error).not.toBeNull(); }); it('clears a handle when the form sends an empty value', () => { - const { updates, error } = buildWalletUpdates(parse({ lightning_address: '', address_or_xpub: '' })); + const { updates, error } = buildWalletUpdates( + parse({ lightning_address: '', address_or_xpub: '' }) + ); expect(error).toBeNull(); expect(updates).toMatchObject({ lightning_address: null, address_or_xpub: null }); }); diff --git a/__tests__/unit/wallets/wallet-usage.test.ts b/__tests__/unit/wallets/wallet-usage.test.ts index 011cfecf4..4ca792586 100644 --- a/__tests__/unit/wallets/wallet-usage.test.ts +++ b/__tests__/unit/wallets/wallet-usage.test.ts @@ -6,12 +6,12 @@ * resolution failure degrades to null instead of breaking the page. */ -jest.mock('@/utils/logger', () => ({ - logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() }, +vi.mock('@/utils/logger', () => ({ + logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() }, })); -const mockResolve = jest.fn(); -jest.mock('@/domain/payments', () => ({ +const mockResolve = vi.fn(); +vi.mock('@/domain/payments', () => ({ resolveSellerWallet: (...args: unknown[]) => mockResolve(...args), })); @@ -22,7 +22,7 @@ let addressTwins: Array<{ id: string }> = []; let linkRows: Array<{ entity_type: string; entity_id: string }> = []; let visibleByTable: Record = {}; -jest.mock('@/lib/supabase/admin', () => ({ +vi.mock('@/lib/supabase/admin', () => ({ getAdminClient: () => ({ from: (table: string) => { if (table === 'wallets') { diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index 490a44aa7..000000000 --- a/jest.config.js +++ /dev/null @@ -1,83 +0,0 @@ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'jsdom', - moduleDirectories: ['node_modules', 'src'], - setupFilesAfterEnv: ['/jest.setup.ts'], - transform: { - '^.+\\.(ts|tsx)$': [ - 'ts-jest', - { - tsconfig: 'tsconfig.test.json', - }, - ], - // @noble/@scure ship ESM-only .js (used by the Solon decision verifier); - // scoped here so no other node_modules JS goes through a transform. - '[\\/]node_modules[\\/](@noble|@scure)[\\/].+\\.js$': [ - 'ts-jest', - { - tsconfig: { allowJs: true }, - diagnostics: false, - }, - ], - }, - transformIgnorePatterns: [ - 'node_modules/(?!(@supabase/.*|@playwright/.*|isows/.*|bs58check|bs58|safe-buffer|base-x|@noble/.*|@scure/.*))', - ], - testTimeout: 30000, - collectCoverageFrom: [ - 'src/**/*.{ts,tsx}', - '!src/**/*.d.ts', - '!src/**/*.test.{ts,tsx}', - '!src/**/__tests__/**', - ], - coverageReporters: ['text', 'lcov', 'html'], - // Ratchet floor — set just below measured coverage (2026-07: ~10.9% stmts, - // 7.6% branches) so coverage can only go up. Raise as tests are added; - // never lower to make a failing build pass. - coverageThreshold: { - global: { - statements: 10, - branches: 7, - functions: 7, - lines: 10, - }, - }, - verbose: true, - // Exclude Playwright tests from Jest - // Parallel-session worktrees under .claude/ carry their own __mocks__ and - // tests; without this they pollute the haste map (duplicate manual mocks - // silently mocking real modules) and break unrelated suites. - modulePathIgnorePatterns: ['/.claude/'], - testPathIgnorePatterns: [ - '/node_modules/', - '/tests/e2e/', - '/.next/', - '/playwright-report/', - '/test-results/', - '/.claude/worktrees/', - '\\.spec\\.(ts|tsx)$', // Exclude Playwright spec files - ], - // Mock Next.js modules that cause issues in Jest - moduleNameMapper: { - '^@/components/ui/tabs$': '/__mocks__/ui-tabs.js', - // Jest resolves lucide's ESM to a build where some icons come back - // undefined, which fails as "Element type is invalid" and looks like a - // component bug. See __mocks__/lucide-react.js. - '^lucide-react$': '/__mocks__/lucide-react.js', - '^@/contexts/AuthContext$': '/__mocks__/contexts/AuthContext.js', - '^@/lib/nostr/nwc$': '/__mocks__/nostr-nwc.js', - '^@/(.*)$': '/src/$1', - '^next/navigation$': '/__mocks__/next-navigation.js', - '^next/server$': '/__mocks__/next-server.js', - '^vitest$': '/__mocks__/vitest.js', - '^isows/(.*)$': '/__mocks__/isows.js', - // NOTE: crypto encoders/validators (bs58check, formerly - // bitcoin-address-validation) are deliberately NOT mocked — stubbing them - // made tests pass vacuously: derivation against 'mockedEncodedValue' - // instead of the BIP spec vectors, and validate() returning true for - // EVERY string. Address validation now goes through bitcoinjs-lib (CJS), - // so no ESM transform gymnastics are needed. Beware: the ts-jest - // `transform` above only compiles .ts/.tsx — an ESM-only .js dependency - // cannot be whitelisted into working via transformIgnorePatterns alone. - }, -}; diff --git a/package-lock.json b/package-lock.json index f30443d9a..8b5f31b3e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -80,6 +80,7 @@ "remark": "^15.0.1", "remark-gfm": "^4.0.1", "resend": "^6.21.0", + "sharp": "^0.35.4", "sonner": "^2.0.7", "tailwind-merge": "^3.3.1", "tailwindcss": "^4.3.3", @@ -103,12 +104,12 @@ "@testing-library/jest-dom": "^7.0.0", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.4", - "@types/jest": "^30.0.0", "@types/node": "^26.3.0", "@types/react": "^19.2.18", "@types/react-dom": "^19.2.4", "@typescript-eslint/eslint-plugin": "^8.67.0", "@typescript-eslint/parser": "^8.67.0", + "@vitest/coverage-v8": "^4.1.11", "chalk": "^6.0.0", "concurrently": "^10.0.4", "dotenv": "^16.5.0", @@ -117,9 +118,8 @@ "eslint-plugin-jsdoc": "^63.3.3", "eslint-plugin-unused-imports": "^4.4.1", "husky": "^9.1.7", - "jest": "^30.3.0", - "jest-environment-jsdom": "^30.2.0", "jscpd": "5.0.16", + "jsdom": "^29.1.1", "lint-staged": "^17.3.0", "node-fetch": "^3.3.2", "pg": "^8.23.0", @@ -127,7 +127,7 @@ "prettier": "^3.6.2", "shadcn": "^4.19.0", "supabase": "^2.115.0", - "ts-jest": "^29.4.12", + "vitest": "^4.1.11", "ws": "^8.21.3" }, "engines": { @@ -154,21 +154,55 @@ } }, "node_modules/@asamuzakjp/css-color": { - "version": "3.2.0", + "version": "5.1.11", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz", + "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==", "dev": true, "license": "MIT", "dependencies": { - "@csstools/css-calc": "^2.1.3", - "@csstools/css-color-parser": "^3.0.9", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "lru-cache": "^10.4.3" + "@asamuzakjp/generational-cache": "^1.0.1", + "@csstools/css-calc": "^3.2.0", + "@csstools/css-color-parser": "^4.1.0", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { - "version": "10.4.3", + "node_modules/@asamuzakjp/dom-selector": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.1.1.tgz", + "integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "@asamuzakjp/generational-cache": "^1.0.1", + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.2.1", + "is-potential-custom-element-name": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/generational-cache": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz", + "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "dev": true, + "license": "MIT" }, "node_modules/@asteasolutions/zod-to-openapi": { "version": "9.1.0", @@ -460,89 +494,6 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "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-syntax-import-meta": { - "version": "7.10.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-jsx": { "version": "7.27.1", "dev": true, @@ -557,100 +508,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-typescript": { "version": "7.27.1", "dev": true, @@ -765,13 +622,23 @@ "node": ">=6.9.0" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", + "node_modules/@bramus/specificity": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz", + "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "css-tree": "^3.0.0" + }, + "bin": { + "specificity": "bin/cli.js" + } }, "node_modules/@csstools/color-helpers": { - "version": "5.1.0", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.1.1.tgz", + "integrity": "sha512-gLNsunvwf3mCi5u5o46/Z/JcJMnhbHSaZ69rkgPzNM3J4s8hWwpPUQB6/tt0EDFyCiWzxANlx+2LJwpYj4zS1w==", "dev": true, "funding": [ { @@ -785,11 +652,13 @@ ], "license": "MIT-0", "engines": { - "node": ">=18" + "node": ">=20.19.0" } }, "node_modules/@csstools/css-calc": { - "version": "2.1.4", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.3.0.tgz", + "integrity": "sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==", "dev": true, "funding": [ { @@ -803,15 +672,17 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" } }, "node_modules/@csstools/css-color-parser": { - "version": "3.1.0", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.2.2.tgz", + "integrity": "sha512-3QKjR/vxyjcSXBLgb6lP0S3MGdvwbmqSsvLPbYdVORqPDc8FX1HAJ0Spk38bxaRXgvENTA47tlhhbb5Z2e8hEg==", "dev": true, "funding": [ { @@ -825,19 +696,21 @@ ], "license": "MIT", "dependencies": { - "@csstools/color-helpers": "^5.1.0", - "@csstools/css-calc": "^2.1.4" + "@csstools/color-helpers": "^6.1.1", + "@csstools/css-calc": "^3.3.0" }, "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" } }, "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.5", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", "dev": true, "funding": [ { @@ -851,14 +724,41 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.10.tgz", + "integrity": "sha512-xBja6gaAaH2R2c7eNyl0TY4dhnnZ2uhj+KXpLdEQ6M/wuk9bYFZM8wY0ykw3VO4TgEJ56KGlerXS/9KBKVR/Cg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } } }, "node_modules/@csstools/css-tokenizer": { - "version": "3.0.4", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", "dev": true, "funding": [ { @@ -872,7 +772,7 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" } }, "node_modules/@discoveryjs/json-ext": { @@ -1128,6 +1028,24 @@ "node": "^20.19.0 || ^22.13.0 || >=24" } }, + "node_modules/@exodus/bytes": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.1.tgz", + "integrity": "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } + } + }, "node_modules/@floating-ui/core": { "version": "1.8.0", "license": "MIT", @@ -1918,1484 +1836,1421 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", "dev": true, "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "dev": true, + "node_modules/@marsidev/react-turnstile": { + "version": "1.6.0", "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "peerDependencies": { + "react": "^17.0.2 || ^18.0.0 || ^19.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0" } }, - "node_modules/@jest/console": { - "version": "30.3.0", - "dev": true, + "node_modules/@mdx-js/loader": { + "version": "3.1.1", "license": "MIT", "dependencies": { - "@jest/types": "30.3.0", - "@types/node": "*", - "chalk": "^4.1.2", - "jest-message-util": "30.3.0", - "jest-util": "30.3.0", - "slash": "^3.0.0" + "@mdx-js/mdx": "^3.0.0", + "source-map": "^0.7.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "webpack": ">=5" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } } }, - "node_modules/@jest/console/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, + "node_modules/@mdx-js/mdx": { + "version": "3.1.1", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "acorn": "^8.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-scope": "^1.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@jest/console/node_modules/chalk": { - "version": "4.1.2", - "dev": true, + "node_modules/@mdx-js/react": { + "version": "3.1.1", "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "@types/mdx": "^2.0.0" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" } }, - "node_modules/@jest/console/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.30.0", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "@hono/node-server": "^1.19.9 || ^2.0.5", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.2.1", + "express-rate-limit": "^8.2.1", + "hono": "^4.11.4", + "jose": "^6.1.3", + "json-schema-typed": "^8.0.2", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.25 || ^4.0", + "zod-to-json-schema": "^3.25.1" }, "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/core": { - "version": "30.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "30.3.0", - "@jest/pattern": "30.0.1", - "@jest/reporters": "30.3.0", - "@jest/test-result": "30.3.0", - "@jest/transform": "30.3.0", - "@jest/types": "30.3.0", - "@types/node": "*", - "ansi-escapes": "^4.3.2", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "exit-x": "^0.2.2", - "graceful-fs": "^4.2.11", - "jest-changed-files": "30.3.0", - "jest-config": "30.3.0", - "jest-haste-map": "30.3.0", - "jest-message-util": "30.3.0", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.3.0", - "jest-resolve-dependencies": "30.3.0", - "jest-runner": "30.3.0", - "jest-runtime": "30.3.0", - "jest-snapshot": "30.3.0", - "jest-util": "30.3.0", - "jest-validate": "30.3.0", - "jest-watcher": "30.3.0", - "pretty-format": "30.3.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "@cfworker/json-schema": "^4.1.1", + "zod": "^3.25 || ^4.0" }, "peerDependenciesMeta": { - "node-notifier": { + "@cfworker/json-schema": { "optional": true + }, + "zod": { + "optional": false } } }, - "node_modules/@jest/core/node_modules/chalk": { - "version": "4.1.2", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/ajv-formats": { + "version": "3.0.1", "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ajv": "^8.0.0" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "ajv": "^8.0.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependenciesMeta": { + "ajv": { + "optional": true + } } }, - "node_modules/@jest/core/node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" } }, - "node_modules/@jest/core/node_modules/pretty-format": { - "version": "30.3.0", + "node_modules/@next/bundle-analyzer": { + "version": "16.3.2", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "webpack-bundle-analyzer": "4.10.1" } }, - "node_modules/@jest/core/node_modules/react-is": { - "version": "18.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@jest/core/node_modules/supports-color": { + "node_modules/@next/bundle-analyzer/node_modules/commander": { "version": "7.2.0", "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/diff-sequences": { - "version": "30.3.0", - "dev": true, - "license": "MIT", "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 10" } }, - "node_modules/@jest/environment": { - "version": "30.3.0", + "node_modules/@next/bundle-analyzer/node_modules/webpack-bundle-analyzer": { + "version": "4.10.1", "dev": true, "license": "MIT", "dependencies": { - "@jest/fake-timers": "30.3.0", - "@jest/types": "30.3.0", - "@types/node": "*", - "jest-mock": "30.3.0" + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "gzip-size": "^6.0.0", + "html-escaper": "^2.0.2", + "is-plain-object": "^5.0.0", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 10.13.0" } }, - "node_modules/@jest/environment-jsdom-abstract": { - "version": "30.3.0", + "node_modules/@next/bundle-analyzer/node_modules/ws": { + "version": "7.5.11", "dev": true, "license": "MIT", - "dependencies": { - "@jest/environment": "30.3.0", - "@jest/fake-timers": "30.3.0", - "@jest/types": "30.3.0", - "@types/jsdom": "^21.1.7", - "@types/node": "*", - "jest-mock": "30.3.0", - "jest-util": "30.3.0" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=8.3.0" }, "peerDependencies": { - "canvas": "^3.0.0", - "jsdom": "*" + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" }, "peerDependenciesMeta": { - "canvas": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { "optional": true } } }, - "node_modules/@jest/expect": { - "version": "30.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "expect": "30.3.0", - "jest-snapshot": "30.3.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } + "node_modules/@next/env": { + "version": "16.2.12", + "license": "MIT" }, - "node_modules/@jest/expect-utils": { - "version": "30.3.0", + "node_modules/@next/eslint-plugin-next": { + "version": "16.3.1", "dev": true, "license": "MIT", "dependencies": { - "@jest/get-type": "30.1.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "@eslint-community/eslint-utils": "4.9.1", + "fast-glob": "3.3.1" } }, - "node_modules/@jest/fake-timers": { - "version": "30.3.0", - "dev": true, + "node_modules/@next/mdx": { + "version": "16.2.2", "license": "MIT", "dependencies": { - "@jest/types": "30.3.0", - "@sinonjs/fake-timers": "^15.0.0", - "@types/node": "*", - "jest-message-util": "30.3.0", - "jest-mock": "30.3.0", - "jest-util": "30.3.0" + "source-map": "^0.7.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "peerDependencies": { + "@mdx-js/loader": ">=0.15.0", + "@mdx-js/react": ">=0.15.0" + }, + "peerDependenciesMeta": { + "@mdx-js/loader": { + "optional": true + }, + "@mdx-js/react": { + "optional": true + } } }, - "node_modules/@jest/get-type": { - "version": "30.1.0", - "dev": true, + "node_modules/@next/swc-darwin-arm64": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.12.tgz", + "integrity": "sha512-0W1R0teHWJrqKX0FH20IzzIWAOuGtBxPGuObrxy1lE8hQvCFj49KE8a3WUg0D7sq6rn6zkM4c7YGUnhudBS6oA==", + "cpu": [ + "arm64" + ], "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 10" } }, - "node_modules/@jest/globals": { - "version": "30.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "30.3.0", - "@jest/expect": "30.3.0", - "@jest/types": "30.3.0", - "jest-mock": "30.3.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } + "node_modules/@next/swc-darwin-x64": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.12.tgz", + "integrity": "sha512-Hy5Ls099+aFUmOLmIgPfLqNi6iCwhL3uQCssz5rWk+5Nkc6TUKCE83DY5BbNylfm3+mfwcSFnLRfrZDJhVxdtw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@jest/pattern": { - "version": "30.0.1", - "dev": true, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.12.tgz", + "integrity": "sha512-+YqU2h1cQkHsGfvjAsrSmst8UIFBibBGm5x3Xgel8NLMiDQtNOM4sM2GOEMvG5YiOBNeN/Ykk8cQC2S0Xrqljg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], "license": "MIT", - "dependencies": { - "@types/node": "*", - "jest-regex-util": "30.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 10" } }, - "node_modules/@jest/reporters": { - "version": "30.3.0", - "dev": true, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.12.tgz", + "integrity": "sha512-0qjhiYBaKAqF63LA1ZWAAnKTzFUguAaZiRa5etMLGGPj/B6uEVjtIZldIzFEp3wHlB0koK6aTzqPtSdplTCjoA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], "license": "MIT", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "30.3.0", - "@jest/test-result": "30.3.0", - "@jest/transform": "30.3.0", - "@jest/types": "30.3.0", - "@jridgewell/trace-mapping": "^0.3.25", - "@types/node": "*", - "chalk": "^4.1.2", - "collect-v8-coverage": "^1.0.2", - "exit-x": "^0.2.2", - "glob": "^10.5.0", - "graceful-fs": "^4.2.11", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^5.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "30.3.0", - "jest-util": "30.3.0", - "jest-worker": "30.3.0", - "slash": "^3.0.0", - "string-length": "^4.0.2", - "v8-to-istanbul": "^9.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">= 10" } }, - "node_modules/@jest/reporters/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "16.2.12", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">= 10" } }, - "node_modules/@jest/reporters/node_modules/brace-expansion": { - "version": "2.1.4", - "dev": true, + "node_modules/@next/swc-linux-x64-musl": { + "version": "16.2.12", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@jest/reporters/node_modules/chalk": { - "version": "4.1.2", - "dev": true, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.12.tgz", + "integrity": "sha512-X6hzsOUJac/e7AWSbn9gQ9nzHld1xWP5iyjHpYWvud8pufB679O1xg4JDyKr8Xd69Jvd+kM2Der6uftiZCmjYA==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">= 10" } }, - "node_modules/@jest/reporters/node_modules/glob": { - "version": "10.5.0", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node_modules/@next/swc-win32-x64-msvc": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.12.tgz", + "integrity": "sha512-F6fakeHuFTLOPt0bslQJdf+xtT+WIP9DVn/m4y1w1mRnVPyh3D/cNvzlRkxM444xfm+IvvYNSOrKiA2CDJ0Uxw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@jest/reporters/node_modules/jackspeak": { - "version": "3.4.3", + "node_modules/@noble/ciphers": { + "version": "1.3.0", "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@jest/reporters/node_modules/lru-cache": { - "version": "10.4.3", - "dev": true, - "license": "ISC" - }, - "node_modules/@jest/reporters/node_modules/minimatch": { - "version": "9.0.9", + "node_modules/@noble/curves": { + "version": "1.9.7", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.2" + "@noble/hashes": "1.8.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "^14.21.3 || >=16" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@jest/reporters/node_modules/path-scurry": { - "version": "1.11.1", + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.8.0", "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.18" + "node": "^14.21.3 || >=16" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@jest/reporters/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, + "node_modules/@noble/hashes": { + "version": "2.3.0", "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@jest/schemas": { - "version": "30.0.5", - "dev": true, + "node_modules/@noble/secp256k1": { + "version": "2.3.0", "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.34.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@jest/snapshot-utils": { - "version": "30.3.0", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.3.0", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "natural-compare": "^1.4.0" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 8" } }, - "node_modules/@jest/snapshot-utils/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">= 8" } }, - "node_modules/@jest/snapshot-utils/node_modules/chalk": { - "version": "4.1.2", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">= 8" } }, - "node_modules/@jest/snapshot-utils/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=12.4.0" } }, - "node_modules/@jest/source-map": { - "version": "30.0.1", - "dev": true, + "node_modules/@octokit/auth-token": { + "version": "6.0.0", "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "callsites": "^3.1.0", - "graceful-fs": "^4.2.11" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 20" } }, - "node_modules/@jest/test-result": { - "version": "30.3.0", - "dev": true, + "node_modules/@octokit/core": { + "version": "7.0.6", "license": "MIT", "dependencies": { - "@jest/console": "30.3.0", - "@jest/types": "30.3.0", - "@types/istanbul-lib-coverage": "^2.0.6", - "collect-v8-coverage": "^1.0.2" + "@octokit/auth-token": "^6.0.0", + "@octokit/graphql": "^9.0.3", + "@octokit/request": "^10.0.6", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "before-after-hook": "^4.0.0", + "universal-user-agent": "^7.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 20" } }, - "node_modules/@jest/test-sequencer": { - "version": "30.3.0", - "dev": true, + "node_modules/@octokit/endpoint": { + "version": "11.0.2", "license": "MIT", "dependencies": { - "@jest/test-result": "30.3.0", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.3.0", - "slash": "^3.0.0" - }, + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.2" + }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 20" } }, - "node_modules/@jest/transform": { - "version": "30.3.0", - "dev": true, + "node_modules/@octokit/graphql": { + "version": "9.0.3", "license": "MIT", "dependencies": { - "@babel/core": "^7.27.4", - "@jest/types": "30.3.0", - "@jridgewell/trace-mapping": "^0.3.25", - "babel-plugin-istanbul": "^7.0.1", - "chalk": "^4.1.2", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.3.0", - "jest-regex-util": "30.0.1", - "jest-util": "30.3.0", - "pirates": "^4.0.7", - "slash": "^3.0.0", - "write-file-atomic": "^5.0.1" + "@octokit/request": "^10.0.6", + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 20" } }, - "node_modules/@jest/transform/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, + "node_modules/@octokit/openapi-types": { + "version": "27.0.0", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "14.0.0", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "@octokit/types": "^16.0.0" }, "engines": { - "node": ">=8" + "node": ">= 20" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "@octokit/core": ">=6" } }, - "node_modules/@jest/transform/node_modules/chalk": { - "version": "4.1.2", - "dev": true, + "node_modules/@octokit/plugin-request-log": { + "version": "6.0.0", "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": ">= 20" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "@octokit/core": ">=6" } }, - "node_modules/@jest/transform/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "17.0.0", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "@octokit/types": "^16.0.0" }, "engines": { - "node": ">=8" + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" } }, - "node_modules/@jest/types": { - "version": "30.3.0", - "dev": true, + "node_modules/@octokit/request": { + "version": "10.0.7", "license": "MIT", "dependencies": { - "@jest/pattern": "30.0.1", - "@jest/schemas": "30.0.5", - "@types/istanbul-lib-coverage": "^2.0.6", - "@types/istanbul-reports": "^3.0.4", - "@types/node": "*", - "@types/yargs": "^17.0.33", - "chalk": "^4.1.2" + "@octokit/endpoint": "^11.0.2", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "fast-content-type-parse": "^3.0.0", + "universal-user-agent": "^7.0.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 20" } }, - "node_modules/@jest/types/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, + "node_modules/@octokit/request-error": { + "version": "7.1.0", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "@octokit/types": "^16.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">= 20" } }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "dev": true, + "node_modules/@octokit/rest": { + "version": "22.0.1", "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@octokit/core": "^7.0.6", + "@octokit/plugin-paginate-rest": "^14.0.0", + "@octokit/plugin-request-log": "^6.0.0", + "@octokit/plugin-rest-endpoint-methods": "^17.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">= 20" } }, - "node_modules/@jest/types/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, + "node_modules/@octokit/types": { + "version": "16.0.0", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@octokit/openapi-types": "^27.0.0" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", + "node_modules/@orangecat/sdk": { + "resolved": "packages/sdk", + "link": true + }, + "node_modules/@oxc-project/types": { + "version": "0.147.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.147.0.tgz", + "integrity": "sha512-IJ3s6ltHLp45S0bh7phkX+gJO7A1Wuz2EaqpAhb8WjqDwbzMiWKHhyyT42tskaWjEYXtHtVCPpnBJVT9+dcRLg==", "dev": true, "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" + "funding": { + "url": "https://github.com/sponsors/Boshen" } }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", + "node_modules/@playwright/mcp": { + "version": "0.0.79", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "playwright": "1.63.0-alpha-2026-08-05", + "playwright-core": "1.63.0-alpha-2026-08-05" + }, + "bin": { + "playwright-mcp": "cli.js" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", + "node_modules/@playwright/mcp/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, + "hasInstallScript": true, "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.0.0" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", + "node_modules/@playwright/mcp/node_modules/playwright": { + "version": "1.63.0-alpha-2026-08-05", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.63.0-alpha-2026-08-05" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=20" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", + "node_modules/@playwright/mcp/node_modules/playwright-core": { + "version": "1.63.0-alpha-2026-08-05", "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@playwright/test": { + "version": "1.62.1", + "devOptional": true, + "license": "Apache-2.0", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "playwright": "1.62.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=20" } }, - "node_modules/@marsidev/react-turnstile": { - "version": "1.6.0", + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "dev": true, + "license": "MIT" + }, + "node_modules/@radix-ui/number": { + "version": "1.1.3", + "license": "MIT" + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.15", "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.10" + }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@mdx-js/loader": { - "version": "3.1.1", + "node_modules/@radix-ui/react-collection": { + "version": "1.1.15", "license": "MIT", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "source-map": "^0.7.0" + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-slot": "1.3.3" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.5", + "license": "MIT", "peerDependencies": { - "webpack": ">=5" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { - "webpack": { + "@types/react": { "optional": true } } }, - "node_modules/@mdx-js/mdx": { - "version": "3.1.1", + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdx": "^2.0.0", - "acorn": "^8.0.0", - "collapse-white-space": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "estree-util-scope": "^1.0.0", - "estree-walker": "^3.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "markdown-extensions": "^2.0.0", - "recma-build-jsx": "^1.0.0", - "recma-jsx": "^1.0.0", - "recma-stringify": "^1.0.0", - "rehype-recma": "^1.0.0", - "remark-mdx": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "source-map": "^0.7.0", - "unified": "^11.0.0", - "unist-util-position-from-estree": "^2.0.0", - "unist-util-stringify-position": "^4.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@mdx-js/react": { - "version": "3.1.1", + "node_modules/@radix-ui/react-context": { + "version": "1.2.2", "license": "MIT", - "dependencies": { - "@types/mdx": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, "peerDependencies": { - "@types/react": ">=16", - "react": ">=16" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.30.0", + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.23", "license": "MIT", "dependencies": { - "@hono/node-server": "^1.19.9 || ^2.0.5", - "ajv": "^8.17.1", - "ajv-formats": "^3.0.1", - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.5", - "eventsource": "^3.0.2", - "eventsource-parser": "^3.0.0", - "express": "^5.2.1", - "express-rate-limit": "^8.2.1", - "hono": "^4.11.4", - "jose": "^6.1.3", - "json-schema-typed": "^8.0.2", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.25 || ^4.0", - "zod-to-json-schema": "^3.25.1" - }, - "engines": { - "node": ">=18" + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-dismissable-layer": "1.1.19", + "@radix-ui/react-focus-guards": "1.1.6", + "@radix-ui/react-focus-scope": "1.1.16", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-portal": "1.1.17", + "@radix-ui/react-presence": "1.1.10", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-slot": "1.3.3", + "@radix-ui/react-use-controllable-state": "1.2.6", + "@radix-ui/react-use-layout-effect": "1.1.4", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" }, "peerDependencies": { - "@cfworker/json-schema": "^4.1.1", - "zod": "^3.25 || ^4.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { - "@cfworker/json-schema": { + "@types/react": { "optional": true }, - "zod": { - "optional": false + "@types/react-dom": { + "optional": true } } }, - "node_modules/@modelcontextprotocol/sdk/node_modules/ajv-formats": { - "version": "3.0.1", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/primitive": { + "version": "1.1.7", + "license": "MIT" + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.5", "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, "peerDependencies": { - "ajv": "^8.0.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { - "ajv": { + "@types/react": { "optional": true } } }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", - "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", - "dev": true, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.6", "license": "MIT", - "optional": true, "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-use-effect-event": "0.0.5", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@next/bundle-analyzer": { - "version": "16.3.2", - "dev": true, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.5", "license": "MIT", "dependencies": { - "webpack-bundle-analyzer": "4.10.1" + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@next/bundle-analyzer/node_modules/commander": { - "version": "7.2.0", - "dev": true, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.4", "license": "MIT", - "engines": { - "node": ">= 10" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@next/bundle-analyzer/node_modules/webpack-bundle-analyzer": { - "version": "4.10.1", - "dev": true, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.4", "license": "MIT", - "dependencies": { - "@discoveryjs/json-ext": "0.5.7", - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "commander": "^7.2.0", - "debounce": "^1.2.1", - "escape-string-regexp": "^4.0.0", - "gzip-size": "^6.0.0", - "html-escaper": "^2.0.2", - "is-plain-object": "^5.0.0", - "opener": "^1.5.2", - "picocolors": "^1.0.0", - "sirv": "^2.0.3", - "ws": "^7.3.1" - }, - "bin": { - "webpack-bundle-analyzer": "lib/bin/analyzer.js" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">= 10.13.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@next/bundle-analyzer/node_modules/ws": { - "version": "7.5.11", - "dev": true, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.19", "license": "MIT", - "engines": { - "node": ">=8.3.0" + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-callback-ref": "1.1.4", + "@radix-ui/react-use-effect-event": "0.0.5" }, "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { - "bufferutil": { + "@types/react": { "optional": true }, - "utf-8-validate": { + "@types/react-dom": { "optional": true } } }, - "node_modules/@next/env": { - "version": "16.2.12", + "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/primitive": { + "version": "1.1.7", "license": "MIT" }, - "node_modules/@next/eslint-plugin-next": { - "version": "16.3.1", - "dev": true, + "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.5", "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "4.9.1", - "fast-glob": "3.3.1" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@next/mdx": { - "version": "16.2.2", + "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.5", "license": "MIT", "dependencies": { - "source-map": "^0.7.0" + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { - "@mdx-js/loader": ">=0.15.0", - "@mdx-js/react": ">=0.15.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { - "@mdx-js/loader": { - "optional": true - }, - "@mdx-js/react": { + "@types/react": { "optional": true } } }, - "node_modules/@next/swc-darwin-arm64": { - "version": "16.2.12", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.12.tgz", - "integrity": "sha512-0W1R0teHWJrqKX0FH20IzzIWAOuGtBxPGuObrxy1lE8hQvCFj49KE8a3WUg0D7sq6rn6zkM4c7YGUnhudBS6oA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "16.2.12", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.12.tgz", - "integrity": "sha512-Hy5Ls099+aFUmOLmIgPfLqNi6iCwhL3uQCssz5rWk+5Nkc6TUKCE83DY5BbNylfm3+mfwcSFnLRfrZDJhVxdtw==", - "cpu": [ - "x64" - ], + "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.4", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "16.2.12", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.12.tgz", - "integrity": "sha512-+YqU2h1cQkHsGfvjAsrSmst8UIFBibBGm5x3Xgel8NLMiDQtNOM4sM2GOEMvG5YiOBNeN/Ykk8cQC2S0Xrqljg==", - "cpu": [ - "arm64" - ], - "libc": [ - "glibc" - ], + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.24", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-menu": "2.1.24", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-controllable-state": "1.2.6" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "16.2.12", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.12.tgz", - "integrity": "sha512-0qjhiYBaKAqF63LA1ZWAAnKTzFUguAaZiRa5etMLGGPj/B6uEVjtIZldIzFEp3wHlB0koK6aTzqPtSdplTCjoA==", - "cpu": [ - "arm64" - ], - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } + "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/primitive": { + "version": "1.1.7", + "license": "MIT" }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "16.2.12", - "cpu": [ - "x64" - ], - "libc": [ - "glibc" - ], + "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.5", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "16.2.12", - "cpu": [ - "x64" - ], - "libc": [ - "musl" - ], + "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.6", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-use-effect-event": "0.0.5", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "16.2.12", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.12.tgz", - "integrity": "sha512-X6hzsOUJac/e7AWSbn9gQ9nzHld1xWP5iyjHpYWvud8pufB679O1xg4JDyKr8Xd69Jvd+kM2Der6uftiZCmjYA==", - "cpu": [ - "arm64" - ], + "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.5", "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "16.2.12", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.12.tgz", - "integrity": "sha512-F6fakeHuFTLOPt0bslQJdf+xtT+WIP9DVn/m4y1w1mRnVPyh3D/cNvzlRkxM444xfm+IvvYNSOrKiA2CDJ0Uxw==", - "cpu": [ - "x64" - ], + "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.4", "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@noble/ciphers": { - "version": "1.3.0", - "dev": true, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.6", "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@noble/curves": { - "version": "1.9.7", - "dev": true, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.16", "license": "MIT", "dependencies": { - "@noble/hashes": "1.8.0" + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-callback-ref": "1.1.4" }, - "engines": { - "node": "^14.21.3 || >=16" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.8.0", - "dev": true, + "node_modules/@radix-ui/react-focus-scope/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.5", "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@noble/hashes": { - "version": "2.3.0", + "node_modules/@radix-ui/react-hover-card": { + "version": "1.1.23", "license": "MIT", - "engines": { - "node": ">= 20.19.0" + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-dismissable-layer": "1.1.19", + "@radix-ui/react-popper": "1.3.7", + "@radix-ui/react-portal": "1.1.17", + "@radix-ui/react-presence": "1.1.10", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-controllable-state": "1.2.6" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@noble/secp256k1": { - "version": "2.3.0", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } + "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/primitive": { + "version": "1.1.7", + "license": "MIT" }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, + "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.5", "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, + "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.6", "license": "MIT", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-use-effect-event": "0.0.5", + "@radix-ui/react-use-layout-effect": "1.1.4" }, - "engines": { - "node": ">= 8" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@nolyfill/is-core-module": { - "version": "1.0.39", - "dev": true, + "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.5", "license": "MIT", - "engines": { - "node": ">=12.4.0" + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@octokit/auth-token": { - "version": "6.0.0", + "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.4", "license": "MIT", - "engines": { - "node": ">= 20" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@octokit/core": { - "version": "7.0.6", + "node_modules/@radix-ui/react-id": { + "version": "1.1.4", "license": "MIT", "dependencies": { - "@octokit/auth-token": "^6.0.0", - "@octokit/graphql": "^9.0.3", - "@octokit/request": "^10.0.6", - "@octokit/request-error": "^7.0.2", - "@octokit/types": "^16.0.0", - "before-after-hook": "^4.0.0", - "universal-user-agent": "^7.0.0" + "@radix-ui/react-use-layout-effect": "1.1.4" }, - "engines": { - "node": ">= 20" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@octokit/endpoint": { - "version": "11.0.2", + "node_modules/@radix-ui/react-id/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.4", "license": "MIT", - "dependencies": { - "@octokit/types": "^16.0.0", - "universal-user-agent": "^7.0.2" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">= 20" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@octokit/graphql": { - "version": "9.0.3", + "node_modules/@radix-ui/react-label": { + "version": "2.1.15", "license": "MIT", "dependencies": { - "@octokit/request": "^10.0.6", - "@octokit/types": "^16.0.0", - "universal-user-agent": "^7.0.0" + "@radix-ui/react-primitive": "2.1.10" }, - "engines": { - "node": ">= 20" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@octokit/openapi-types": { - "version": "27.0.0", - "license": "MIT" - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "14.0.0", + "node_modules/@radix-ui/react-menu": { + "version": "2.1.24", "license": "MIT", "dependencies": { - "@octokit/types": "^16.0.0" - }, - "engines": { - "node": ">= 20" + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-collection": "1.1.15", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-direction": "1.1.4", + "@radix-ui/react-dismissable-layer": "1.1.19", + "@radix-ui/react-focus-guards": "1.1.6", + "@radix-ui/react-focus-scope": "1.1.16", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-popper": "1.3.7", + "@radix-ui/react-portal": "1.1.17", + "@radix-ui/react-presence": "1.1.10", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-roving-focus": "1.1.19", + "@radix-ui/react-slot": "1.3.3", + "@radix-ui/react-use-callback-ref": "1.1.4", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" }, "peerDependencies": { - "@octokit/core": ">=6" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@octokit/plugin-request-log": { - "version": "6.0.0", + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/primitive": { + "version": "1.1.7", + "license": "MIT" + }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.5", "license": "MIT", - "engines": { - "node": ">= 20" - }, "peerDependencies": { - "@octokit/core": ">=6" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "17.0.0", + "node_modules/@radix-ui/react-popper": { + "version": "1.3.7", "license": "MIT", "dependencies": { - "@octokit/types": "^16.0.0" - }, - "engines": { - "node": ">= 20" - }, - "peerDependencies": { - "@octokit/core": ">=6" - } - }, - "node_modules/@octokit/request": { - "version": "10.0.7", - "license": "MIT", - "dependencies": { - "@octokit/endpoint": "^11.0.2", - "@octokit/request-error": "^7.0.2", - "@octokit/types": "^16.0.0", - "fast-content-type-parse": "^3.0.0", - "universal-user-agent": "^7.0.2" + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.15", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-callback-ref": "1.1.4", + "@radix-ui/react-use-layout-effect": "1.1.4", + "@radix-ui/react-use-rect": "1.1.4", + "@radix-ui/react-use-size": "1.1.4", + "@radix-ui/rect": "1.1.3" }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/@octokit/request-error": { - "version": "7.1.0", - "license": "MIT", - "dependencies": { - "@octokit/types": "^16.0.0" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">= 20" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@octokit/rest": { - "version": "22.0.1", + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.5", "license": "MIT", - "dependencies": { - "@octokit/core": "^7.0.6", - "@octokit/plugin-paginate-rest": "^14.0.0", - "@octokit/plugin-request-log": "^6.0.0", - "@octokit/plugin-rest-endpoint-methods": "^17.0.0" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/@octokit/types": { - "version": "16.0.0", - "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^27.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@orangecat/sdk": { - "resolved": "packages/sdk", - "link": true - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "dev": true, + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.4", "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@playwright/mcp": { - "version": "0.0.79", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "playwright": "1.63.0-alpha-2026-08-05", - "playwright-core": "1.63.0-alpha-2026-08-05" - }, - "bin": { - "playwright-mcp": "cli.js" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=18" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@playwright/mcp/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-size": { + "version": "1.1.4", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/@playwright/mcp/node_modules/playwright": { - "version": "1.63.0-alpha-2026-08-05", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "playwright-core": "1.63.0-alpha-2026-08-05" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=20" - }, - "optionalDependencies": { - "fsevents": "2.3.2" - } - }, - "node_modules/@playwright/mcp/node_modules/playwright-core": { - "version": "1.63.0-alpha-2026-08-05", - "dev": true, - "license": "Apache-2.0", - "bin": { - "playwright-core": "cli.js" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/@playwright/test": { - "version": "1.62.1", - "devOptional": true, - "license": "Apache-2.0", "dependencies": { - "playwright": "1.62.1" + "@radix-ui/react-use-layout-effect": "1.1.4" }, - "bin": { - "playwright": "cli.js" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=20" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@polka/url": { - "version": "1.0.0-next.29", - "dev": true, - "license": "MIT" - }, - "node_modules/@radix-ui/number": { - "version": "1.1.3", - "license": "MIT" - }, - "node_modules/@radix-ui/react-arrow": { - "version": "1.1.15", + "node_modules/@radix-ui/react-portal": { + "version": "1.1.17", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.10" + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -3412,14 +3267,24 @@ } } }, - "node_modules/@radix-ui/react-collection": { - "version": "1.1.15", + "node_modules/@radix-ui/react-portal/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.4", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.10", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.5", - "@radix-ui/react-context": "1.2.2", - "@radix-ui/react-primitive": "2.1.10", - "@radix-ui/react-slot": "1.3.3" + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -3436,8 +3301,8 @@ } } }, - "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.5", + "node_modules/@radix-ui/react-presence/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.4", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -3449,51 +3314,64 @@ } } }, - "node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.2", + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.10", "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.3.3" + }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true + }, + "@types/react-dom": { + "optional": true } } }, - "node_modules/@radix-ui/react-context": { - "version": "1.2.2", + "node_modules/@radix-ui/react-progress": { + "version": "1.1.16", "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-primitive": "2.1.10" + }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true + }, + "@types/react-dom": { + "optional": true } } }, - "node_modules/@radix-ui/react-dialog": { - "version": "1.1.23", + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.19", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", - "@radix-ui/react-dismissable-layer": "1.1.19", - "@radix-ui/react-focus-guards": "1.1.6", - "@radix-ui/react-focus-scope": "1.1.16", + "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-id": "1.1.4", - "@radix-ui/react-portal": "1.1.17", - "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", - "@radix-ui/react-slot": "1.3.3", + "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-controllable-state": "1.2.6", - "@radix-ui/react-use-layout-effect": "1.1.4", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.7.2" + "@radix-ui/react-use-is-hydrated": "0.1.3", + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -3510,11 +3388,11 @@ } } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/primitive": { + "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/primitive": { "version": "1.1.7", "license": "MIT" }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-compose-refs": { + "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-compose-refs": { "version": "1.1.5", "license": "MIT", "peerDependencies": { @@ -3527,7 +3405,7 @@ } } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-controllable-state": { + "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-use-controllable-state": { "version": "1.2.6", "license": "MIT", "dependencies": { @@ -3545,7 +3423,7 @@ } } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-effect-event": { + "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-use-effect-event": { "version": "0.0.5", "license": "MIT", "dependencies": { @@ -3561,20 +3439,7 @@ } } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.4", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-direction": { + "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-use-layout-effect": { "version": "1.1.4", "license": "MIT", "peerDependencies": { @@ -3587,15 +3452,32 @@ } } }, - "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.19", + "node_modules/@radix-ui/react-select": { + "version": "2.3.7", "license": "MIT", "dependencies": { + "@radix-ui/number": "1.1.3", "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-direction": "1.1.4", + "@radix-ui/react-dismissable-layer": "1.1.19", + "@radix-ui/react-focus-guards": "1.1.6", + "@radix-ui/react-focus-scope": "1.1.16", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-popper": "1.3.7", + "@radix-ui/react-portal": "1.1.17", + "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-callback-ref": "1.1.4", - "@radix-ui/react-use-effect-event": "0.0.5" + "@radix-ui/react-use-controllable-state": "1.2.6", + "@radix-ui/react-use-layout-effect": "1.1.4", + "@radix-ui/react-use-previous": "1.1.4", + "@radix-ui/react-visually-hidden": "1.2.11", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", @@ -3612,11 +3494,11 @@ } } }, - "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/primitive": { + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/primitive": { "version": "1.1.7", "license": "MIT" }, - "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-compose-refs": { + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-compose-refs": { "version": "1.1.5", "license": "MIT", "peerDependencies": { @@ -3629,7 +3511,25 @@ } } }, - "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-use-effect-event": { + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.6", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-use-effect-event": "0.0.5", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-use-effect-event": { "version": "0.0.5", "license": "MIT", "dependencies": { @@ -3645,7 +3545,7 @@ } } }, - "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-use-layout-effect": { + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-use-layout-effect": { "version": "1.1.4", "license": "MIT", "peerDependencies": { @@ -3658,17 +3558,26 @@ } } }, - "node_modules/@radix-ui/react-dropdown-menu": { - "version": "2.1.24", + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-use-previous": { + "version": "1.1.4", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.15.tgz", + "integrity": "sha512-jOLO4lssEzWpoDu7G+Ze4VjwMRUBt291pnZD0gmalREZipnTX3wadQo7Fy48GCTfe14/YRN6rw/rOJqrE85Wxw==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.5", - "@radix-ui/react-context": "1.2.2", - "@radix-ui/react-id": "1.1.4", - "@radix-ui/react-menu": "2.1.24", - "@radix-ui/react-primitive": "2.1.10", - "@radix-ui/react-use-controllable-state": "1.2.6" + "@radix-ui/react-primitive": "2.1.10" }, "peerDependencies": { "@types/react": "*", @@ -3685,13 +3594,12 @@ } } }, - "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/primitive": { - "version": "1.1.7", - "license": "MIT" - }, - "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.5", + "node_modules/@radix-ui/react-slot": { + "version": "1.3.3", "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.5" + }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -3702,14 +3610,9 @@ } } }, - "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.6", + "node_modules/@radix-ui/react-slot/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.5", "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-use-effect-event": "0.0.5", - "@radix-ui/react-use-layout-effect": "1.1.4" - }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -3720,24 +3623,38 @@ } } }, - "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-use-effect-event": { - "version": "0.0.5", + "node_modules/@radix-ui/react-switch": { + "version": "1.3.7", "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.4" + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-controllable-state": "1.2.6", + "@radix-ui/react-use-size": "1.1.4" }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true + }, + "@types/react-dom": { + "optional": true } } }, - "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.4", + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/primitive": { + "version": "1.1.7", + "license": "MIT" + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.5", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -3749,9 +3666,14 @@ } } }, - "node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.6", + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.6", "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-use-effect-event": "0.0.5", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -3762,32 +3684,41 @@ } } }, - "node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.16", + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.5", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.5", - "@radix-ui/react-primitive": "2.1.10", - "@radix-ui/react-use-callback-ref": "1.1.4" + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true - }, - "@types/react-dom": { + } + } + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.4", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { "optional": true } } }, - "node_modules/@radix-ui/react-focus-scope/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.5", + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-use-size": { + "version": "1.1.4", "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.4" + }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -3798,18 +3729,17 @@ } } }, - "node_modules/@radix-ui/react-hover-card": { - "version": "1.1.23", + "node_modules/@radix-ui/react-tabs": { + "version": "1.1.21", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", - "@radix-ui/react-dismissable-layer": "1.1.19", - "@radix-ui/react-popper": "1.3.7", - "@radix-ui/react-portal": "1.1.17", + "@radix-ui/react-direction": "1.1.4", + "@radix-ui/react-id": "1.1.4", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { @@ -3827,13 +3757,18 @@ } } }, - "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/primitive": { + "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/primitive": { "version": "1.1.7", "license": "MIT" }, - "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.5", + "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.6", "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.7", + "@radix-ui/react-use-effect-event": "0.0.5", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -3844,12 +3779,10 @@ } } }, - "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.6", + "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.5", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-use-effect-event": "0.0.5", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { @@ -3862,12 +3795,9 @@ } } }, - "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-use-effect-event": { - "version": "0.0.5", + "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.4", "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.4" - }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -3878,7 +3808,7 @@ } } }, - "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-use-layout-effect": { + "node_modules/@radix-ui/react-use-callback-ref": { "version": "1.1.4", "license": "MIT", "peerDependencies": { @@ -3891,12 +3821,9 @@ } } }, - "node_modules/@radix-ui/react-id": { - "version": "1.1.4", + "node_modules/@radix-ui/react-use-is-hydrated": { + "version": "0.1.3", "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.4" - }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -3907,9 +3834,12 @@ } } }, - "node_modules/@radix-ui/react-id/node_modules/@radix-ui/react-use-layout-effect": { + "node_modules/@radix-ui/react-use-rect": { "version": "1.1.4", "license": "MIT", + "dependencies": { + "@radix-ui/rect": "1.1.3" + }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -3920,8 +3850,8 @@ } } }, - "node_modules/@radix-ui/react-label": { - "version": "2.1.15", + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.11", "license": "MIT", "dependencies": { "@radix-ui/react-primitive": "2.1.10" @@ -3941,2888 +3871,462 @@ } } }, - "node_modules/@radix-ui/react-menu": { - "version": "2.1.24", + "node_modules/@radix-ui/rect": { + "version": "1.1.3", + "license": "MIT" + }, + "node_modules/@rolldown/binding-android-arm-eabi": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.6.tgz", + "integrity": "sha512-b+jTcARdTiFLI6jB4a5XjTm0RWd6KcRfQj/I2356fxUZemiho9zQLxo0RtCuMDAyKcLo6cEltkgbQp6d1+sjjQ==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-collection": "1.1.15", - "@radix-ui/react-compose-refs": "1.1.5", - "@radix-ui/react-context": "1.2.2", - "@radix-ui/react-direction": "1.1.4", - "@radix-ui/react-dismissable-layer": "1.1.19", - "@radix-ui/react-focus-guards": "1.1.6", - "@radix-ui/react-focus-scope": "1.1.16", - "@radix-ui/react-id": "1.1.4", - "@radix-ui/react-popper": "1.3.7", - "@radix-ui/react-portal": "1.1.17", - "@radix-ui/react-presence": "1.1.10", - "@radix-ui/react-primitive": "2.1.10", - "@radix-ui/react-roving-focus": "1.1.19", - "@radix-ui/react-slot": "1.3.3", - "@radix-ui/react-use-callback-ref": "1.1.4", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.7.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/primitive": { - "version": "1.1.7", - "license": "MIT" - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.5", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popper": { - "version": "1.3.7", - "license": "MIT", - "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.15", - "@radix-ui/react-compose-refs": "1.1.5", - "@radix-ui/react-context": "1.2.2", - "@radix-ui/react-primitive": "2.1.10", - "@radix-ui/react-use-callback-ref": "1.1.4", - "@radix-ui/react-use-layout-effect": "1.1.4", - "@radix-ui/react-use-rect": "1.1.4", - "@radix-ui/react-use-size": "1.1.4", - "@radix-ui/rect": "1.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.5", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.4", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-size": { - "version": "1.1.4", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-portal": { - "version": "1.1.17", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.10", - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-portal/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.4", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-presence": { - "version": "1.1.10", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-presence/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.4", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-primitive": { - "version": "2.1.10", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.3.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-progress": { - "version": "1.1.16", - "license": "MIT", - "dependencies": { - "@radix-ui/react-context": "1.2.2", - "@radix-ui/react-primitive": "2.1.10" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.19", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-collection": "1.1.15", - "@radix-ui/react-compose-refs": "1.1.5", - "@radix-ui/react-context": "1.2.2", - "@radix-ui/react-direction": "1.1.4", - "@radix-ui/react-id": "1.1.4", - "@radix-ui/react-primitive": "2.1.10", - "@radix-ui/react-use-callback-ref": "1.1.4", - "@radix-ui/react-use-controllable-state": "1.2.6", - "@radix-ui/react-use-is-hydrated": "0.1.3", - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/primitive": { - "version": "1.1.7", - "license": "MIT" - }, - "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.5", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.6", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-use-effect-event": "0.0.5", - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-use-effect-event": { - "version": "0.0.5", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.4", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select": { - "version": "2.3.7", - "license": "MIT", - "dependencies": { - "@radix-ui/number": "1.1.3", - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-collection": "1.1.15", - "@radix-ui/react-compose-refs": "1.1.5", - "@radix-ui/react-context": "1.2.2", - "@radix-ui/react-direction": "1.1.4", - "@radix-ui/react-dismissable-layer": "1.1.19", - "@radix-ui/react-focus-guards": "1.1.6", - "@radix-ui/react-focus-scope": "1.1.16", - "@radix-ui/react-id": "1.1.4", - "@radix-ui/react-popper": "1.3.7", - "@radix-ui/react-portal": "1.1.17", - "@radix-ui/react-presence": "1.1.10", - "@radix-ui/react-primitive": "2.1.10", - "@radix-ui/react-slot": "1.3.3", - "@radix-ui/react-use-callback-ref": "1.1.4", - "@radix-ui/react-use-controllable-state": "1.2.6", - "@radix-ui/react-use-layout-effect": "1.1.4", - "@radix-ui/react-use-previous": "1.1.4", - "@radix-ui/react-visually-hidden": "1.2.11", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.7.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/primitive": { - "version": "1.1.7", - "license": "MIT" - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.5", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.6", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-use-effect-event": "0.0.5", - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-use-effect-event": { - "version": "0.0.5", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.4", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-use-previous": { - "version": "1.1.4", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-separator": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.15.tgz", - "integrity": "sha512-jOLO4lssEzWpoDu7G+Ze4VjwMRUBt291pnZD0gmalREZipnTX3wadQo7Fy48GCTfe14/YRN6rw/rOJqrE85Wxw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.10" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-slot": { - "version": "1.3.3", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.5" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-slot/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.5", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-switch": { - "version": "1.3.7", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.5", - "@radix-ui/react-context": "1.2.2", - "@radix-ui/react-primitive": "2.1.10", - "@radix-ui/react-use-controllable-state": "1.2.6", - "@radix-ui/react-use-size": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/primitive": { - "version": "1.1.7", - "license": "MIT" - }, - "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.5", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.6", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-use-effect-event": "0.0.5", - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-use-effect-event": { - "version": "0.0.5", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.4", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-use-size": { - "version": "1.1.4", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tabs": { - "version": "1.1.21", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-context": "1.2.2", - "@radix-ui/react-direction": "1.1.4", - "@radix-ui/react-id": "1.1.4", - "@radix-ui/react-presence": "1.1.10", - "@radix-ui/react-primitive": "2.1.10", - "@radix-ui/react-roving-focus": "1.1.19", - "@radix-ui/react-use-controllable-state": "1.2.6" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/primitive": { - "version": "1.1.7", - "license": "MIT" - }, - "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.6", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-use-effect-event": "0.0.5", - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-use-effect-event": { - "version": "0.0.5", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.4", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.4", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-is-hydrated": { - "version": "0.1.3", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-rect": { - "version": "1.1.4", - "license": "MIT", - "dependencies": { - "@radix-ui/rect": "1.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.2.11", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.10" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/rect": { - "version": "1.1.3", - "license": "MIT" - }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@scure/base": { - "version": "2.2.0", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "@noble/curves": "2.0.1", - "@noble/hashes": "2.0.1", - "@scure/base": "2.0.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32/node_modules/@noble/curves": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "@noble/hashes": "2.0.1" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "2.0.1", - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32/node_modules/@scure/base": { - "version": "2.0.0", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "@noble/hashes": "2.0.1", - "@scure/base": "2.0.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39/node_modules/@noble/hashes": { - "version": "2.0.1", - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39/node_modules/@scure/base": { - "version": "2.0.0", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@sec-ant/readable-stream": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@sinclair/typebox": { - "version": "0.34.49", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@sindresorhus/base62": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "15.3.2", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1" - } - }, - "node_modules/@stablelib/base64": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/@standard-schema/utils": { - "version": "0.3.0", - "license": "MIT" - }, - "node_modules/@supabase/auth-js": { - "version": "2.112.2", - "license": "MIT", - "dependencies": { - "tslib": "2.8.1" - }, - "engines": { - "node": ">=22.0.0" - } - }, - "node_modules/@supabase/cli-darwin-arm64": { - "version": "2.115.0", - "resolved": "https://registry.npmjs.org/@supabase/cli-darwin-arm64/-/cli-darwin-arm64-2.115.0.tgz", - "integrity": "sha512-yUNw1KG+fyuBqBGvFT8ASC7aAkFkx2Kx+qPjUTW50ttiKKgg8D/eMSCoSjQuaAbL0vafw98bHEZ2dAfdyYyXMA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@supabase/cli-darwin-x64": { - "version": "2.115.0", - "resolved": "https://registry.npmjs.org/@supabase/cli-darwin-x64/-/cli-darwin-x64-2.115.0.tgz", - "integrity": "sha512-e4bbWADYcjSjXgSSErreoqyEeEjrFQunxCYummUoiGdVanck/itAIFwhtRykKpBtoKqCYh4CFxUiDxOFMBdNHQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@supabase/cli-linux-arm64": { - "version": "2.115.0", - "resolved": "https://registry.npmjs.org/@supabase/cli-linux-arm64/-/cli-linux-arm64-2.115.0.tgz", - "integrity": "sha512-JBcnnFuVekMR9+EOCcup1QihW+CHMBWcL/+N1Uz4HB6leX8d894VQ+sX0pFgbXLqnpGcc35IiXKwjLz4FCb8Dw==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@supabase/cli-linux-arm64-musl": { - "version": "2.115.0", - "resolved": "https://registry.npmjs.org/@supabase/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.115.0.tgz", - "integrity": "sha512-2OCzD4qZx8RFbW2vfOlXpup+1UnVqSauUsSGH4mKiUIveMD/UyMI6Md8CLKLszwV2XwM+6bZG6w7d7Ems9vxCQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@supabase/cli-linux-x64": { - "version": "2.115.0", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@supabase/cli-linux-x64-musl": { - "version": "2.115.0", - "resolved": "https://registry.npmjs.org/@supabase/cli-linux-x64-musl/-/cli-linux-x64-musl-2.115.0.tgz", - "integrity": "sha512-t36QEEQxy0AsOn0rr1L8aEzZKYS+kRH4fvYr5KdB+rHA1x39A1dUeOCTqCucCr0V5oQ3+odJLlO6tinNczHKMQ==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@supabase/cli-windows-arm64": { - "version": "2.115.0", - "resolved": "https://registry.npmjs.org/@supabase/cli-windows-arm64/-/cli-windows-arm64-2.115.0.tgz", - "integrity": "sha512-MkYbWrNZXpWZxwglVaTexj+w6EWYUi34c7Y9SRGbcQBC/infteM/8zhVVRUmO3ltSEqnJCacHowLPISXIF6g/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@supabase/cli-windows-x64": { - "version": "2.115.0", - "resolved": "https://registry.npmjs.org/@supabase/cli-windows-x64/-/cli-windows-x64-2.115.0.tgz", - "integrity": "sha512-jRXsJjbw/h0ssSpFQeClTTO2wtMw0YYS1yMzN2f/px4DehigBZNxSFB4thOtzmIJoisInm1gYV5pQJZla1Ytpw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@supabase/functions-js": { - "version": "2.112.2", - "license": "MIT", - "dependencies": { - "tslib": "2.8.1" - }, - "engines": { - "node": ">=22.0.0" - } - }, - "node_modules/@supabase/phoenix": { - "version": "0.4.5", - "license": "MIT" - }, - "node_modules/@supabase/postgrest-js": { - "version": "2.112.2", - "license": "MIT", - "dependencies": { - "tslib": "2.8.1" - }, - "engines": { - "node": ">=22.0.0" - } - }, - "node_modules/@supabase/realtime-js": { - "version": "2.112.2", - "license": "MIT", - "dependencies": { - "@supabase/phoenix": "0.4.5", - "tslib": "2.8.1" - }, - "engines": { - "node": ">=22.0.0" - } - }, - "node_modules/@supabase/ssr": { - "version": "0.12.4", - "license": "MIT", - "dependencies": { - "cookie": "^1.0.2" - }, - "peerDependencies": { - "@supabase/supabase-js": "^2.111.0" - } - }, - "node_modules/@supabase/storage-js": { - "version": "2.112.2", - "license": "MIT", - "dependencies": { - "iceberg-js": "^0.8.1", - "tslib": "2.8.1" - }, - "engines": { - "node": ">=22.0.0" - } - }, - "node_modules/@supabase/supabase-js": { - "version": "2.112.2", - "license": "MIT", - "dependencies": { - "@supabase/auth-js": "2.112.2", - "@supabase/functions-js": "2.112.2", - "@supabase/postgrest-js": "2.112.2", - "@supabase/realtime-js": "2.112.2", - "@supabase/storage-js": "2.112.2" - }, - "engines": { - "node": ">=22.0.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - } - } - }, - "node_modules/@swc/core": { - "version": "1.16.1", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.28" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/swc" - }, - "optionalDependencies": { - "@swc/core-darwin-arm64": "1.16.1", - "@swc/core-darwin-x64": "1.16.1", - "@swc/core-linux-arm-gnueabihf": "1.16.1", - "@swc/core-linux-arm64-gnu": "1.16.1", - "@swc/core-linux-arm64-musl": "1.16.1", - "@swc/core-linux-ppc64-gnu": "1.16.1", - "@swc/core-linux-s390x-gnu": "1.16.1", - "@swc/core-linux-x64-gnu": "1.16.1", - "@swc/core-linux-x64-musl": "1.16.1", - "@swc/core-win32-arm64-msvc": "1.16.1", - "@swc/core-win32-ia32-msvc": "1.16.1", - "@swc/core-win32-x64-msvc": "1.16.1" - }, - "peerDependencies": { - "@swc/helpers": ">=0.5.17" - }, - "peerDependenciesMeta": { - "@swc/helpers": { - "optional": true - } - } - }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.16.1.tgz", - "integrity": "sha512-zlJblJ8ncErD43lKdxjbUaUskJQf+LxiPXYcWXD8/8ZMV+7uuAT+CwjciLXpyZBd5Pq/S726bMpeeAwSeL1hhg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.16.1.tgz", - "integrity": "sha512-IN0BmPWb0YAh/17mmlWB/HDBtTw2MfuW4hulf/tQAgTQBRH17l+z499bNJLK6LizSjqs0P7V+jU38Zj+vJC1DA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.16.1.tgz", - "integrity": "sha512-EYgrx2YOCQ2Twz2S793kqNjPkpvYVUPzzR95bIb7by+VQcyaai4lZZ2iz/tZvcFVKSNcN3/JTKwx+aBn2ZL52A==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.16.1.tgz", - "integrity": "sha512-moyKm0YZlHdHohzm1YwgAyesqnE853rO0REMfJLFAova51wF9BNi+3ZW2PeS7Vqvn6HeJuepLpAHbBdZctxpHA==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.16.1.tgz", - "integrity": "sha512-kKGBO9wdapiSzuf5ZzZ2fYtlu1BNSYtIIUxvH1ir/gcelTOREEHGDCLTDFx/2Knf878nU11A40z7LxwasEFxqA==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-ppc64-gnu": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/@swc/core-linux-ppc64-gnu/-/core-linux-ppc64-gnu-1.16.1.tgz", - "integrity": "sha512-nZ6qahtLxC3PM54cWOQZHxt4lTCF/3J4LIoWWzz6v7A+rLs8Dx54anYQf7mH3eIi8KlNpgKci/ie8ZSqFN8O7A==", - "cpu": [ - "ppc64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-s390x-gnu": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/@swc/core-linux-s390x-gnu/-/core-linux-s390x-gnu-1.16.1.tgz", - "integrity": "sha512-4ji5PNzhYq193Z4/4xUaSoNJza6iCkDJSzhetrbB6KOYxsr+kxtQr8ePWhMJUiMt6JUWtXaZ1PYT8FhtED+nGA==", - "cpu": [ - "s390x" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.16.1", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.16.1.tgz", - "integrity": "sha512-r9oV1mwxxsIGcLV1IQ/tw76MW3doatKze1QFWuC+a7QqJUkhY/bKTSVk6NpKKUGm2LDsE33Va8VqSClfA7vSiQ==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.16.1.tgz", - "integrity": "sha512-6huNRessoBLxWEqBm5zJXyCQ27TO7anvkdiuQ5MDO4CJni0nOXEqKtV9RllQ2TdyENKKsUMXVnIfW2hIXx/R5Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.16.1.tgz", - "integrity": "sha512-OVKJFUzphrGmsh+BGtcZDesx0YryV7/Yvy5XGgTqnrZfjnyfcr5uaqYQugCckdIlupc5Vs3XtDjRAj12z4ZPlw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.16.1.tgz", - "integrity": "sha512-Bt+VIhWYCGk4urklnkkteLUOeLv1VxigwTCeB/xC6rBZxY6IIKdDwCJf6on3E3SUGsIqmQS6QqtuJQc1VxF4Aw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/@swc/types": { - "version": "0.1.28", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@swc/counter": "^0.1.3" - } - }, - "node_modules/@tailwindcss/node": { - "version": "4.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.5", - "enhanced-resolve": "^5.24.1", - "jiti": "^2.7.0", - "lightningcss": "1.32.0", - "magic-string": "^0.30.21", - "source-map-js": "^1.2.1", - "tailwindcss": "4.3.3" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.3.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.3.3", - "@tailwindcss/oxide-darwin-arm64": "4.3.3", - "@tailwindcss/oxide-darwin-x64": "4.3.3", - "@tailwindcss/oxide-freebsd-x64": "4.3.3", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", - "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", - "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", - "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", - "@tailwindcss/oxide-linux-x64-musl": "4.3.3", - "@tailwindcss/oxide-wasm32-wasi": "4.3.3", - "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", - "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", - "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", - "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", - "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", - "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", - "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", - "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", - "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.3.3", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", - "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", - "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.11.1", - "@emnapi/runtime": "^1.11.1", - "@emnapi/wasi-threads": "^1.2.2", - "@napi-rs/wasm-runtime": "^1.1.4", - "@tybys/wasm-util": "^0.10.2", - "tslib": "^2.8.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { - "version": "1.11.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.2", - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { - "version": "1.11.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { - "version": "1.2.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { - "version": "0.10.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { - "version": "2.8.1", - "dev": true, - "inBundle": true, - "license": "0BSD", - "optional": true - }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", - "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", - "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/postcss": { - "version": "4.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.3.3", - "@tailwindcss/oxide": "4.3.3", - "postcss": "^8.5.16", - "tailwindcss": "4.3.3" - } - }, - "node_modules/@tanstack/query-core": { - "version": "5.102.8", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.102.8.tgz", - "integrity": "sha512-ZNjkJ33CqvPNec/6lZBnHqLc3EVGPZ9ySLhYahU9TcuRFdmwXewuj0c4hwSWcGHqEUwcSrKeZ+oGcvPBqXcQcg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tanstack/react-query": { - "version": "5.102.8", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.102.8.tgz", - "integrity": "sha512-TYBea4OuXWD7MhaSHq069TWbFe7rcwWN6kzT7JF0OKi1K6c1gTv2IzD6A6ExJsCMozdkqBWeuIUZmu4KQg0O5A==", - "license": "MIT", - "dependencies": { - "@tanstack/query-core": "5.102.8" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^18 || ^19" - } - }, - "node_modules/@testing-library/dom": { - "version": "10.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.3.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "picocolors": "1.1.1", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@testing-library/jest-dom": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@adobe/css-tools": "^4.4.0", - "aria-query": "^5.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.6.3", - "picocolors": "^1.1.1", - "redent": "^3.0.0" - }, - "engines": { - "node": ">=22", - "npm": ">=6", - "yarn": ">=1" - }, - "peerDependencies": { - "@testing-library/dom": ">=10 <11" - } - }, - "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { - "version": "0.6.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@testing-library/react": { - "version": "16.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.12.5" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@testing-library/dom": "^10.0.0", - "@types/react": "^18.0.0 || ^19.0.0", - "@types/react-dom": "^18.0.0 || ^19.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@testing-library/user-event": { - "version": "14.6.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12", - "npm": ">=6" - }, - "peerDependencies": { - "@testing-library/dom": ">=7.21.4" - } - }, - "node_modules/@ts-morph/common": { - "version": "0.27.0", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-glob": "^3.3.3", - "minimatch": "^10.0.1", - "path-browserify": "^1.0.1" - } - }, - "node_modules/@ts-morph/common/node_modules/fast-glob": { - "version": "3.3.3", - "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/@ts-morph/common/node_modules/glob-parent": { - "version": "5.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", - "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "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", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/dompurify": { - "version": "3.2.0", - "deprecated": "This is a stub types definition. dompurify provides its own type definitions, so you do not need this installed.", - "license": "MIT", - "dependencies": { - "dompurify": "*" - } - }, - "node_modules/@types/esrecurse": { - "version": "4.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.9", - "license": "MIT" - }, - "node_modules/@types/estree-jsx": { - "version": "1.0.5", - "license": "MIT", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "30.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "expect": "^30.0.0", - "pretty-format": "^30.0.0" - } - }, - "node_modules/@types/jest/node_modules/pretty-format": { - "version": "30.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@types/jest/node_modules/react-is": { - "version": "18.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/jsdom": { - "version": "21.1.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/lodash": { - "version": "4.17.25", - "license": "MIT" - }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/mdx": { - "version": "2.0.14", - "license": "MIT" - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "26.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~8.3.0" - } - }, - "node_modules/@types/react": { - "version": "19.2.18", - "license": "MIT", - "dependencies": { - "csstype": "^3.2.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.2.4", - "license": "MIT", - "peerDependencies": { - "@types/react": "^19.2.0" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "license": "MIT", - "optional": true - }, - "node_modules/@types/unist": { - "version": "3.0.3", - "license": "MIT" - }, - "node_modules/@types/validate-npm-package-name": { - "version": "4.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/yargs": { - "version": "17.0.35", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.67.0", - "@typescript-eslint/type-utils": "8.67.0", - "@typescript-eslint/utils": "8.67.0", - "@typescript-eslint/visitor-keys": "8.67.0", - "ignore": "^7.0.5", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.5.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.67.0", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/project-service": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.67.0", - "@typescript-eslint/types": "^8.67.0", - "debug": "^4.4.3" - }, - "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 <6.1.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/visitor-keys": "8.67.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/eslint-plugin/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "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 <6.1.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "8.67.0", - "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/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.67.0", - "@typescript-eslint/tsconfig-utils": "8.67.0", - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/visitor-keys": "8.67.0", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.5.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 <6.1.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.67.0", - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/typescript-estree": "8.67.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 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.67.0", - "eslint-visitor-keys": "^5.0.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/eslint-plugin/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.67.0", - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/typescript-estree": "8.67.0", - "@typescript-eslint/visitor-keys": "8.67.0", - "debug": "^4.4.3" - }, - "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 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/project-service": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.67.0", - "@typescript-eslint/types": "^8.67.0", - "debug": "^4.4.3" - }, - "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 <6.1.0" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/visitor-keys": "8.67.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/parser/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "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 <6.1.0" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "8.67.0", - "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/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.67.0", - "@typescript-eslint/tsconfig-utils": "8.67.0", - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/visitor-keys": "8.67.0", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.5.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 <6.1.0" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.67.0", - "eslint-visitor-keys": "^5.0.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/parser/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.65.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.65.0", - "@typescript-eslint/types": "^8.65.0", - "debug": "^4.4.3" - }, - "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 <6.1.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.65.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/visitor-keys": "8.65.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/tsconfig-utils": { - "version": "8.65.0", - "dev": true, - "license": "MIT", - "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 <6.1.0" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/typescript-estree": "8.67.0", - "@typescript-eslint/utils": "8.67.0", - "debug": "^4.4.3", - "ts-api-utils": "^2.5.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 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/project-service": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.67.0", - "@typescript-eslint/types": "^8.67.0", - "debug": "^4.4.3" - }, - "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 <6.1.0" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/visitor-keys": "8.67.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/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "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 <6.1.0" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "8.67.0", - "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/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.67.0", - "@typescript-eslint/tsconfig-utils": "8.67.0", - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/visitor-keys": "8.67.0", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.5.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 <6.1.0" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "8.67.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.67.0", - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/typescript-estree": "8.67.0" - }, + "optional": true, + "os": [ + "android" + ], "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 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.67.0", + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.6.tgz", + "integrity": "sha512-lkWU8ZJaRk9q3CIEY1Tc7vIFALp3Xw5NfGJo2hQg5oIqNgxWi1zI+IiDEK3r70BF5Dzol1tcXsnzsRc8NLhG+Q==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.67.0", - "eslint-visitor-keys": "^5.0.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/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "dev": true, - "license": "Apache-2.0", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript-eslint/types": { - "version": "8.65.0", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.6.tgz", + "integrity": "sha512-dgR56NYnvAszm7Ob1B2/Vn0e8bUQYZH2UjVaMMtMVOCKFSfjhfLmuA/9+O+F+ajUdG6B/bSssrKW6JJYASa8jA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.65.0", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.6.tgz", + "integrity": "sha512-vpVxFvUCFioJqug7OTvqptkc4yb8UX0AwfDmJpaR/0sWz+BUmqSVAf7c8JkUgnN8YLspb4a/N6NhTyMAmdyQ7Q==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.65.0", - "@typescript-eslint/tsconfig-utils": "8.65.0", - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/visitor-keys": "8.65.0", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.5.0" - }, + "optional": true, + "os": [ + "darwin" + ], "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 <6.1.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript-eslint/utils": { - "version": "8.65.0", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.6.tgz", + "integrity": "sha512-h1wG6Y6K3JlRswxsI64qQJqBAy4vrLuHgRbc8CZMGSWTOFRY6ghMApM1NKzB2I0n5xV1fjkE18SuVl2QpLeNpA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.65.0", - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/typescript-estree": "8.65.0" - }, + "optional": true, + "os": [ + "freebsd" + ], "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 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.65.0", + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.6.tgz", + "integrity": "sha512-tbCiqub0q2MVWJKgF5PoAlNWCtQydiOYSLIkd8sByqK/6MMYLJRcSXSYodqYtd0O+Fw7QaVmKKlS4oL94YRZ0w==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.65.0", - "eslint-visitor-keys": "^5.0.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/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "dev": true, - "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "license": "ISC" - }, - "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", - "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.6.tgz", + "integrity": "sha512-oxK9+baEBPhZG5HB4URY+uU04zJWeZlH6Tb9rB5DK4DF9XR1uXNLXt5Q5ZsugTKayNCNLhkcwz/ye74hRI98dg==", "cpu": [ - "arm" + "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ - "android" - ] - }, - "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", - "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.6.tgz", + "integrity": "sha512-muWCk27FVBEZtv0MsK8gnfSmgczA8KQ0uRVJbTABKhkRfQc38aUrcb7fhi3BNiyseFmgcRsoMfQsSNJ+DbZdSw==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ - "android" - ] + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", - "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.6.tgz", + "integrity": "sha512-eWDoSfU7Co2qj3vgB3Dt4lj1mG6CoWbcJQkRMP3XJplyCMtuaq3LHvPFjS9QIPvMGWVadJC04Xiy0IdcVPtnwQ==", "cpu": [ - "arm64" + "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ - "darwin" - ] + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", - "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.6.tgz", + "integrity": "sha512-2bWNjRSIayvupRKxXUY2tWG9fYdoUlTqWywHRvE8Eq3GvuQ+f2HeIkve697fIt+IQs/PV8yFsdWuhp1aJ1PdnA==", "cpu": [ - "x64" + "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ - "darwin" - ] + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", - "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.6.tgz", + "integrity": "sha512-KekI0gS0wLxe1UBSQSjenBVwou/JkcQPDzBPICGZjxUv9k3RteHDPBQaiOicZUFKRIH2wKEimGwVpnJsbPzu7w==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ - "freebsd" - ] + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", - "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.6.tgz", + "integrity": "sha512-TvtPnfVr+HtyGiDmPK4VWmlNm7QhNNAcK5Q9A7aOXsI8545yCyaoMaicXrFZ72JzeYjaUVk7yT243zT0jzjFKQ==", "cpu": [ - "arm" + "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", - "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.6.tgz", + "integrity": "sha512-iOo0VEay2XFhaCcH0sps5XIimkSuOnNaZrf6+ZkoSOQBJPKNU48RkmJv0/lSpipexu5P+ouFgafe5IGr/DiQfg==", "cpu": [ - "arm" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" - ] + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", - "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.6.tgz", + "integrity": "sha512-y5NTmmasMS455JlOCO4ZM9krIchv3Mvm1crL1iUPGOPgEzSkves9n0SdC5Sjz6+qWDFhd8/JpfWMH8NSWNHe+A==", "cpu": [ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ - "linux" - ] + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", - "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.6.tgz", + "integrity": "sha512-np8iZSLfXlAD4kWhiyq/u0Yt8oZDtRQ8lGhQaCXo2rl37KNjeU0GjJuwr4P3oeZ++ROfofsKNBqR5LTO8aXyWQ==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ - "linux" - ] + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", - "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@scure/base": { + "version": "2.2.0", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "@noble/curves": "2.0.1", + "@noble/hashes": "2.0.1", + "@scure/base": "2.0.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/curves": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "@noble/hashes": "2.0.1" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@scure/base": { + "version": "2.0.0", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "@noble/hashes": "2.0.1", + "@scure/base": "2.0.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39/node_modules/@scure/base": { + "version": "2.0.0", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@sindresorhus/base62": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@stablelib/base64": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "license": "MIT" + }, + "node_modules/@supabase/auth-js": { + "version": "2.112.2", + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@supabase/cli-darwin-arm64": { + "version": "2.115.0", + "resolved": "https://registry.npmjs.org/@supabase/cli-darwin-arm64/-/cli-darwin-arm64-2.115.0.tgz", + "integrity": "sha512-yUNw1KG+fyuBqBGvFT8ASC7aAkFkx2Kx+qPjUTW50ttiKKgg8D/eMSCoSjQuaAbL0vafw98bHEZ2dAfdyYyXMA==", "cpu": [ - "ppc64" + "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ - "linux" + "darwin" ] }, - "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", - "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "node_modules/@supabase/cli-darwin-x64": { + "version": "2.115.0", + "resolved": "https://registry.npmjs.org/@supabase/cli-darwin-x64/-/cli-darwin-x64-2.115.0.tgz", + "integrity": "sha512-e4bbWADYcjSjXgSSErreoqyEeEjrFQunxCYummUoiGdVanck/itAIFwhtRykKpBtoKqCYh4CFxUiDxOFMBdNHQ==", "cpu": [ - "riscv64" + "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ - "linux" + "darwin" ] }, - "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", - "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "node_modules/@supabase/cli-linux-arm64": { + "version": "2.115.0", + "resolved": "https://registry.npmjs.org/@supabase/cli-linux-arm64/-/cli-linux-arm64-2.115.0.tgz", + "integrity": "sha512-JBcnnFuVekMR9+EOCcup1QihW+CHMBWcL/+N1Uz4HB6leX8d894VQ+sX0pFgbXLqnpGcc35IiXKwjLz4FCb8Dw==", "cpu": [ - "riscv64" + "arm64" ], "dev": true, "libc": [ - "musl" + "glibc" ], "license": "MIT", "optional": true, @@ -6830,16 +4334,16 @@ "linux" ] }, - "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", - "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "node_modules/@supabase/cli-linux-arm64-musl": { + "version": "2.115.0", + "resolved": "https://registry.npmjs.org/@supabase/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.115.0.tgz", + "integrity": "sha512-2OCzD4qZx8RFbW2vfOlXpup+1UnVqSauUsSGH4mKiUIveMD/UyMI6Md8CLKLszwV2XwM+6bZG6w7d7Ems9vxCQ==", "cpu": [ - "s390x" + "arm64" ], "dev": true, "libc": [ - "glibc" + "musl" ], "license": "MIT", "optional": true, @@ -6847,8 +4351,8 @@ "linux" ] }, - "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.11.1", + "node_modules/@supabase/cli-linux-x64": { + "version": "2.115.0", "cpu": [ "x64" ], @@ -6862,8 +4366,10 @@ "linux" ] }, - "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.11.1", + "node_modules/@supabase/cli-linux-x64-musl": { + "version": "2.115.0", + "resolved": "https://registry.npmjs.org/@supabase/cli-linux-x64-musl/-/cli-linux-x64-musl-2.115.0.tgz", + "integrity": "sha512-t36QEEQxy0AsOn0rr1L8aEzZKYS+kRH4fvYr5KdB+rHA1x39A1dUeOCTqCucCr0V5oQ3+odJLlO6tinNczHKMQ==", "cpu": [ "x64" ], @@ -6877,27 +4383,10 @@ "linux" ] }, - "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", - "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.11" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", - "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "node_modules/@supabase/cli-windows-arm64": { + "version": "2.115.0", + "resolved": "https://registry.npmjs.org/@supabase/cli-windows-arm64/-/cli-windows-arm64-2.115.0.tgz", + "integrity": "sha512-MkYbWrNZXpWZxwglVaTexj+w6EWYUi34c7Y9SRGbcQBC/infteM/8zhVVRUmO3ltSEqnJCacHowLPISXIF6g/w==", "cpu": [ "arm64" ], @@ -6906,3311 +4395,3424 @@ "optional": true, "os": [ "win32" - ] - }, - "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", - "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", - "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@upstash/core-analytics": { - "version": "v0.0.10", - "license": "MIT", - "dependencies": { - "@upstash/redis": "^1.28.3" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@upstash/ratelimit": { - "version": "v2.0.7", - "license": "MIT", - "dependencies": { - "@upstash/core-analytics": "^0.0.10" - }, - "peerDependencies": { - "@upstash/redis": "^1.34.3" - } - }, - "node_modules/@upstash/redis": { - "version": "1.38.2", - "license": "MIT", - "dependencies": { - "uncrypto": "^0.1.3" - } - }, - "node_modules/accepts": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.16.0", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "7.1.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/ai-forms": { - "version": "0.1.2", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "react": ">=18" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - } - } - }, - "node_modules/ai-kit": { - "version": "0.6.2", - "resolved": "git+ssh://git@github.com/bitbaum/ai-kit.git#ace11f14d817079ae2bf4cdc010b6daa9faacbec", - "license": "MIT", - "dependencies": { - "ai-forms": "^0.1.2" - }, - "engines": { - "node": ">=20" - }, - "peerDependencies": { - "react": ">=18" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - } - } - }, - "node_modules/ajv": { - "version": "8.18.0", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "license": "MIT", - "engines": { - "node": ">=8" - } + ] }, - "node_modules/ansi-styles": { - "version": "5.2.0", + "node_modules/@supabase/cli-windows-x64": { + "version": "2.115.0", + "resolved": "https://registry.npmjs.org/@supabase/cli-windows-x64/-/cli-windows-x64-2.115.0.tgz", + "integrity": "sha512-jRXsJjbw/h0ssSpFQeClTTO2wtMw0YYS1yMzN2f/px4DehigBZNxSFB4thOtzmIJoisInm1gYV5pQJZla1Ytpw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/anymatch": { - "version": "3.1.3", - "dev": true, - "license": "ISC", + "node_modules/@supabase/functions-js": { + "version": "2.112.2", + "license": "MIT", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "tslib": "2.8.1" }, "engines": { - "node": ">= 8" + "node": ">=22.0.0" } }, - "node_modules/are-docs-informative": { - "version": "0.0.2", - "dev": true, + "node_modules/@supabase/phoenix": { + "version": "0.4.5", + "license": "MIT" + }, + "node_modules/@supabase/postgrest-js": { + "version": "2.112.2", "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, "engines": { - "node": ">=14" + "node": ">=22.0.0" } }, - "node_modules/argparse": { - "version": "2.0.1", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/aria-hidden": { - "version": "1.2.6", + "node_modules/@supabase/realtime-js": { + "version": "2.112.2", "license": "MIT", "dependencies": { - "tslib": "^2.0.0" + "@supabase/phoenix": "0.4.5", + "tslib": "2.8.1" }, "engines": { - "node": ">=10" + "node": ">=22.0.0" } }, - "node_modules/aria-query": { - "version": "5.3.0", - "dev": true, - "license": "Apache-2.0", + "node_modules/@supabase/ssr": { + "version": "0.12.4", + "license": "MIT", "dependencies": { - "dequal": "^2.0.3" + "cookie": "^1.0.2" + }, + "peerDependencies": { + "@supabase/supabase-js": "^2.111.0" } }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "dev": true, + "node_modules/@supabase/storage-js": { + "version": "2.112.2", "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" + "iceberg-js": "^0.8.1", + "tslib": "2.8.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=22.0.0" } }, - "node_modules/array-includes": { - "version": "3.1.9", - "dev": true, + "node_modules/@supabase/supabase-js": { + "version": "2.112.2", "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.24.0", - "es-object-atoms": "^1.1.1", - "get-intrinsic": "^1.3.0", - "is-string": "^1.1.1", - "math-intrinsics": "^1.1.0" + "@supabase/auth-js": "2.112.2", + "@supabase/functions-js": "2.112.2", + "@supabase/postgrest-js": "2.112.2", + "@supabase/realtime-js": "2.112.2", + "@supabase/storage-js": "2.112.2" }, "engines": { - "node": ">= 0.4" + "node": ">=22.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + } } }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", + "node_modules/@swc/core": { + "version": "1.16.1", "dev": true, - "license": "MIT", + "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.28" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.16.1", + "@swc/core-darwin-x64": "1.16.1", + "@swc/core-linux-arm-gnueabihf": "1.16.1", + "@swc/core-linux-arm64-gnu": "1.16.1", + "@swc/core-linux-arm64-musl": "1.16.1", + "@swc/core-linux-ppc64-gnu": "1.16.1", + "@swc/core-linux-s390x-gnu": "1.16.1", + "@swc/core-linux-x64-gnu": "1.16.1", + "@swc/core-linux-x64-musl": "1.16.1", + "@swc/core-win32-arm64-msvc": "1.16.1", + "@swc/core-win32-ia32-msvc": "1.16.1", + "@swc/core-win32-x64-msvc": "1.16.1" + }, + "peerDependencies": { + "@swc/helpers": ">=0.5.17" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.6", + "node_modules/@swc/core-darwin-arm64": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.16.1.tgz", + "integrity": "sha512-zlJblJ8ncErD43lKdxjbUaUskJQf+LxiPXYcWXD8/8ZMV+7uuAT+CwjciLXpyZBd5Pq/S726bMpeeAwSeL1hhg==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-shim-unscopables": "^1.1.0" - }, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.3", + "node_modules/@swc/core-darwin-x64": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.16.1.tgz", + "integrity": "sha512-IN0BmPWb0YAh/17mmlWB/HDBtTw2MfuW4hulf/tQAgTQBRH17l+z499bNJLK6LizSjqs0P7V+jU38Zj+vJC1DA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.3", + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.16.1.tgz", + "integrity": "sha512-EYgrx2YOCQ2Twz2S793kqNjPkpvYVUPzzR95bIb7by+VQcyaai4lZZ2iz/tZvcFVKSNcN3/JTKwx+aBn2ZL52A==", + "cpu": [ + "arm" + ], "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.16.1.tgz", + "integrity": "sha512-moyKm0YZlHdHohzm1YwgAyesqnE853rO0REMfJLFAova51wF9BNi+3ZW2PeS7Vqvn6HeJuepLpAHbBdZctxpHA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, + "libc": [ + "glibc" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" + "node": ">=10" } }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.16.1.tgz", + "integrity": "sha512-kKGBO9wdapiSzuf5ZzZ2fYtlu1BNSYtIIUxvH1ir/gcelTOREEHGDCLTDFx/2Knf878nU11A40z7LxwasEFxqA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" - }, + "libc": [ + "musl" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/ast-types-flow": { - "version": "0.0.8", + "node_modules/@swc/core-linux-ppc64-gnu": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-ppc64-gnu/-/core-linux-ppc64-gnu-1.16.1.tgz", + "integrity": "sha512-nZ6qahtLxC3PM54cWOQZHxt4lTCF/3J4LIoWWzz6v7A+rLs8Dx54anYQf7mH3eIi8KlNpgKci/ie8ZSqFN8O7A==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "MIT" - }, - "node_modules/astring": { - "version": "1.9.0", - "license": "MIT", - "bin": { - "astring": "bin/astring" + "libc": [ + "glibc" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" } }, - "node_modules/async-function": { - "version": "1.0.0", + "node_modules/@swc/core-linux-s390x-gnu": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-s390x-gnu/-/core-linux-s390x-gnu-1.16.1.tgz", + "integrity": "sha512-4ji5PNzhYq193Z4/4xUaSoNJza6iCkDJSzhetrbB6KOYxsr+kxtQr8ePWhMJUiMt6JUWtXaZ1PYT8FhtED+nGA==", + "cpu": [ + "s390x" + ], "dev": true, - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" + "node": ">=10" } }, - "node_modules/autoprefixer": { - "version": "10.5.4", - "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" - } + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.16.1", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" ], - "license": "MIT", - "dependencies": { - "browserslist": "^4.28.6", - "caniuse-lite": "^1.0.30001806", - "fraction.js": "^5.3.4", - "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": ">=10" } }, - "node_modules/autoprefixer/node_modules/browserslist": { - "version": "4.28.8", - "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" - } + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.16.1.tgz", + "integrity": "sha512-r9oV1mwxxsIGcLV1IQ/tw76MW3doatKze1QFWuC+a7QqJUkhY/bKTSVk6NpKKUGm2LDsE33Va8VqSClfA7vSiQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" ], - "license": "MIT", - "dependencies": { - "baseline-browser-mapping": "^2.11.12", - "caniuse-lite": "^1.0.30001809", - "electron-to-chromium": "^1.5.402", - "node-releases": "^2.0.53", - "update-browserslist-db": "^1.3.0" - }, - "bin": { - "browserslist": "cli.js" - }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">=10" } }, - "node_modules/autoprefixer/node_modules/update-browserslist-db": { - "version": "1.3.1", - "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" - } + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.16.1.tgz", + "integrity": "sha512-6huNRessoBLxWEqBm5zJXyCQ27TO7anvkdiuQ5MDO4CJni0nOXEqKtV9RllQ2TdyENKKsUMXVnIfW2hIXx/R5Q==", + "cpu": [ + "arm64" ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.16.1.tgz", + "integrity": "sha512-OVKJFUzphrGmsh+BGtcZDesx0YryV7/Yvy5XGgTqnrZfjnyfcr5uaqYQugCckdIlupc5Vs3XtDjRAj12z4ZPlw==", + "cpu": [ + "ia32" + ], "dev": true, - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/axe-core": { - "version": "4.11.2", + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.16.1.tgz", + "integrity": "sha512-Bt+VIhWYCGk4urklnkkteLUOeLv1VxigwTCeB/xC6rBZxY6IIKdDwCJf6on3E3SUGsIqmQS6QqtuJQc1VxF4Aw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MPL-2.0", + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/axobject-query": { - "version": "4.1.0", + "node_modules/@swc/counter": { + "version": "0.1.3", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@swc/types": { + "version": "0.1.28", "dev": true, "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" + "dependencies": { + "@swc/counter": "^0.1.3" } }, - "node_modules/babel-jest": { - "version": "30.3.0", + "node_modules/@tailwindcss/node": { + "version": "4.3.3", "dev": true, "license": "MIT", "dependencies": { - "@jest/transform": "30.3.0", - "@types/babel__core": "^7.20.5", - "babel-plugin-istanbul": "^7.0.1", - "babel-preset-jest": "30.3.0", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "slash": "^3.0.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.11.0 || ^8.0.0-0" + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.24.1", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.3" } }, - "node_modules/babel-jest/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/@tailwindcss/oxide": { + "version": "4.3.3", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">= 20" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-x64": "4.3.3", + "@tailwindcss/oxide-freebsd-x64": "4.3.3", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-x64-musl": "4.3.3", + "@tailwindcss/oxide-wasm32-wasi": "4.3.3", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" } }, - "node_modules/babel-jest/node_modules/chalk": { - "version": "4.1.2", + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", + "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">= 20" } }, - "node_modules/babel-jest/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", + "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=8" + "node": ">= 20" } }, - "node_modules/babel-plugin-istanbul": { - "version": "7.0.1", + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", + "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BSD-3-Clause", - "workspaces": [ - "test/babel-8" + "license": "MIT", + "optional": true, + "os": [ + "darwin" ], - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-instrument": "^6.0.2", - "test-exclude": "^6.0.0" - }, "engines": { - "node": ">=12" + "node": ">= 20" } }, - "node_modules/babel-plugin-jest-hoist": { - "version": "30.3.0", + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", + "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/babel__core": "^7.20.5" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 20" } }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.2.0", + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", + "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" - }, - "peerDependencies": { - "@babel/core": "^7.0.0 || ^8.0.0-0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" } }, - "node_modules/babel-preset-jest": { - "version": "30.3.0", + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", + "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", + "cpu": [ + "arm64" + ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "dependencies": { - "babel-plugin-jest-hoist": "30.3.0", - "babel-preset-current-node-syntax": "^1.2.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.11.0 || ^8.0.0-beta.1" - } - }, - "node_modules/bail": { - "version": "2.0.2", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node": ">= 20" } }, - "node_modules/balanced-match": { - "version": "1.0.2", + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", + "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" - }, - "node_modules/base-x": { - "version": "5.0.1", - "license": "MIT" - }, - "node_modules/baseline-browser-mapping": { - "version": "2.11.14", - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/bech32": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/before-after-hook": { - "version": "4.0.0", - "license": "Apache-2.0" - }, - "node_modules/bip174": { - "version": "2.1.1", + "libc": [ + "musl" + ], "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8.0.0" + "node": ">= 20" } }, - "node_modules/bip32": { - "version": "5.0.1", + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.3", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.2.0", - "@scure/base": "^1.1.1", - "uint8array-tools": "^0.0.8", - "valibot": "^1.2.0", - "wif": "^5.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18.0.0" + "node": ">= 20" } }, - "node_modules/bip32/node_modules/@noble/hashes": { - "version": "1.8.0", + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", + "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/bip32/node_modules/@scure/base": { - "version": "1.2.6", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">= 20" } - }, - "node_modules/bitcoinjs-lib": { - "version": "6.1.7", + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", + "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@noble/hashes": "^1.2.0", - "bech32": "^2.0.0", - "bip174": "^2.1.1", - "bs58check": "^3.0.1", - "typeforce": "^1.11.3", - "varuint-bitcoin": "^1.1.2" + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" }, "engines": { - "node": ">=8.0.0" + "node": ">=14.0.0" } }, - "node_modules/bitcoinjs-lib/node_modules/@noble/hashes": { - "version": "1.8.0", + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.11.1", + "dev": true, + "inBundle": true, "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" } }, - "node_modules/bitcoinjs-lib/node_modules/base-x": { - "version": "4.0.1", - "license": "MIT" - }, - "node_modules/bitcoinjs-lib/node_modules/bs58": { - "version": "5.0.0", + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "dev": true, + "inBundle": true, "license": "MIT", + "optional": true, "dependencies": { - "base-x": "^4.0.0" + "tslib": "^2.4.0" } }, - "node_modules/bitcoinjs-lib/node_modules/bs58check": { - "version": "3.0.1", + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "dev": true, + "inBundle": true, "license": "MIT", + "optional": true, "dependencies": { - "@noble/hashes": "^1.2.0", - "bs58": "^5.0.0" + "tslib": "^2.4.0" } }, - "node_modules/body-parser": { - "version": "2.3.0", + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "dev": true, + "inBundle": true, "license": "MIT", + "optional": true, "dependencies": { - "bytes": "^3.1.2", - "content-type": "^2.0.0", - "debug": "^4.4.3", - "http-errors": "^2.0.1", - "iconv-lite": "^0.7.2", - "on-finished": "^2.4.1", - "qs": "^6.15.2", - "raw-body": "^3.0.2", - "type-is": "^2.1.0" - }, - "engines": { - "node": ">=18" + "@tybys/wasm-util": "^0.10.1" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" } }, - "node_modules/body-parser/node_modules/content-type": { - "version": "2.0.0", + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "dev": true, + "inBundle": true, "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "optional": true, + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/boolbase": { - "version": "1.0.0", - "license": "ISC" + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { + "version": "2.8.1", + "dev": true, + "inBundle": true, + "license": "0BSD", + "optional": true }, - "node_modules/brace-expansion": { - "version": "5.0.9", + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", + "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "20 || >=22" + "node": ">= 20" } }, - "node_modules/brace-expansion/node_modules/balanced-match": { - "version": "4.0.4", + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", + "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "18 || 20 || >=22" + "node": ">= 20" } }, - "node_modules/braces": { - "version": "3.0.3", + "node_modules/@tailwindcss/postcss": { + "version": "4.3.3", "dev": true, "license": "MIT", "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.3.3", + "@tailwindcss/oxide": "4.3.3", + "postcss": "^8.5.16", + "tailwindcss": "4.3.3" } }, - "node_modules/browserslist": { - "version": "4.28.1", - "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" - } - ], + "node_modules/@tanstack/query-core": { + "version": "5.102.8", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.102.8.tgz", + "integrity": "sha512-ZNjkJ33CqvPNec/6lZBnHqLc3EVGPZ9ySLhYahU9TcuRFdmwXewuj0c4hwSWcGHqEUwcSrKeZ+oGcvPBqXcQcg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.102.8", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.102.8.tgz", + "integrity": "sha512-TYBea4OuXWD7MhaSHq069TWbFe7rcwWN6kzT7JF0OKi1K6c1gTv2IzD6A6ExJsCMozdkqBWeuIUZmu4KQg0O5A==", "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" + "@tanstack/query-core": "5.102.8" }, - "bin": { - "browserslist": "cli.js" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "peerDependencies": { + "react": "^18 || ^19" } }, - "node_modules/bs-logger": { - "version": "0.2.6", + "node_modules/@testing-library/dom": { + "version": "10.4.1", "dev": true, "license": "MIT", "dependencies": { - "fast-json-stable-stringify": "2.x" + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/bs58": { - "version": "6.0.0", - "license": "MIT", - "dependencies": { - "base-x": "^5.0.0" + "node": ">=18" } }, - "node_modules/bs58check": { - "version": "4.0.0", + "node_modules/@testing-library/jest-dom": { + "version": "7.0.0", + "dev": true, "license": "MIT", "dependencies": { - "@noble/hashes": "^1.2.0", - "bs58": "^6.0.0" - } - }, - "node_modules/bs58check/node_modules/@noble/hashes": { - "version": "1.8.0", - "license": "MIT", + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "picocolors": "^1.1.1", + "redent": "^3.0.0" + }, "engines": { - "node": "^14.21.3 || >=16" + "node": ">=22", + "npm": ">=6", + "yarn": ">=1" }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "node-int64": "^0.4.0" + "peerDependencies": { + "@testing-library/dom": ">=10 <11" } }, - "node_modules/buffer-from": { - "version": "1.1.2", + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", "dev": true, "license": "MIT" }, - "node_modules/bundle-name": { - "version": "4.1.0", + "node_modules/@testing-library/react": { + "version": "16.3.2", "dev": true, "license": "MIT", "dependencies": { - "run-applescript": "^7.0.0" + "@babel/runtime": "^7.12.5" }, "engines": { "node": ">=18" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/bytes": { - "version": "3.1.2", + "node_modules/@testing-library/user-event": { + "version": "14.6.4", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" } }, - "node_modules/call-bind": { - "version": "1.0.8", + "node_modules/@ts-morph/common": { + "version": "0.27.0", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "fast-glob": "^3.3.3", + "minimatch": "^10.0.1", + "path-browserify": "^1.0.1" } }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", + "node_modules/@ts-morph/common/node_modules/fast-glob": { + "version": "3.3.3", + "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" + "@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": ">= 0.4" + "node": ">=8.6.0" } }, - "node_modules/call-bound": { - "version": "1.0.4", - "license": "MIT", + "node_modules/@ts-morph/common/node_modules/glob-parent": { + "version": "5.1.2", + "dev": true, + "license": "ISC", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" + "is-glob": "^4.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 6" } }, - "node_modules/callsites": { - "version": "3.1.0", + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "optional": true, + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/camelcase": { - "version": "5.3.1", + "node_modules/@types/aria-query": { + "version": "5.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001809", - "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/ccount": { - "version": "2.0.1", + "node_modules/@types/debug": { + "version": "4.1.12", "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "@types/ms": "*" } }, - "node_modules/chalk": { - "version": "6.0.0", + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, + "license": "MIT" + }, + "node_modules/@types/dompurify": { + "version": "3.2.0", + "deprecated": "This is a stub types definition. dompurify provides its own type definitions, so you do not need this installed.", "license": "MIT", - "engines": { - "node": ">=22" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "dependencies": { + "dompurify": "*" } }, - "node_modules/char-regex": { - "version": "1.0.2", + "node_modules/@types/esrecurse": { + "version": "4.3.1", "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "license": "MIT" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "@types/estree": "*" } }, - "node_modules/character-entities": { - "version": "2.0.2", + "node_modules/@types/hast": { + "version": "3.0.4", "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "@types/unist": "*" } }, - "node_modules/character-entities-html4": { - "version": "2.1.0", + "node_modules/@types/json-schema": { + "version": "7.0.15", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.25", + "license": "MIT" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "@types/unist": "*" } }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", + "node_modules/@types/mdx": { + "version": "2.0.14", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "26.3.0", + "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "undici-types": "~8.3.0" } }, - "node_modules/character-reference-invalid": { - "version": "2.0.1", + "node_modules/@types/react": { + "version": "19.2.18", "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "csstype": "^3.2.2" } }, - "node_modules/ci-info": { - "version": "4.4.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], + "node_modules/@types/react-dom": { + "version": "19.2.4", "license": "MIT", - "engines": { - "node": ">=8" + "peerDependencies": { + "@types/react": "^19.2.0" } }, - "node_modules/cjs-module-lexer": { - "version": "2.2.0", + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "license": "MIT", + "optional": true + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "license": "MIT" + }, + "node_modules/@types/validate-npm-package-name": { + "version": "4.0.2", "dev": true, "license": "MIT" }, - "node_modules/class-variance-authority": { - "version": "0.7.1", - "license": "Apache-2.0", - "dependencies": { - "clsx": "^2.1.1" - }, - "funding": { - "url": "https://polar.sh/cva" - } - }, - "node_modules/cli-cursor": { - "version": "5.0.0", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.67.0", "dev": true, "license": "MIT", "dependencies": { - "restore-cursor": "^5.0.0" + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/type-utils": "8.67.0", + "@typescript-eslint/utils": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.67.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/cli-spinners": { - "version": "2.9.2", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/project-service": { + "version": "8.67.0", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.67.0", + "@typescript-eslint/types": "^8.67.0", + "debug": "^4.4.3" + }, "engines": { - "node": ">=6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/client-only": { - "version": "0.0.1", - "license": "MIT" - }, - "node_modules/cliui": { - "version": "8.0.1", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "8.67.0", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0" }, "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/cliui/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.67.0", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "8.67.0", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.67.0", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@typescript-eslint/project-service": "8.67.0", + "@typescript-eslint/tsconfig-utils": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "8.67.0", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0" }, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/clsx": { - "version": "2.1.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cmdk": { - "version": "1.1.1", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "^1.1.1", - "@radix-ui/react-dialog": "^1.1.6", - "@radix-ui/react-id": "^1.1.0", - "@radix-ui/react-primitive": "^2.0.2" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "react": "^18 || ^19 || ^19.0.0-rc", - "react-dom": "^18 || ^19 || ^19.0.0-rc" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/co": { - "version": "4.6.0", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.67.0", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.67.0", + "eslint-visitor-keys": "^5.0.0" + }, "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/code-block-writer": { - "version": "13.0.3", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-visitor-keys": { + "version": "5.0.1", "dev": true, - "license": "MIT" - }, - "node_modules/collapse-white-space": { - "version": "2.1.0", - "license": "MIT", + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://opencollective.com/eslint" } }, - "node_modules/collect-v8-coverage": { - "version": "1.0.3", + "node_modules/@typescript-eslint/parser": { + "version": "8.67.0", "dev": true, - "license": "MIT" - }, - "node_modules/color-convert": { - "version": "2.0.1", "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "debug": "^4.4.3" }, "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "license": "MIT", + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/comment-parser": { - "version": "1.4.7", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/project-service": { + "version": "8.67.0", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.67.0", + "@typescript-eslint/types": "^8.67.0", + "debug": "^4.4.3" + }, "engines": { - "node": ">= 12.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/concurrently": { - "version": "10.0.4", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "8.67.0", "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "5.6.2", - "rxjs": "7.8.2", - "shell-quote": "1.9.0", - "supports-color": "10.2.2", - "tree-kill": "1.2.2", - "yargs": "18.0.0" - }, - "bin": { - "conc": "dist/bin/index.js", - "concurrently": "dist/bin/index.js" + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0" }, "engines": { - "node": ">=22" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/concurrently/node_modules/ansi-regex": { - "version": "6.3.0", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.67.0", "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/concurrently/node_modules/ansi-styles": { - "version": "6.2.3", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "8.67.0", "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/concurrently/node_modules/chalk": { - "version": "5.6.2", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.67.0", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.67.0", + "@typescript-eslint/tsconfig-utils": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/concurrently/node_modules/cliui": { - "version": "9.0.1", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.67.0", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" + "@typescript-eslint/types": "8.67.0", + "eslint-visitor-keys": "^5.0.0" }, "engines": { - "node": ">=20" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/concurrently/node_modules/emoji-regex": { - "version": "10.6.0", + "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { + "version": "5.0.1", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } }, - "node_modules/concurrently/node_modules/string-width": { - "version": "7.2.0", + "node_modules/@typescript-eslint/project-service": { + "version": "8.65.0", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" + "@typescript-eslint/tsconfig-utils": "^8.65.0", + "@typescript-eslint/types": "^8.65.0", + "debug": "^4.4.3" }, "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/concurrently/node_modules/strip-ansi": { - "version": "7.2.0", + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.65.0", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.2.2" + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/visitor-keys": "8.65.0" }, "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/concurrently/node_modules/supports-color": { - "version": "10.2.2", + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.65.0", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/concurrently/node_modules/wrap-ansi": { - "version": "9.0.2", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.67.0", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/utils": "8.67.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/concurrently/node_modules/yargs": { - "version": "18.0.0", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/project-service": { + "version": "8.67.0", "dev": true, "license": "MIT", "dependencies": { - "cliui": "^9.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "string-width": "^7.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^22.0.0" + "@typescript-eslint/tsconfig-utils": "^8.67.0", + "@typescript-eslint/types": "^8.67.0", + "debug": "^4.4.3" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/concurrently/node_modules/yargs-parser": { - "version": "22.0.0", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "8.67.0", "dev": true, - "license": "ISC", - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/content-disposition": { - "version": "1.0.1", "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0" + }, "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/content-type": { - "version": "1.0.5", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.67.0", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/convert-source-map": { - "version": "2.0.0", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "8.67.0", "dev": true, - "license": "MIT" - }, - "node_modules/cookie": { - "version": "1.1.1", "license": "MIT", "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/cookie-signature": { - "version": "1.2.2", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.67.0", + "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.67.0", + "@typescript-eslint/tsconfig-utils": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, "engines": { - "node": ">=6.6.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/cors": { - "version": "2.8.5", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "8.67.0", + "dev": true, "license": "MIT", "dependencies": { - "object-assign": "^4", - "vary": "^1" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0" }, "engines": { - "node": ">= 0.10" + "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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/cosmiconfig": { - "version": "9.0.0", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.67.0", "dev": true, "license": "MIT", "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" + "@typescript-eslint/types": "8.67.0", + "eslint-visitor-keys": "^5.0.0" }, "engines": { - "node": ">=14" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/critters": { - "version": "0.0.23", + "node_modules/@typescript-eslint/type-utils/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "dev": true, "license": "Apache-2.0", - "dependencies": { - "chalk": "^4.1.0", - "css-select": "^5.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.2", - "htmlparser2": "^8.0.2", - "postcss": "^8.4.23", - "postcss-media-query-parser": "^0.2.3" + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/critters/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/@typescript-eslint/types": { + "version": "8.65.0", + "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/critters/node_modules/chalk": { - "version": "4.1.2", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.65.0", + "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@typescript-eslint/project-service": "8.65.0", + "@typescript-eslint/tsconfig-utils": "8.65.0", + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/visitor-keys": "8.65.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/critters/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/@typescript-eslint/utils": { + "version": "8.65.0", + "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.65.0", + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.0" }, "engines": { - "node": ">=8" + "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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.65.0", + "dev": true, "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "@typescript-eslint/types": "8.65.0", + "eslint-visitor-keys": "^5.0.0" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/css-select": { - "version": "5.2.2", - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/css-what": { - "version": "6.2.2", - "license": "BSD-2-Clause", + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">= 6" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "url": "https://opencollective.com/eslint" } }, - "node_modules/css.escape": { - "version": "1.5.1", + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/cssesc": { - "version": "3.0.0", + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/cssstyle": { - "version": "4.6.0", + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "dependencies": { - "@asamuzakjp/css-color": "^3.2.0", - "rrweb-cssom": "^0.8.0" - }, - "engines": { - "node": ">=18" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/csstype": { - "version": "3.2.3", - "license": "MIT" + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], "dev": true, - "license": "BSD-2-Clause" + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "cpu": [ + "x64" + ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "engines": { - "node": ">= 12" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/data-urls": { - "version": "5.0.0", + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "cpu": [ + "x64" + ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", - "dependencies": { - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0" - }, - "engines": { - "node": ">=18" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/data-view-buffer": { - "version": "1.0.2", + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" + "@napi-rs/wasm-runtime": "^0.2.11" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=14.0.0" } }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@upstash/core-analytics": { + "version": "v0.0.10", + "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" + "@upstash/redis": "^1.28.3" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" + "node": ">=16.0.0" } }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "dev": true, + "node_modules/@upstash/ratelimit": { + "version": "v2.0.7", "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" + "@upstash/core-analytics": "^0.0.10" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@upstash/redis": "^1.34.3" } }, - "node_modules/date-fns": { - "version": "4.1.0", + "node_modules/@upstash/redis": { + "version": "1.38.2", "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" + "dependencies": { + "uncrypto": "^0.1.3" } }, - "node_modules/debounce": { - "version": "1.2.1", + "node_modules/@vitest/coverage-v8": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.11.tgz", + "integrity": "sha512-8MVGEFnJIcdGjcbfKmeq8z0pZHH0JlVtoVZH9Q/qwUp6wyFnEJUBMrw9DCaj+ra3vShGmhavjalMIhPNxZAUcw==", "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.1.11", + "ast-v8-to-istanbul": "^1.0.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.2", + "obug": "^2.1.1", + "std-env": "^4.0.0-rc.1", + "tinyrainbow": "^3.1.0" }, - "engines": { - "node": ">=6.0" + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "4.1.11", + "vitest": "4.1.11" }, "peerDependenciesMeta": { - "supports-color": { + "@vitest/browser": { "optional": true } } }, - "node_modules/decamelize": { - "version": "1.2.0", + "node_modules/@vitest/coverage-v8/node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decimal.js": { - "version": "10.6.0", - "dev": true, - "license": "MIT" + "node": ">=18" + } }, - "node_modules/decode-named-character-reference": { - "version": "1.2.0", + "node_modules/@vitest/expect": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.11.tgz", + "integrity": "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==", + "dev": true, "license": "MIT", "dependencies": { - "character-entities": "^2.0.0" + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://opencollective.com/vitest" } }, - "node_modules/dedent": { - "version": "1.7.0", + "node_modules/@vitest/mocker": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.11.tgz", + "integrity": "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==", "dev": true, "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.11", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, "peerDependencies": { - "babel-plugin-macros": "^3.1.0" + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { - "babel-plugin-macros": { + "msw": { + "optional": true + }, + "vite": { "optional": true } } }, - "node_modules/deep-is": { - "version": "0.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-browser": { - "version": "5.4.0", + "node_modules/@vitest/pretty-format": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.11.tgz", + "integrity": "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==", "dev": true, "license": "MIT", "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" - }, - "engines": { - "node": ">=18" + "tinyrainbow": "^3.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, - "node_modules/default-browser-id": { - "version": "5.0.1", + "node_modules/@vitest/runner": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.11.tgz", + "integrity": "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "@vitest/utils": "4.1.11", + "pathe": "^2.0.3" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, - "node_modules/define-data-property": { - "version": "1.1.4", + "node_modules/@vitest/snapshot": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.11.tgz", + "integrity": "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==", "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" + "@vitest/pretty-format": "4.1.11", + "@vitest/utils": "4.1.11", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/vitest" } }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", + "node_modules/@vitest/spy": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.11.tgz", + "integrity": "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" - }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, - "node_modules/define-properties": { - "version": "1.2.1", + "node_modules/@vitest/utils": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.11.tgz", + "integrity": "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==", "dev": true, "license": "MIT", "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" + "@vitest/pretty-format": "4.1.11", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/vitest" } }, - "node_modules/depd": { + "node_modules/accepts": { "version": "2.0.0", "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, "engines": { - "node": ">= 0.8" + "node": ">= 0.6" } }, - "node_modules/dequal": { - "version": "2.0.3", + "node_modules/acorn": { + "version": "8.16.0", "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, "engines": { - "node": ">=6" + "node": ">=0.4.0" } }, - "node_modules/detect-libc": { - "version": "2.1.2", - "devOptional": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" + "node_modules/acorn-jsx": { + "version": "5.3.2", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/detect-newline": { - "version": "3.1.0", + "node_modules/acorn-walk": { + "version": "8.3.4", "dev": true, "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, "engines": { - "node": ">=8" + "node": ">=0.4.0" } }, - "node_modules/detect-node-es": { - "version": "1.1.0", - "license": "MIT" + "node_modules/ai-forms": { + "version": "0.1.2", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": ">=18" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } }, - "node_modules/devlop": { - "version": "1.1.0", + "node_modules/ai-kit": { + "version": "0.6.2", + "resolved": "git+ssh://git@github.com/bitbaum/ai-kit.git#ace11f14d817079ae2bf4cdc010b6daa9faacbec", "license": "MIT", "dependencies": { - "dequal": "^2.0.0" + "ai-forms": "^0.1.2" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "react": ">=18" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, + "node_modules/ajv": { + "version": "8.18.0", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/diff": { - "version": "8.0.3", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", "engines": { - "node": ">=0.3.1" + "node": ">=8" } }, - "node_modules/dijkstrajs": { - "version": "1.0.3", - "license": "MIT" - }, - "node_modules/doctrine": { - "version": "2.1.0", + "node_modules/ansi-styles": { + "version": "5.2.0", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" + "license": "MIT", + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/are-docs-informative": { + "version": "0.0.2", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=14" } }, - "node_modules/dom-accessibility-api": { - "version": "0.5.16", + "node_modules/argparse": { + "version": "2.0.1", "dev": true, - "license": "MIT" + "license": "Python-2.0" }, - "node_modules/dom-serializer": { - "version": "2.0.0", + "node_modules/aria-hidden": { + "version": "1.2.6", "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" + "tslib": "^2.0.0" }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "engines": { + "node": ">=10" } }, - "node_modules/domelementtype": { - "version": "2.3.0", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" + "node_modules/aria-query": { + "version": "5.3.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } }, - "node_modules/domhandler": { - "version": "5.0.3", - "license": "BSD-2-Clause", + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "dev": true, + "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, "engines": { - "node": ">= 4" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/dompurify": { - "version": "3.4.13", - "license": "(MPL-2.0 OR Apache-2.0)", - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/domutils": { - "version": "3.2.2", - "license": "BSD-2-Clause", + "node_modules/array-includes": { + "version": "3.1.9", + "dev": true, + "license": "MIT", "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dotenv": { - "version": "16.6.1", - "dev": true, - "license": "BSD-2-Clause", "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://dotenvx.com" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/duplexer": { - "version": "0.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "license": "MIT" - }, - "node_modules/eciesjs": { - "version": "0.4.16", + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", "dev": true, "license": "MIT", "dependencies": { - "@ecies/ciphers": "^0.2.4", - "@noble/ciphers": "^1.3.0", - "@noble/curves": "^1.9.7", - "@noble/hashes": "^1.8.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" }, "engines": { - "bun": ">=1", - "deno": ">=2", - "node": ">=16" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eciesjs/node_modules/@noble/hashes": { - "version": "1.8.0", + "node_modules/array.prototype.flat": { + "version": "1.3.3", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, "engines": { - "node": "^14.21.3 || >=16" + "node": ">= 0.4" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ee-first": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.406", - "license": "ISC" - }, - "node_modules/emittery": { - "version": "0.13.1", + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" } }, - "node_modules/enhanced-resolve": { - "version": "5.24.5", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.3" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/env-paths": { - "version": "2.2.1", + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=12" } }, - "node_modules/error-ex": { - "version": "1.3.4", + "node_modules/ast-types-flow": { + "version": "0.0.8", + "dev": true, + "license": "MIT" + }, + "node_modules/ast-v8-to-istanbul": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.5.tgz", + "integrity": "sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==", "dev": true, "license": "MIT", "dependencies": { - "is-arrayish": "^0.2.1" + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" } }, - "node_modules/es-abstract": { - "version": "1.24.1", + "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", "dev": true, + "license": "MIT" + }, + "node_modules/astring": { + "version": "1.9.0", "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "astring": "bin/astring" } }, - "node_modules/es-define-property": { - "version": "1.0.1", + "node_modules/async-function": { + "version": "1.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" } }, - "node_modules/es-errors": { - "version": "1.3.0", + "node_modules/autoprefixer": { + "version": "10.5.4", + "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.28.6", + "caniuse-lite": "^1.0.30001806", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, "engines": { - "node": ">= 0.4" + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/es-iterator-helpers": { - "version": "1.3.1", - "dev": true, + "node_modules/autoprefixer/node_modules/browserslist": { + "version": "4.28.8", + "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": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.24.1", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.1.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.3.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "iterator.prototype": "^1.1.5", - "math-intrinsics": "^1.1.0", - "safe-array-concat": "^1.1.3" + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" + }, + "bin": { + "browserslist": "cli.js" }, "engines": { - "node": ">= 0.4" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/es-object-atoms": { - "version": "1.1.1", + "node_modules/autoprefixer/node_modules/update-browserslist-db": { + "version": "1.3.1", + "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": { - "es-errors": "^1.3.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, - "engines": { - "node": ">= 0.4" + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", + "node_modules/available-typed-arrays": { + "version": "1.0.7", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "possible-typed-array-names": "^1.0.0" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-shim-unscopables": { - "version": "1.1.0", + "node_modules/axe-core": { + "version": "4.11.2", "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, + "license": "MPL-2.0", "engines": { - "node": ">= 0.4" + "node": ">=4" } }, - "node_modules/es-to-primitive": { - "version": "1.3.0", + "node_modules/axobject-query": { + "version": "4.1.0", "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" - }, + "license": "Apache-2.0", "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esast-util-from-estree": { - "version": "2.0.0", + "node_modules/bail": { + "version": "2.0.2", "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "devlop": "^1.0.0", - "estree-util-visit": "^2.0.0", - "unist-util-position-from-estree": "^2.0.0" - }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/esast-util-from-js": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "acorn": "^8.0.0", - "esast-util-from-estree": "^2.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } + "node_modules/balanced-match": { + "version": "1.0.2", + "dev": true, + "license": "MIT" }, - "node_modules/escalade": { - "version": "3.2.0", - "license": "MIT", + "node_modules/base-x": { + "version": "5.0.1", + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.14", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, "engines": { - "node": ">=6" + "node": ">=6.0.0" } }, - "node_modules/escape-html": { - "version": "1.0.3", + "node_modules/bech32": { + "version": "2.0.0", "license": "MIT" }, - "node_modules/escape-string-regexp": { + "node_modules/before-after-hook": { "version": "4.0.0", + "license": "Apache-2.0" + }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "require-from-string": "^2.0.2" } }, - "node_modules/eslint": { - "version": "10.8.1", - "dev": true, + "node_modules/bip174": { + "version": "2.1.1", "license": "MIT", - "workspaces": [ - "packages/*" - ], - "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.2", - "@eslint/config-array": "^0.23.5", - "@eslint/config-helpers": "^0.7.0", - "@eslint/core": "^1.2.1", - "@eslint/plugin-kit": "^0.7.2", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "ajv": "^6.14.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^9.1.2", - "eslint-visitor-keys": "^5.0.1", - "espree": "^11.2.0", - "esquery": "^1.7.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", - "minimatch": "^10.2.5", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } + "node": ">=8.0.0" } }, - "node_modules/eslint-config-next": { - "version": "16.3.1", - "dev": true, + "node_modules/bip32": { + "version": "5.0.1", "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "16.3.1", - "eslint-import-resolver-node": "^0.3.6", - "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.32.0", - "eslint-plugin-jsx-a11y": "^6.10.0", - "eslint-plugin-react": "^7.37.0", - "eslint-plugin-react-hooks": "^7.0.0", - "globals": "16.4.0", - "typescript-eslint": "^8.46.0" - }, - "peerDependencies": { - "eslint": ">=9.0.0", - "typescript": ">=3.3.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@noble/hashes": "^1.2.0", + "@scure/base": "^1.1.1", + "uint8array-tools": "^0.0.8", + "valibot": "^1.2.0", + "wif": "^5.0.0" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/eslint-config-next/node_modules/aria-query": { - "version": "5.3.2", - "dev": true, - "license": "Apache-2.0", + "node_modules/bip32/node_modules/@noble/hashes": { + "version": "1.8.0", + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/eslint-config-next/node_modules/brace-expansion": { - "version": "1.1.18", - "dev": true, + "node_modules/bip32/node_modules/@scure/base": { + "version": "1.2.6", "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/eslint-config-next/node_modules/eslint-import-resolver-typescript": { - "version": "3.10.1", - "dev": true, - "license": "ISC", + "node_modules/bitcoinjs-lib": { + "version": "6.1.7", + "license": "MIT", "dependencies": { - "@nolyfill/is-core-module": "1.0.39", - "debug": "^4.4.0", - "get-tsconfig": "^4.10.0", - "is-bun-module": "^2.0.0", - "stable-hash": "^0.0.5", - "tinyglobby": "^0.2.13", - "unrs-resolver": "^1.6.2" + "@noble/hashes": "^1.2.0", + "bech32": "^2.0.0", + "bip174": "^2.1.1", + "bs58check": "^3.0.1", + "typeforce": "^1.11.3", + "varuint-bitcoin": "^1.1.2" }, "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-import-resolver-typescript" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*", - "eslint-plugin-import-x": "*" - }, - "peerDependenciesMeta": { - "eslint-plugin-import": { - "optional": true - }, - "eslint-plugin-import-x": { - "optional": true - } + "node": ">=8.0.0" } }, - "node_modules/eslint-config-next/node_modules/eslint-plugin-import": { - "version": "2.32.0", - "dev": true, + "node_modules/bitcoinjs-lib/node_modules/@noble/hashes": { + "version": "1.8.0", "license": "MIT", - "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.9", - "array.prototype.findlastindex": "^1.2.6", - "array.prototype.flat": "^1.3.3", - "array.prototype.flatmap": "^1.3.3", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.1", - "hasown": "^2.0.2", - "is-core-module": "^2.16.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.1", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.9", - "tsconfig-paths": "^3.15.0" - }, "engines": { - "node": ">=4" + "node": "^14.21.3 || >=16" }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/eslint-config-next/node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "dev": true, + "node_modules/bitcoinjs-lib/node_modules/base-x": { + "version": "4.0.1", + "license": "MIT" + }, + "node_modules/bitcoinjs-lib/node_modules/bs58": { + "version": "5.0.0", "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "base-x": "^4.0.0" } }, - "node_modules/eslint-config-next/node_modules/eslint-plugin-jsx-a11y": { - "version": "6.10.2", - "dev": true, + "node_modules/bitcoinjs-lib/node_modules/bs58check": { + "version": "3.0.1", "license": "MIT", "dependencies": { - "aria-query": "^5.3.2", - "array-includes": "^3.1.8", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "^4.10.0", - "axobject-query": "^4.1.0", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "hasown": "^2.0.2", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "safe-regex-test": "^1.0.3", - "string.prototype.includes": "^2.0.1" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + "@noble/hashes": "^1.2.0", + "bs58": "^5.0.0" } }, - "node_modules/eslint-config-next/node_modules/eslint-plugin-react": { - "version": "7.37.5", - "dev": true, + "node_modules/body-parser": { + "version": "2.3.0", "license": "MIT", "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.3", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.2.1", - "estraverse": "^5.3.0", - "hasown": "^2.0.2", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.9", - "object.fromentries": "^2.0.8", - "object.values": "^1.2.1", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.12", - "string.prototype.repeat": "^1.0.0" + "bytes": "^3.1.2", + "content-type": "^2.0.0", + "debug": "^4.4.3", + "http-errors": "^2.0.1", + "iconv-lite": "^0.7.2", + "on-finished": "^2.4.1", + "qs": "^6.15.2", + "raw-body": "^3.0.2", + "type-is": "^2.1.0" }, "engines": { - "node": ">=4" + "node": ">=18" }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/eslint-config-next/node_modules/globals": { - "version": "16.4.0", - "dev": true, + "node_modules/body-parser/node_modules/content-type": { + "version": "2.0.0", "license": "MIT", "engines": { "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/eslint-config-next/node_modules/minimatch": { - "version": "3.1.5", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } + "node_modules/boolbase": { + "version": "1.0.0", + "license": "ISC" }, - "node_modules/eslint-config-next/node_modules/resolve": { - "version": "2.0.0-next.6", - "dev": true, + "node_modules/brace-expansion": { + "version": "5.0.9", "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "is-core-module": "^2.16.1", - "node-exports-info": "^1.6.0", - "object-keys": "^1.1.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "balanced-match": "^4.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-config-next/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node": "20 || >=22" } }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "dev": true, + "node_modules/brace-expansion/node_modules/balanced-match": { + "version": "4.0.4", "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" + "engines": { + "node": "18 || 20 || >=22" } }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", + "node_modules/braces": { + "version": "3.0.3", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/eslint-module-utils": { - "version": "2.12.1", + "node_modules/browserslist": { + "version": "4.28.1", "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": { - "debug": "^3.2.7" + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" }, - "engines": { - "node": ">=4" + "bin": { + "browserslist": "cli.js" }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "dev": true, + "node_modules/bs58": { + "version": "6.0.0", "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "base-x": "^5.0.0" } }, - "node_modules/eslint-plugin-jsdoc": { - "version": "63.3.3", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/bs58check": { + "version": "4.0.0", + "license": "MIT", "dependencies": { - "@es-joy/jsdoccomment": "~0.91.0", - "@es-joy/resolve.exports": "1.2.0", - "are-docs-informative": "^0.0.2", - "comment-parser": "1.4.7", - "debug": "^4.4.3", - "escape-string-regexp": "^4.0.0", - "espree": "^11.2.0", - "esquery": "^1.7.0", - "html-entities": "^2.6.0", - "object-deep-merge": "^2.0.1", - "parse-imports-exports": "^0.2.4", - "semver": "^7.8.5", - "spdx-expression-parse": "^5.0.0", - "to-valid-identifier": "^1.0.0" - }, - "engines": { - "node": "^22.13.0 || >=24" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0" + "@noble/hashes": "^1.2.0", + "bs58": "^6.0.0" } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "7.1.1", - "dev": true, + "node_modules/bs58check/node_modules/@noble/hashes": { + "version": "1.8.0", "license": "MIT", - "dependencies": { - "@babel/core": "^7.24.4", - "@babel/parser": "^7.24.4", - "hermes-parser": "^0.25.1", - "zod": "^3.25.0 || ^4.0.0", - "zod-validation-error": "^3.5.0 || ^4.0.0" - }, "engines": { - "node": ">=18" + "node": "^14.21.3 || >=16" }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/eslint-plugin-unused-imports": { - "version": "4.4.1", + "node_modules/bundle-name": { + "version": "4.1.0", "dev": true, "license": "MIT", - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", - "eslint": "^10.0.0 || ^9.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "9.1.2", - "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "@types/esrecurse": "^4.3.1", - "@types/estree": "^1.0.8", - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "run-applescript": "^7.0.0" }, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": ">=18" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "dev": true, - "license": "Apache-2.0", + "node_modules/bytes": { + "version": "3.1.2", + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">= 0.8" } }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.14.0", + "node_modules/call-bind": { + "version": "1.0.8", "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" + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "dev": true, - "license": "Apache-2.0", "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint/node_modules/ignore": { - "version": "5.3.2", - "dev": true, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, "engines": { - "node": ">= 4" + "node": ">= 0.4" } }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/espree": { - "version": "11.2.0", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/call-bound": { + "version": "1.0.4", + "license": "MIT", "dependencies": { - "acorn": "^8.16.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^5.0.1" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "5.0.1", + "node_modules/callsites": { + "version": "3.1.0", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=6" } }, - "node_modules/esprima": { - "version": "4.0.1", - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, + "node_modules/camelcase": { + "version": "5.3.1", + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/esquery": { - "version": "1.7.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" + "node_modules/caniuse-lite": { + "version": "1.0.30001809", + "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/ccount": { + "version": "2.0.1", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/esrecurse": { - "version": "4.3.0", + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">=18" } }, - "node_modules/estraverse": { - "version": "5.3.0", + "node_modules/chalk": { + "version": "6.0.0", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">=22" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/estree-util-attach-comments": { - "version": "3.0.0", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - }, + "node_modules/character-entities": { + "version": "2.0.2", + "license": "MIT", "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/estree-util-build-jsx": { - "version": "3.0.1", + "node_modules/character-entities-html4": { + "version": "2.1.0", "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "estree-walker": "^3.0.0" - }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/estree-util-is-identifier-name": { + "node_modules/character-entities-legacy": { "version": "3.0.0", "license": "MIT", "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/estree-util-scope": { - "version": "1.0.0", + "node_modules/character-reference-invalid": { + "version": "2.0.1", "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "license": "Apache-2.0", "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0" + "clsx": "^2.1.1" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://polar.sh/cva" } }, - "node_modules/estree-util-to-js": { - "version": "2.0.0", + "node_modules/cli-cursor": { + "version": "5.0.0", + "dev": true, "license": "MIT", "dependencies": { - "@types/estree-jsx": "^1.0.0", - "astring": "^1.8.0", - "source-map": "^0.7.0" + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/estree-util-visit": { - "version": "2.0.0", + "node_modules/cli-spinners": { + "version": "2.9.2", + "dev": true, "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/unist": "^3.0.0" + "engines": { + "node": ">=6" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/estree-walker": { - "version": "3.0.3", + "node_modules/client-only": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cmdk": { + "version": "1.1.1", "license": "MIT", "dependencies": { - "@types/estree": "^1.0.0" + "@radix-ui/react-compose-refs": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-id": "^1.1.0", + "@radix-ui/react-primitive": "^2.0.2" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, - "node_modules/esutils": { - "version": "2.0.3", + "node_modules/code-block-writer": { + "version": "13.0.3", "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/etag": { - "version": "1.8.1", + "node_modules/collapse-white-space": { + "version": "2.1.0", "license": "MIT", - "engines": { - "node": ">= 0.6" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/eventsource": { - "version": "3.0.7", + "node_modules/color-convert": { + "version": "2.0.1", "license": "MIT", "dependencies": { - "eventsource-parser": "^3.0.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">=18.0.0" + "node": ">=7.0.0" } }, - "node_modules/eventsource-parser": { - "version": "3.0.6", + "node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/comment-parser": { + "version": "1.4.7", + "dev": true, "license": "MIT", "engines": { - "node": ">=18.0.0" + "node": ">= 12.0.0" } }, - "node_modules/execa": { - "version": "5.1.1", + "node_modules/concat-map": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/concurrently": { + "version": "10.0.4", "dev": true, "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "chalk": "5.6.2", + "rxjs": "7.8.2", + "shell-quote": "1.9.0", + "supports-color": "10.2.2", + "tree-kill": "1.2.2", + "yargs": "18.0.0" + }, + "bin": { + "conc": "dist/bin/index.js", + "concurrently": "dist/bin/index.js" }, "engines": { - "node": ">=10" + "node": ">=22" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, - "node_modules/execa/node_modules/signal-exit": { - "version": "3.0.7", + "node_modules/concurrently/node_modules/ansi-regex": { + "version": "6.3.0", "dev": true, - "license": "ISC" + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } }, - "node_modules/exit-x": { - "version": "0.2.2", + "node_modules/concurrently/node_modules/ansi-styles": { + "version": "6.2.3", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/expect": { - "version": "30.3.0", + "node_modules/concurrently/node_modules/chalk": { + "version": "5.6.2", "dev": true, "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/cliui": { + "version": "9.0.1", + "dev": true, + "license": "ISC", "dependencies": { - "@jest/expect-utils": "30.3.0", - "@jest/get-type": "30.1.0", - "jest-matcher-utils": "30.3.0", - "jest-message-util": "30.3.0", - "jest-mock": "30.3.0", - "jest-util": "30.3.0" + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=20" } }, - "node_modules/express": { - "version": "5.2.1", + "node_modules/concurrently/node_modules/emoji-regex": { + "version": "10.6.0", + "dev": true, + "license": "MIT" + }, + "node_modules/concurrently/node_modules/string-width": { + "version": "7.2.0", + "dev": true, "license": "MIT", "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.1", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "depd": "^2.0.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" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">= 18" + "node": ">=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/express-rate-limit": { - "version": "8.5.2", + "node_modules/concurrently/node_modules/strip-ansi": { + "version": "7.2.0", + "dev": true, "license": "MIT", "dependencies": { - "ip-address": "^10.2.0" + "ansi-regex": "^6.2.2" }, "engines": { - "node": ">= 16" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/express-rate-limit" - }, - "peerDependencies": { - "express": ">= 4.11" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/express/node_modules/cookie": { - "version": "0.7.2", + "node_modules/concurrently/node_modules/supports-color": { + "version": "10.2.2", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/extend": { - "version": "3.0.2", - "license": "MIT" - }, - "node_modules/extend-shallow": { - "version": "2.0.1", + "node_modules/concurrently/node_modules/wrap-ansi": { + "version": "9.0.2", + "dev": true, "license": "MIT", "dependencies": { - "is-extendable": "^0.1.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/fast-content-type-parse": { - "version": "3.0.0", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.1", + "node_modules/concurrently/node_modules/yargs": { + "version": "18.0.0", "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.4" + "cliui": "^9.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "string-width": "^7.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^22.0.0" }, "engines": { - "node": ">=8.6.0" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", + "node_modules/concurrently/node_modules/yargs-parser": { + "version": "22.0.0", "dev": true, "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, "engines": { - "node": ">= 6" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "dev": true, - "license": "MIT" + "node_modules/content-disposition": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", + "node_modules/content-type": { + "version": "1.0.5", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", "dev": true, "license": "MIT" }, - "node_modules/fast-sha256": { - "version": "1.3.0", - "license": "Unlicense" - }, - "node_modules/fast-uri": { - "version": "3.1.5", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" + "node_modules/cookie": { + "version": "1.1.1", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } }, - "node_modules/fastq": { - "version": "1.19.1", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" + "node_modules/cookie-signature": { + "version": "1.2.2", + "license": "MIT", + "engines": { + "node": ">=6.6.0" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "dev": true, - "license": "Apache-2.0", + "node_modules/cors": { + "version": "2.8.5", + "license": "MIT", "dependencies": { - "bser": "2.1.1" + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" } }, - "node_modules/fetch-blob": { - "version": "3.2.0", + "node_modules/cosmiconfig": { + "version": "9.0.0", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], "license": "MIT", "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" }, "engines": { - "node": "^12.20 || >= 14.13" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/figures": { - "version": "6.1.0", - "dev": true, + "node_modules/critters": { + "version": "0.0.23", + "license": "Apache-2.0", + "dependencies": { + "chalk": "^4.1.0", + "css-select": "^5.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.2", + "htmlparser2": "^8.0.2", + "postcss": "^8.4.23", + "postcss-media-query-parser": "^0.2.3" + } + }, + "node_modules/critters/node_modules/ansi-styles": { + "version": "4.3.0", "license": "MIT", "dependencies": { - "is-unicode-supported": "^2.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=18" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "dev": true, + "node_modules/critters/node_modules/chalk": { + "version": "4.1.2", "license": "MIT", "dependencies": { - "flat-cache": "^4.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "dev": true, + "node_modules/critters/node_modules/supports-color": { + "version": "7.2.0", "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/finalhandler": { - "version": "2.1.1", + "node_modules/cross-spawn": { + "version": "7.0.6", "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" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">= 18.0.0" + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/find-up": { - "version": "5.0.0", + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" }, "engines": { - "node": ">=10" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/flat-cache": { - "version": "4.0.1", + "node_modules/css.escape": { + "version": "1.5.1", + "dev": true, + "license": "MIT" + }, + "node_modules/cssesc": { + "version": "3.0.0", "dev": true, "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" + "bin": { + "cssesc": "bin/cssesc" }, "engines": { - "node": ">=16" + "node": ">=4" } }, - "node_modules/flatted": { - "version": "3.4.3", + "node_modules/csstype": { + "version": "3.2.3", + "license": "MIT" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", "dev": true, - "license": "ISC" + "license": "BSD-2-Clause" }, - "node_modules/focus-lock": { - "version": "1.3.6", + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "dev": true, "license": "MIT", - "dependencies": { - "tslib": "^2.0.3" - }, "engines": { - "node": ">=10" - } - }, - "node_modules/focus-trap": { - "version": "7.8.0", - "license": "MIT", - "dependencies": { - "tabbable": "^6.4.0" + "node": ">= 12" } }, - "node_modules/focus-trap-react": { - "version": "11.0.6", + "node_modules/data-urls": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", + "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", + "dev": true, "license": "MIT", "dependencies": { - "focus-trap": "^7.8.0", - "tabbable": "^6.4.0" + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.0" }, - "peerDependencies": { - "@types/react": "^18.0.0 || ^19.0.0", - "@types/react-dom": "^18.0.0 || ^19.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/for-each": { - "version": "0.3.5", + "node_modules/data-view-buffer": { + "version": "1.0.2", "dev": true, "license": "MIT", "dependencies": { - "is-callable": "^1.2.7" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10219,197 +7821,176 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "license": "ISC", + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "dev": true, + "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" }, "engines": { - "node": ">=14" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/inspect-js" } }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", + "node_modules/data-view-byte-offset": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "fetch-blob": "^3.1.2" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fraction.js": { - "version": "5.3.4", + "node_modules/date-fns": { + "version": "4.1.0", "license": "MIT", - "engines": { - "node": "*" - }, "funding": { "type": "github", - "url": "https://github.com/sponsors/rawify" + "url": "https://github.com/sponsors/kossnocorp" } }, - "node_modules/framer-motion": { - "version": "13.1.1", + "node_modules/debounce": { + "version": "1.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", "license": "MIT", "dependencies": { - "motion-dom": "^13.1.1", - "motion-utils": "^13.0.0", - "tslib": "^2.4.0" + "ms": "^2.1.3" }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" + "engines": { + "node": ">=6.0" }, "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { + "supports-color": { "optional": true } } }, - "node_modules/fresh": { - "version": "2.0.0", + "node_modules/decamelize": { + "version": "1.2.0", "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/fs-extra": { - "version": "11.3.2", + "node_modules/decimal.js": { + "version": "10.6.0", "dev": true, + "license": "MIT" + }, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "character-entities": "^2.0.0" }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "dev": true, - "license": "ISC" - }, - "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", - "license": "MIT", "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/function.prototype.name": { - "version": "1.1.8", + "node_modules/dedent": { + "version": "1.7.0", "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } } }, - "node_modules/functions-have-names": { - "version": "1.2.3", + "node_modules/deep-is": { + "version": "0.1.4", "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, - "node_modules/fuzzysort": { - "version": "3.1.0", + "node_modules/deepmerge": { + "version": "4.3.1", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/generator-function": { - "version": "2.0.1", + "node_modules/default-browser": { + "version": "5.4.0", "dev": true, "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", + "node_modules/default-browser-id": { + "version": "5.0.1", "dev": true, "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "license": "ISC", + "node_modules/define-data-property": { + "version": "1.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-east-asian-width": { - "version": "1.4.0", + "node_modules/define-lazy-prop": { + "version": "3.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", + "node_modules/define-properties": { + "version": "1.2.1", + "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" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -10418,251 +7999,300 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-nonce": { - "version": "1.0.1", + "node_modules/depd": { + "version": "2.0.0", "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.8" } }, - "node_modules/get-own-enumerable-keys": { - "version": "1.0.0", - "dev": true, + "node_modules/dequal": { + "version": "2.0.3", "license": "MIT", "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "dev": true, - "license": "MIT", + "node_modules/detect-libc": { + "version": "2.1.2", + "devOptional": true, + "license": "Apache-2.0", "engines": { - "node": ">=8.0.0" + "node": ">=8" } }, - "node_modules/get-proto": { - "version": "1.0.1", + "node_modules/detect-node-es": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" + "dequal": "^2.0.0" }, - "engines": { - "node": ">= 0.4" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/get-stream": { - "version": "6.0.1", + "node_modules/diff": { + "version": "8.0.3", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.3.1" } }, - "node_modules/get-symbol-description": { - "version": "1.1.0", + "node_modules/dijkstrajs": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "2.1.0", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" + "esutils": "^2.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/get-tsconfig": { - "version": "4.13.7", + "node_modules/dom-accessibility-api": { + "version": "0.5.16", "dev": true, + "license": "MIT" + }, + "node_modules/dom-serializer": { + "version": "2.0.0", "license": "MIT", "dependencies": { - "resolve-pkg-maps": "^1.0.0" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" }, "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/glob": { - "version": "11.1.0", - "license": "BlueOak-1.0.0", + "node_modules/domelementtype": { + "version": "2.3.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "license": "BSD-2-Clause", "dependencies": { - "foreground-child": "^3.3.1", - "jackspeak": "^4.1.1", - "minimatch": "^10.1.1", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "domelementtype": "^2.3.0" }, "engines": { - "node": "20 || >=22" + "node": ">= 4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" + "node_modules/dompurify": { + "version": "3.4.13", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" } }, - "node_modules/globalthis": { - "version": "1.0.4", - "dev": true, - "license": "MIT", + "node_modules/domutils": { + "version": "3.2.2", + "license": "BSD-2-Clause", "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/gopd": { - "version": "1.2.0", - "license": "MIT", + "node_modules/dotenv": { + "version": "16.6.1", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://dotenvx.com" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "dev": true, - "license": "ISC" - }, - "node_modules/gray-matter": { - "version": "4.0.3", + "node_modules/dunder-proto": { + "version": "1.0.1", "license": "MIT", "dependencies": { - "js-yaml": "^3.13.1", - "kind-of": "^6.0.2", - "section-matter": "^1.0.0", - "strip-bom-string": "^1.0.0" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, "engines": { - "node": ">=6.0" + "node": ">= 0.4" } }, - "node_modules/gray-matter/node_modules/argparse": { - "version": "1.0.10", - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } + "node_modules/duplexer": { + "version": "0.1.2", + "dev": true, + "license": "MIT" }, - "node_modules/gray-matter/node_modules/js-yaml": { - "version": "3.15.1", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "license": "MIT" + }, + "node_modules/eciesjs": { + "version": "0.4.16", + "dev": true, "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "@ecies/ciphers": "^0.2.4", + "@noble/ciphers": "^1.3.0", + "@noble/curves": "^1.9.7", + "@noble/hashes": "^1.8.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "bun": ">=1", + "deno": ">=2", + "node": ">=16" } }, - "node_modules/gzip-size": { - "version": "6.0.0", + "node_modules/eciesjs/node_modules/@noble/hashes": { + "version": "1.8.0", "dev": true, "license": "MIT", - "dependencies": { - "duplexer": "^0.1.2" - }, "engines": { - "node": ">=10" + "node": "^14.21.3 || >=16" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/handlebars": { - "version": "4.7.9", - "dev": true, + "node_modules/ee-first": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.406", + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" + "node": ">= 0.8" } }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", + "node_modules/enhanced-resolve": { + "version": "5.24.5", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" } }, - "node_modules/has-bigints": { - "version": "1.1.0", - "dev": true, - "license": "MIT", + "node_modules/entities": { + "version": "4.5.0", + "license": "BSD-2-Clause", "engines": { - "node": ">= 0.4" + "node": ">=0.12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/has-flag": { - "version": "4.0.0", + "node_modules/env-paths": { + "version": "2.2.1", + "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", + "node_modules/error-ex": { + "version": "1.3.4", "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "is-arrayish": "^0.2.1" } }, - "node_modules/has-proto": { - "version": "1.2.0", + "node_modules/es-abstract": { + "version": "1.24.1", "dev": true, "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.0" + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" }, "engines": { "node": ">= 0.4" @@ -10671,2491 +8301,2481 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-symbols": { - "version": "1.1.0", + "node_modules/es-define-property": { + "version": "1.0.1", "license": "MIT", "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "dev": true, + "node_modules/es-errors": { + "version": "1.3.0", "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hasown": { - "version": "2.0.2", + "node_modules/es-iterator-helpers": { + "version": "1.3.1", + "dev": true, "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.1", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0", + "safe-array-concat": "^1.1.3" }, "engines": { "node": ">= 0.4" } }, - "node_modules/hast-util-sanitize": { - "version": "5.0.2", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@ungap/structured-clone": "^1.0.0", - "unist-util-position": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-estree": { - "version": "3.1.3", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-attach-comments": "^3.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-js": "^1.0.0", - "unist-util-position": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-jsx-runtime": { - "version": "2.3.6", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-js": "^1.0.0", - "unist-util-position": "^5.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } + "node_modules/es-module-lexer": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", + "dev": true, + "license": "MIT" }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", + "node_modules/es-object-atoms": { + "version": "1.1.1", "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0" + "es-errors": "^1.3.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 0.4" } }, - "node_modules/hermes-estree": { - "version": "0.25.1", - "dev": true, - "license": "MIT" - }, - "node_modules/hermes-parser": { - "version": "0.25.1", + "node_modules/es-set-tostringtag": { + "version": "2.1.0", "dev": true, "license": "MIT", "dependencies": { - "hermes-estree": "0.25.1" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/hono": { - "version": "4.13.4", + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "dev": true, "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, "engines": { - "node": ">=16.9.0" + "node": ">= 0.4" } }, - "node_modules/html-encoding-sniffer": { - "version": "4.0.0", + "node_modules/es-to-primitive": { + "version": "1.3.0", "dev": true, "license": "MIT", "dependencies": { - "whatwg-encoding": "^3.1.1" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/html-entities": { - "version": "2.6.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ], - "license": "MIT" - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/html-url-attributes": { - "version": "3.0.1", + "node_modules/esast-util-from-estree": { + "version": "2.0.0", "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0" + }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/htmlparser2": { - "version": "8.0.2", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], + "node_modules/esast-util-from-js": { + "version": "2.0.1", "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/http-errors": { - "version": "2.0.1", + "node_modules/escalade": { + "version": "3.2.0", "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, "engines": { - "node": ">= 0.8" + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", + "node_modules/eslint": { + "version": "10.8.1", "dev": true, "license": "MIT", + "workspaces": [ + "packages/*" + ], "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.7.0", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.2", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.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", + "minimatch": "^10.2.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">= 14" + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", + "node_modules/eslint-config-next": { + "version": "16.3.1", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" + "@next/eslint-plugin-next": "16.3.1", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^7.0.0", + "globals": "16.4.0", + "typescript-eslint": "^8.46.0" }, - "engines": { - "node": ">= 14" + "peerDependencies": { + "eslint": ">=9.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/human-signals": { - "version": "2.1.0", + "node_modules/eslint-config-next/node_modules/aria-query": { + "version": "5.3.2", "dev": true, "license": "Apache-2.0", "engines": { - "node": ">=10.17.0" + "node": ">= 0.4" } }, - "node_modules/husky": { - "version": "9.1.7", + "node_modules/eslint-config-next/node_modules/brace-expansion": { + "version": "1.1.18", "dev": true, "license": "MIT", - "bin": { - "husky": "bin.js" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-config-next/node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" }, "engines": { - "node": ">=18" + "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/iceberg-js": { - "version": "0.8.1", - "license": "MIT", - "engines": { - "node": ">=20.0.0" + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } } }, - "node_modules/iconv-lite": { - "version": "0.7.2", + "node_modules/eslint-config-next/node_modules/eslint-plugin-import": { + "version": "2.32.0", + "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, - "node_modules/ignore": { - "version": "7.0.5", + "node_modules/eslint-config-next/node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", "dev": true, "license": "MIT", - "engines": { - "node": ">= 4" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/import-fresh": { - "version": "3.3.1", + "node_modules/eslint-config-next/node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", "dev": true, "license": "MIT", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" }, "engines": { - "node": ">=6" + "node": ">=4.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, - "node_modules/import-local": { - "version": "3.2.0", + "node_modules/eslint-config-next/node_modules/eslint-plugin-react": { + "version": "7.37.5", "dev": true, "license": "MIT", "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "node_modules/indent-string": { - "version": "4.0.0", + "node_modules/eslint-config-next/node_modules/globals": { + "version": "16.4.0", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/inflight": { - "version": "1.0.6", + "node_modules/eslint-config-next/node_modules/minimatch": { + "version": "3.1.5", "dev": true, "license": "ISC", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "node_modules/inherits": { - "version": "2.0.4", - "license": "ISC" - }, - "node_modules/inline-style-parser": { - "version": "0.2.7", - "license": "MIT" - }, - "node_modules/internal-slot": { - "version": "1.1.0", + "node_modules/eslint-config-next/node_modules/resolve": { + "version": "2.0.0-next.6", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" + "is-core-module": "^2.16.1", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ip-address": { - "version": "10.4.0", - "license": "MIT", - "engines": { - "node": ">= 12" + "node_modules/eslint-config-next/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/ipaddr.js": { - "version": "1.9.1", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.10" + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, - "node_modules/is-alphabetical": { - "version": "2.0.1", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/is-alphanumerical": { - "version": "2.0.1", + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "dev": true, "license": "MIT", "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" + "debug": "^3.2.7" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/is-array-buffer": { - "version": "3.0.5", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-jsdoc": { + "version": "63.3.3", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.91.0", + "@es-joy/resolve.exports": "1.2.0", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.7", + "debug": "^4.4.3", + "escape-string-regexp": "^4.0.0", + "espree": "^11.2.0", + "esquery": "^1.7.0", + "html-entities": "^2.6.0", + "object-deep-merge": "^2.0.1", + "parse-imports-exports": "^0.2.4", + "semver": "^7.8.5", + "spdx-expression-parse": "^5.0.0", + "to-valid-identifier": "^1.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^22.13.0 || >=24" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/is-async-function": { - "version": "2.1.1", + "node_modules/eslint-plugin-react-hooks": { + "version": "7.1.1", "dev": true, "license": "MIT", "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" } }, - "node_modules/is-bigint": { - "version": "1.1.0", + "node_modules/eslint-plugin-unused-imports": { + "version": "4.4.1", "dev": true, "license": "MIT", + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", + "eslint": "^10.0.0 || ^9.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "9.1.2", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "has-bigints": "^1.0.2" + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 0.4" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/is-boolean-object": { - "version": "1.2.2", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, + "license": "Apache-2.0", "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/is-bun-module": { - "version": "2.0.0", + "node_modules/eslint/node_modules/ajv": { + "version": "6.14.0", "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.7.1" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" + "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": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/is-core-module": { - "version": "2.16.1", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "5.0.1", "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, + "license": "Apache-2.0", "engines": { - "node": ">= 0.4" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/is-data-view": { - "version": "1.0.2", + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 4" } }, - "node_modules/is-date-object": { - "version": "1.1.0", + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/espree": { + "version": "11.2.0", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" }, "engines": { - "node": ">= 0.4" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-decimal": { - "version": "2.0.1", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://opencollective.com/eslint" } }, - "node_modules/is-docker": { - "version": "3.0.0", + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "5.0.1", "dev": true, - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, + "license": "Apache-2.0", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/is-extendable": { - "version": "0.1.1", - "license": "MIT", + "node_modules/esprima": { + "version": "4.0.1", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/is-extglob": { - "version": "2.1.1", + "node_modules/esquery": { + "version": "1.7.0", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=0.10" } }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", + "node_modules/esrecurse": { + "version": "4.3.0", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "call-bound": "^1.0.3" + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4.0" } }, - "node_modules/is-generator-fn": { - "version": "2.1.0", + "node_modules/estraverse": { + "version": "5.3.0", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "engines": { - "node": ">=6" + "node": ">=4.0" } }, - "node_modules/is-generator-function": { - "version": "1.1.2", - "dev": true, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", "license": "MIT", "dependencies": { - "call-bound": "^1.0.4", - "generator-function": "^2.0.0", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" + "@types/estree": "^1.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "dev": true, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/is-hexadecimal": { - "version": "2.0.1", + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", "license": "MIT", "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/is-in-ssh": { + "node_modules/estree-util-scope": { "version": "1.0.0", - "dev": true, "license": "MIT", - "engines": { - "node": ">=20" + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "dev": true, + "node_modules/estree-util-to-js": { + "version": "2.0.0", "license": "MIT", "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" }, - "engines": { - "node": ">=14.16" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" } }, - "node_modules/is-interactive": { - "version": "2.0.0", - "dev": true, + "node_modules/eventsource": { + "version": "3.0.7", "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "eventsource-parser": "^3.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/is-map": { - "version": "2.0.3", - "dev": true, + "node_modules/eventsource-parser": { + "version": "3.0.6", "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18.0.0" } }, - "node_modules/is-negative-zero": { - "version": "2.0.3", + "node_modules/execa": { + "version": "5.1.1", "dev": true, "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/is-number": { - "version": "7.0.0", + "node_modules/execa/node_modules/signal-exit": { + "version": "3.0.7", "dev": true, - "license": "MIT", + "license": "ISC" + }, + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=0.12.0" + "node": ">=12.0.0" } }, - "node_modules/is-number-object": { - "version": "1.1.1", - "dev": true, + "node_modules/express": { + "version": "5.2.1", "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.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": ">= 0.4" + "node": ">= 18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/is-obj": { - "version": "3.0.0", - "dev": true, + "node_modules/express-rate-limit": { + "version": "8.5.2", "license": "MIT", + "dependencies": { + "ip-address": "^10.2.0" + }, "engines": { - "node": ">=12" + "node": ">= 16" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" } }, - "node_modules/is-plain-obj": { - "version": "4.1.0", + "node_modules/express/node_modules/cookie": { + "version": "0.7.2", "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "dev": true, + "node_modules/extend": { + "version": "3.0.2", + "license": "MIT" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "dev": true, + "node_modules/fast-content-type-parse": { + "version": "3.0.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT" }, - "node_modules/is-promise": { - "version": "4.0.0", + "node_modules/fast-deep-equal": { + "version": "3.1.3", "license": "MIT" }, - "node_modules/is-regex": { - "version": "1.2.1", + "node_modules/fast-glob": { + "version": "3.3.1", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8.6.0" } }, - "node_modules/is-regexp": { - "version": "3.1.0", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">= 6" } }, - "node_modules/is-set": { - "version": "2.0.3", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", + "node_modules/fast-levenshtein": { + "version": "2.0.6", "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, - "node_modules/is-stream": { - "version": "2.0.1", + "node_modules/fast-sha256": { + "version": "1.3.0", + "license": "Unlicense" + }, + "node_modules/fast-uri": { + "version": "3.1.5", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.19.1", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" } }, - "node_modules/is-string": { - "version": "1.1.1", + "node_modules/fetch-blob": { + "version": "3.2.0", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^12.20 || >= 14.13" } }, - "node_modules/is-symbol": { - "version": "1.1.1", + "node_modules/figures": { + "version": "6.1.0", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" + "is-unicode-supported": "^2.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-typed-array": { - "version": "1.1.15", + "node_modules/file-entry-cache": { + "version": "8.0.0", "dev": true, "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.16" + "flat-cache": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=16.0.0" } }, - "node_modules/is-unicode-supported": { - "version": "2.1.0", + "node_modules/fill-range": { + "version": "7.1.1", "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "to-regex-range": "^5.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "dev": true, - "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-weakref": { - "version": "1.1.1", - "dev": true, + "node_modules/finalhandler": { + "version": "2.1.1", "license": "MIT", "dependencies": { - "call-bound": "^1.0.3" + "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.4" + "node": ">= 18.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/is-weakset": { - "version": "2.0.4", + "node_modules/find-up": { + "version": "5.0.0", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-wsl": { - "version": "3.1.0", + "node_modules/flat-cache": { + "version": "4.0.1", "dev": true, "license": "MIT", "dependencies": { - "is-inside-container": "^1.0.0" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/isarray": { - "version": "2.0.5", + "node_modules/flatted": { + "version": "3.4.3", "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", "license": "ISC" }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/focus-lock": { + "version": "1.3.6", + "license": "MIT", "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" + "tslib": "^2.0.3" }, "engines": { "node": ">=10" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/focus-trap": { + "version": "7.8.0", + "license": "MIT", "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "tabbable": "^6.4.0" } }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, + "node_modules/focus-trap-react": { + "version": "11.0.6", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "focus-trap": "^7.8.0", + "tabbable": "^6.4.0" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "5.0.6", + "node_modules/for-each": { + "version": "0.3.5", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.23", - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0" + "is-callable": "^1.2.7" }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/foreground-child": { + "version": "3.3.1", + "license": "ISC", "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=8" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/iterator.prototype": { - "version": "1.1.5", + "node_modules/formdata-polyfill": { + "version": "4.0.10", "dev": true, "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "get-proto": "^1.0.0", - "has-symbols": "^1.1.0", - "set-function-name": "^2.0.2" + "fetch-blob": "^3.1.2" }, "engines": { - "node": ">= 0.4" + "node": ">=12.20.0" } }, - "node_modules/jackspeak": { - "version": "4.1.1", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, + "node_modules/forwarded": { + "version": "0.2.0", + "license": "MIT", "engines": { - "node": "20 || >=22" + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "license": "MIT", + "engines": { + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "github", + "url": "https://github.com/sponsors/rawify" } }, - "node_modules/jest": { - "version": "30.3.0", - "dev": true, + "node_modules/framer-motion": { + "version": "13.1.1", "license": "MIT", "dependencies": { - "@jest/core": "30.3.0", - "@jest/types": "30.3.0", - "import-local": "^3.2.0", - "jest-cli": "30.3.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "motion-dom": "^13.1.1", + "motion-utils": "^13.0.0", + "tslib": "^2.4.0" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { - "node-notifier": { + "react": { + "optional": true + }, + "react-dom": { "optional": true } } }, - "node_modules/jest-changed-files": { - "version": "30.3.0", - "dev": true, + "node_modules/fresh": { + "version": "2.0.0", "license": "MIT", - "dependencies": { - "execa": "^5.1.1", - "jest-util": "30.3.0", - "p-limit": "^3.1.0" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.8" } }, - "node_modules/jest-circus": { - "version": "30.3.0", + "node_modules/fs-extra": { + "version": "11.3.2", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.3.0", - "@jest/expect": "30.3.0", - "@jest/test-result": "30.3.0", - "@jest/types": "30.3.0", - "@types/node": "*", - "chalk": "^4.1.2", - "co": "^4.6.0", - "dedent": "^1.6.0", - "is-generator-fn": "^2.1.0", - "jest-each": "30.3.0", - "jest-matcher-utils": "30.3.0", - "jest-message-util": "30.3.0", - "jest-runtime": "30.3.0", - "jest-snapshot": "30.3.0", - "jest-util": "30.3.0", - "p-limit": "^3.1.0", - "pretty-format": "30.3.0", - "pure-rand": "^7.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=14.14" } }, - "node_modules/jest-circus/node_modules/chalk": { - "version": "4.1.2", + "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", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=10" - }, + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "license": "MIT", "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-circus/node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/function.prototype.name": { + "version": "1.1.8", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-circus/node_modules/pretty-format": { - "version": "30.3.0", + "node_modules/functions-have-names": { + "version": "1.2.3", "dev": true, "license": "MIT", - "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-circus/node_modules/react-is": { - "version": "18.3.1", + "node_modules/fuzzysort": { + "version": "3.1.0", "dev": true, "license": "MIT" }, - "node_modules/jest-circus/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/generator-function": { + "version": "2.0.1", "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/jest-cli": { - "version": "30.3.0", + "node_modules/gensync": { + "version": "1.0.0-beta.2", "dev": true, "license": "MIT", - "dependencies": { - "@jest/core": "30.3.0", - "@jest/test-result": "30.3.0", - "@jest/types": "30.3.0", - "chalk": "^4.1.2", - "exit-x": "^0.2.2", - "import-local": "^3.2.0", - "jest-config": "30.3.0", - "jest-util": "30.3.0", - "jest-validate": "30.3.0", - "yargs": "^17.7.2" - }, - "bin": { - "jest": "bin/jest.js" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">=6.9.0" } }, - "node_modules/jest-cli/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/get-caller-file": { + "version": "2.0.5", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-cli/node_modules/chalk": { - "version": "4.1.2", - "dev": true, + "node_modules/get-intrinsic": { + "version": "1.3.0", "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "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": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-cli/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, + "node_modules/get-nonce": { + "version": "1.0.1", "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/jest-config": { - "version": "30.3.0", + "node_modules/get-own-enumerable-keys": { + "version": "1.0.0", "dev": true, "license": "MIT", - "dependencies": { - "@babel/core": "^7.27.4", - "@jest/get-type": "30.1.0", - "@jest/pattern": "30.0.1", - "@jest/test-sequencer": "30.3.0", - "@jest/types": "30.3.0", - "babel-jest": "30.3.0", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "deepmerge": "^4.3.1", - "glob": "^10.5.0", - "graceful-fs": "^4.2.11", - "jest-circus": "30.3.0", - "jest-docblock": "30.2.0", - "jest-environment-node": "30.3.0", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.3.0", - "jest-runner": "30.3.0", - "jest-util": "30.3.0", - "jest-validate": "30.3.0", - "parse-json": "^5.2.0", - "pretty-format": "30.3.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "esbuild-register": ">=3.4.0", - "ts-node": ">=9.0.0" + "engines": { + "node": ">=14.16" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "esbuild-register": { - "optional": true - }, - "ts-node": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-config/node_modules/brace-expansion": { - "version": "2.1.4", - "dev": true, + "node_modules/get-proto": { + "version": "1.0.1", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/jest-config/node_modules/chalk": { - "version": "4.1.2", + "node_modules/get-stream": { + "version": "6.0.1", "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" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-config/node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/get-symbol-description": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-config/node_modules/glob": { - "version": "10.5.0", + "node_modules/get-tsconfig": { + "version": "4.13.7", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "resolve-pkg-maps": "^1.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/jest-config/node_modules/jackspeak": { - "version": "3.4.3", - "dev": true, + "node_modules/glob": { + "version": "11.1.0", "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/jest-config/node_modules/lru-cache": { - "version": "10.4.3", - "dev": true, - "license": "ISC" - }, - "node_modules/jest-config/node_modules/minimatch": { - "version": "9.0.9", + "node_modules/glob-parent": { + "version": "6.0.2", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.2" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10.13.0" } }, - "node_modules/jest-config/node_modules/path-scurry": { - "version": "1.11.1", + "node_modules/globalthis": { + "version": "1.0.4", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-config/node_modules/pretty-format": { - "version": "30.3.0", - "dev": true, + "node_modules/gopd": { + "version": "1.2.0", "license": "MIT", - "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-config/node_modules/react-is": { - "version": "18.3.1", + "node_modules/graceful-fs": { + "version": "4.2.11", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/jest-config/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, + "node_modules/gray-matter": { + "version": "4.0.3", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=6.0" } }, - "node_modules/jest-diff": { - "version": "30.3.0", - "dev": true, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", "license": "MIT", "dependencies": { - "@jest/diff-sequences": "30.3.0", - "@jest/get-type": "30.1.0", - "chalk": "^4.1.2", - "pretty-format": "30.3.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "sprintf-js": "~1.0.2" } }, - "node_modules/jest-diff/node_modules/chalk": { - "version": "4.1.2", - "dev": true, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.15.1", "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jest-diff/node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/gzip-size": { + "version": "6.0.0", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "duplexer": "^0.1.2" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-diff/node_modules/pretty-format": { - "version": "30.3.0", + "node_modules/has-bigints": { + "version": "1.1.0", "dev": true, "license": "MIT", - "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } - }, - "node_modules/jest-diff/node_modules/react-is": { - "version": "18.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/jest-diff/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, + }, + "node_modules/has-flag": { + "version": "4.0.0", "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/jest-docblock": { - "version": "30.2.0", + "node_modules/has-property-descriptors": { + "version": "1.0.2", "dev": true, "license": "MIT", "dependencies": { - "detect-newline": "^3.1.0" + "es-define-property": "^1.0.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-each": { - "version": "30.3.0", + "node_modules/has-proto": { + "version": "1.2.0", "dev": true, "license": "MIT", "dependencies": { - "@jest/get-type": "30.1.0", - "@jest/types": "30.3.0", - "chalk": "^4.1.2", - "jest-util": "30.3.0", - "pretty-format": "30.3.0" + "dunder-proto": "^1.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-each/node_modules/chalk": { - "version": "4.1.2", - "dev": true, + "node_modules/has-symbols": { + "version": "1.1.0", "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-each/node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/has-tostringtag": { + "version": "1.0.2", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "has-symbols": "^1.0.3" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-each/node_modules/pretty-format": { - "version": "30.3.0", - "dev": true, + "node_modules/hasown": { + "version": "2.0.2", "license": "MIT", "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" + "function-bind": "^1.1.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" } }, - "node_modules/jest-each/node_modules/react-is": { - "version": "18.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/jest-each/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, + "node_modules/hast-util-sanitize": { + "version": "5.0.2", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "@types/hast": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "unist-util-position": "^5.0.0" }, - "engines": { - "node": ">=8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-environment-jsdom": { - "version": "30.3.0", - "dev": true, + "node_modules/hast-util-to-estree": { + "version": "3.1.3", "license": "MIT", "dependencies": { - "@jest/environment": "30.3.0", - "@jest/environment-jsdom-abstract": "30.3.0", - "jsdom": "^26.1.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "canvas": "^3.0.0" + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-environment-node": { - "version": "30.3.0", - "dev": true, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", "license": "MIT", "dependencies": { - "@jest/environment": "30.3.0", - "@jest/fake-timers": "30.3.0", - "@jest/types": "30.3.0", - "@types/node": "*", - "jest-mock": "30.3.0", - "jest-util": "30.3.0", - "jest-validate": "30.3.0" + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-haste-map": { - "version": "30.3.0", - "dev": true, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", "license": "MIT", "dependencies": { - "@jest/types": "30.3.0", - "@types/node": "*", - "anymatch": "^3.1.3", - "fb-watchman": "^2.0.2", - "graceful-fs": "^4.2.11", - "jest-regex-util": "30.0.1", - "jest-util": "30.3.0", - "jest-worker": "30.3.0", - "picomatch": "^4.0.3", - "walker": "^1.0.8" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "@types/hast": "^3.0.0" }, - "optionalDependencies": { - "fsevents": "^2.3.3" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-haste-map/node_modules/picomatch": { - "version": "4.0.4", + "node_modules/hermes-estree": { + "version": "0.25.1", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } + "license": "MIT" }, - "node_modules/jest-leak-detector": { - "version": "30.3.0", + "node_modules/hermes-parser": { + "version": "0.25.1", "dev": true, "license": "MIT", "dependencies": { - "@jest/get-type": "30.1.0", - "pretty-format": "30.3.0" - }, + "hermes-estree": "0.25.1" + } + }, + "node_modules/hono": { + "version": "4.13.4", + "license": "MIT", "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=16.9.0" } }, - "node_modules/jest-leak-detector/node_modules/pretty-format": { - "version": "30.3.0", + "node_modules/html-encoding-sniffer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" + "@exodus/bytes": "^1.6.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/jest-leak-detector/node_modules/react-is": { - "version": "18.3.1", + "node_modules/html-entities": { + "version": "2.6.0", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], "license": "MIT" }, - "node_modules/jest-matcher-utils": { - "version": "30.3.0", + "node_modules/html-escaper": { + "version": "2.0.2", "dev": true, + "license": "MIT" + }, + "node_modules/html-url-attributes": { + "version": "3.0.1", "license": "MIT", - "dependencies": { - "@jest/get-type": "30.1.0", - "chalk": "^4.1.2", - "jest-diff": "30.3.0", - "pretty-format": "30.3.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-matcher-utils/node_modules/chalk": { - "version": "4.1.2", - "dev": true, + "node_modules/htmlparser2": { + "version": "8.0.2", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], "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" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" } }, - "node_modules/jest-matcher-utils/node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, + "node_modules/http-errors": { + "version": "2.0.1", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { - "node": ">=8" + "node": ">= 0.8" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/jest-matcher-utils/node_modules/pretty-format": { - "version": "30.3.0", + "node_modules/human-signals": { + "version": "2.1.0", "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" - }, + "license": "Apache-2.0", "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=10.17.0" } }, - "node_modules/jest-matcher-utils/node_modules/react-is": { - "version": "18.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/jest-matcher-utils/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/husky": { + "version": "9.1.7", "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" + "bin": { + "husky": "bin.js" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" } }, - "node_modules/jest-message-util": { - "version": "30.3.0", - "dev": true, + "node_modules/iceberg-js": { + "version": "0.8.1", "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@jest/types": "30.3.0", - "@types/stack-utils": "^2.0.3", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "picomatch": "^4.0.3", - "pretty-format": "30.3.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=20.0.0" } }, - "node_modules/jest-message-util/node_modules/chalk": { - "version": "4.1.2", - "dev": true, + "node_modules/iconv-lite": { + "version": "0.7.2", "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ignore": { + "version": "7.0.5", + "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">= 4" } }, - "node_modules/jest-message-util/node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/import-fresh": { + "version": "3.3.1", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-message-util/node_modules/picomatch": { - "version": "4.0.4", + "node_modules/imurmurhash": { + "version": "0.1.4", "dev": true, "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=0.8.19" } }, - "node_modules/jest-message-util/node_modules/pretty-format": { - "version": "30.3.0", + "node_modules/indent-string": { + "version": "4.0.0", "dev": true, "license": "MIT", - "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=8" } }, - "node_modules/jest-message-util/node_modules/react-is": { - "version": "18.3.1", - "dev": true, + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/inline-style-parser": { + "version": "0.2.7", "license": "MIT" }, - "node_modules/jest-message-util/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/internal-slot": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/jest-mock": { - "version": "30.3.0", - "dev": true, + "node_modules/ip-address": { + "version": "10.4.0", "license": "MIT", - "dependencies": { - "@jest/types": "30.3.0", - "@types/node": "*", - "jest-util": "30.3.0" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 12" } }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "dev": true, + "node_modules/ipaddr.js": { + "version": "1.9.1", "license": "MIT", "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } + "node": ">= 0.10" } }, - "node_modules/jest-regex-util": { - "version": "30.0.1", - "dev": true, + "node_modules/is-alphabetical": { + "version": "2.0.1", "license": "MIT", - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/jest-resolve": { - "version": "30.3.0", - "dev": true, + "node_modules/is-alphanumerical": { + "version": "2.0.1", "license": "MIT", "dependencies": { - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.3.0", - "jest-pnp-resolver": "^1.2.3", - "jest-util": "30.3.0", - "jest-validate": "30.3.0", - "slash": "^3.0.0", - "unrs-resolver": "^1.7.11" + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/jest-resolve-dependencies": { - "version": "30.3.0", + "node_modules/is-array-buffer": { + "version": "3.0.5", "dev": true, "license": "MIT", "dependencies": { - "jest-regex-util": "30.0.1", - "jest-snapshot": "30.3.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-resolve/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/is-arrayish": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-resolve/node_modules/chalk": { - "version": "4.1.2", + "node_modules/is-bigint": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "has-bigints": "^1.0.2" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-resolve/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/is-boolean-object": { + "version": "1.2.2", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-runner": { - "version": "30.3.0", + "node_modules/is-bun-module": { + "version": "2.0.0", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.3.0", - "@jest/environment": "30.3.0", - "@jest/test-result": "30.3.0", - "@jest/transform": "30.3.0", - "@jest/types": "30.3.0", - "@types/node": "*", - "chalk": "^4.1.2", - "emittery": "^0.13.1", - "exit-x": "^0.2.2", - "graceful-fs": "^4.2.11", - "jest-docblock": "30.2.0", - "jest-environment-node": "30.3.0", - "jest-haste-map": "30.3.0", - "jest-leak-detector": "30.3.0", - "jest-message-util": "30.3.0", - "jest-resolve": "30.3.0", - "jest-runtime": "30.3.0", - "jest-util": "30.3.0", - "jest-watcher": "30.3.0", - "jest-worker": "30.3.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "semver": "^7.7.1" } }, - "node_modules/jest-runner/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/is-callable": { + "version": "1.2.7", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-runner/node_modules/chalk": { - "version": "4.1.2", + "node_modules/is-core-module": { + "version": "2.16.1", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "hasown": "^2.0.2" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-runner/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/is-data-view": { + "version": "1.0.2", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-runtime": { - "version": "30.3.0", + "node_modules/is-date-object": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.3.0", - "@jest/fake-timers": "30.3.0", - "@jest/globals": "30.3.0", - "@jest/source-map": "30.0.1", - "@jest/test-result": "30.3.0", - "@jest/transform": "30.3.0", - "@jest/types": "30.3.0", - "@types/node": "*", - "chalk": "^4.1.2", - "cjs-module-lexer": "^2.1.0", - "collect-v8-coverage": "^1.0.2", - "glob": "^10.5.0", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.3.0", - "jest-message-util": "30.3.0", - "jest-mock": "30.3.0", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.3.0", - "jest-snapshot": "30.3.0", - "jest-util": "30.3.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-runtime/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/is-decimal": { + "version": "2.0.1", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" + "bin": { + "is-docker": "cli.js" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-runtime/node_modules/brace-expansion": { - "version": "2.1.4", + "node_modules/is-extendable": { + "version": "0.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/jest-runtime/node_modules/chalk": { - "version": "4.1.2", + "node_modules/is-finalizationregistry": { + "version": "1.1.1", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "call-bound": "^1.0.3" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-runtime/node_modules/glob": { - "version": "10.5.0", + "node_modules/is-generator-function": { + "version": "1.1.2", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, - "bin": { - "glob": "dist/esm/bin.mjs" + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-runtime/node_modules/jackspeak": { - "version": "3.4.3", + "node_modules/is-glob": { + "version": "4.0.3", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "is-extglob": "^2.1.1" }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/jest-runtime/node_modules/lru-cache": { - "version": "10.4.3", - "dev": true, - "license": "ISC" + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, - "node_modules/jest-runtime/node_modules/minimatch": { - "version": "9.0.9", + "node_modules/is-in-ssh": { + "version": "1.0.0", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.2" - }, + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=20" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-runtime/node_modules/path-scurry": { - "version": "1.11.1", + "node_modules/is-inside-container": { + "version": "1.0.0", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": ">=14.16" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-runtime/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/is-interactive": { + "version": "2.0.0", "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-snapshot": { - "version": "30.3.0", + "node_modules/is-map": { + "version": "2.0.3", "dev": true, "license": "MIT", - "dependencies": { - "@babel/core": "^7.27.4", - "@babel/generator": "^7.27.5", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/plugin-syntax-typescript": "^7.27.1", - "@babel/types": "^7.27.3", - "@jest/expect-utils": "30.3.0", - "@jest/get-type": "30.1.0", - "@jest/snapshot-utils": "30.3.0", - "@jest/transform": "30.3.0", - "@jest/types": "30.3.0", - "babel-preset-current-node-syntax": "^1.2.0", - "chalk": "^4.1.2", - "expect": "30.3.0", - "graceful-fs": "^4.2.11", - "jest-diff": "30.3.0", - "jest-matcher-utils": "30.3.0", - "jest-message-util": "30.3.0", - "jest-util": "30.3.0", - "pretty-format": "30.3.0", - "semver": "^7.7.2", - "synckit": "^0.11.8" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-snapshot/node_modules/@pkgr/core": { - "version": "0.2.9", + "node_modules/is-negative-zero": { + "version": "2.0.3", "dev": true, "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/pkgr" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-snapshot/node_modules/chalk": { - "version": "4.1.2", + "node_modules/is-number": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-snapshot/node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/is-obj": { + "version": "3.0.0", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" + "engines": { + "node": ">=12" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-snapshot/node_modules/pretty-format": { - "version": "30.3.0", + "node_modules/is-plain-object": { + "version": "5.0.0", "dev": true, "license": "MIT", - "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-snapshot/node_modules/react-is": { - "version": "18.3.1", + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", "dev": true, "license": "MIT" }, - "node_modules/jest-snapshot/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/is-promise": { + "version": "4.0.0", + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.2.1", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-snapshot/node_modules/synckit": { - "version": "0.11.12", + "node_modules/is-regexp": { + "version": "3.1.0", "dev": true, "license": "MIT", - "dependencies": { - "@pkgr/core": "^0.2.9" + "engines": { + "node": ">=12" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "dev": true, + "license": "MIT", "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/synckit" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-util": { - "version": "30.3.0", + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.3.0", - "@types/node": "*", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "graceful-fs": "^4.2.11", - "picomatch": "^4.0.3" + "call-bound": "^1.0.3" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-util/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/is-stream": { + "version": "2.0.1", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { "node": ">=8" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-util/node_modules/chalk": { - "version": "4.1.2", + "node_modules/is-string": { + "version": "1.1.1", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-util/node_modules/picomatch": { - "version": "4.0.4", + "node_modules/is-symbol": { + "version": "1.1.1", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-util/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/is-typed-array": { + "version": "1.1.15", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "which-typed-array": "^1.1.16" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-validate": { - "version": "30.3.0", + "node_modules/is-unicode-supported": { + "version": "2.1.0", "dev": true, "license": "MIT", - "dependencies": { - "@jest/get-type": "30.1.0", - "@jest/types": "30.3.0", - "camelcase": "^6.3.0", - "chalk": "^4.1.2", - "leven": "^3.1.0", - "pretty-format": "30.3.0" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", + "node_modules/is-weakmap": { + "version": "2.0.2", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-validate/node_modules/chalk": { - "version": "4.1.2", + "node_modules/is-weakref": { + "version": "1.1.1", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "call-bound": "^1.0.3" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-validate/node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/is-weakset": { + "version": "2.0.4", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-validate/node_modules/pretty-format": { - "version": "30.3.0", + "node_modules/is-wsl": { + "version": "3.1.0", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" + "is-inside-container": "^1.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-validate/node_modules/react-is": { - "version": "18.3.1", + "node_modules/isarray": { + "version": "2.0.5", "dev": true, "license": "MIT" }, - "node_modules/jest-validate/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/isexe": { + "version": "2.0.0", + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, + "license": "BSD-3-Clause", "engines": { "node": ">=8" } }, - "node_modules/jest-watcher": { - "version": "30.3.0", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "@jest/test-result": "30.3.0", - "@jest/types": "30.3.0", - "@types/node": "*", - "ansi-escapes": "^4.3.2", - "chalk": "^4.1.2", - "emittery": "^0.13.1", - "jest-util": "30.3.0", - "string-length": "^4.0.2" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=10" } }, - "node_modules/jest-watcher/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-watcher/node_modules/chalk": { - "version": "4.1.2", - "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/jest-watcher/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/istanbul-reports": { + "version": "3.2.0", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "has-flag": "^4.0.0" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/jest-worker": { - "version": "30.3.0", + "node_modules/iterator.prototype": { + "version": "1.1.5", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "@ungap/structured-clone": "^1.3.0", - "jest-util": "30.3.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.1.1" + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jackspeak": { + "version": "4.1.1", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/jiti": { @@ -13317,33 +10937,36 @@ } }, "node_modules/jsdom": { - "version": "26.1.0", + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz", + "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==", "dev": true, "license": "MIT", "dependencies": { - "cssstyle": "^4.2.1", - "data-urls": "^5.0.0", - "decimal.js": "^10.5.0", - "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.6", + "@asamuzakjp/css-color": "^5.1.11", + "@asamuzakjp/dom-selector": "^7.1.1", + "@bramus/specificity": "^2.4.2", + "@csstools/css-syntax-patches-for-csstree": "^1.1.3", + "@exodus/bytes": "^1.15.0", + "css-tree": "^3.2.1", + "data-urls": "^7.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^6.0.0", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.16", - "parse5": "^7.2.1", - "rrweb-cssom": "^0.8.0", + "lru-cache": "^11.3.5", + "parse5": "^8.0.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^5.1.1", + "tough-cookie": "^6.0.1", + "undici": "^7.25.0", "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^3.1.1", - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.1.1", - "ws": "^8.18.0", + "webidl-conversions": "^8.0.1", + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.1", "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.13.0 || >=24.0.0" }, "peerDependencies": { "canvas": "^3.0.0" @@ -13354,6 +10977,42 @@ } } }, + "node_modules/jsdom/node_modules/entities": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/jsdom/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/jsdom/node_modules/parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz", + "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^8.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/jsesc": { "version": "3.1.0", "dev": true, @@ -13463,14 +11122,6 @@ "node": ">=0.10" } }, - "node_modules/leven": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/levn": { "version": "0.4.1", "dev": true, @@ -13808,11 +11459,6 @@ "version": "4.18.1", "license": "MIT" }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "dev": true, - "license": "MIT" - }, "node_modules/log-symbols": { "version": "6.0.0", "dev": true, @@ -13899,6 +11545,18 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/magicast": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.4.tgz", + "integrity": "sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "source-map-js": "^1.2.1" + } + }, "node_modules/make-dir": { "version": "4.0.0", "dev": true, @@ -13913,19 +11571,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-error": { - "version": "1.3.6", - "dev": true, - "license": "ISC" - }, - "node_modules/makeerror": { - "version": "1.0.12", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tmpl": "1.0.5" - } - }, "node_modules/markdown-extensions": { "version": "2.0.0", "license": "MIT", @@ -14216,6 +11861,13 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/media-typer": { "version": "1.1.0", "license": "MIT", @@ -15046,11 +12698,6 @@ "node": ">= 0.6" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "dev": true, - "license": "MIT" - }, "node_modules/next": { "version": "16.2.12", "license": "MIT", @@ -15197,11 +12844,6 @@ "url": "https://opencollective.com/node-fetch" } }, - "node_modules/node-int64": { - "version": "0.4.0", - "dev": true, - "license": "MIT" - }, "node_modules/node-releases": { "version": "2.0.53", "license": "MIT", @@ -15209,14 +12851,6 @@ "node": ">=18" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/nostr-tools": { "version": "2.23.3", "license": "Unlicense", @@ -15303,11 +12937,6 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/nwsapi": { - "version": "2.2.23", - "dev": true, - "license": "MIT" - }, "node_modules/object-assign": { "version": "4.1.1", "license": "MIT", @@ -15426,6 +13055,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obug": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "license": "MIT", @@ -15714,28 +13357,6 @@ "dev": true, "license": "MIT" }, - "node_modules/parse5": { - "version": "7.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5/node_modules/entities": { - "version": "6.0.1", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/parseurl": { "version": "1.3.3", "license": "MIT", @@ -15755,14 +13376,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "license": "MIT", @@ -15804,6 +13417,13 @@ "url": "https://opencollective.com/express" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/pg": { "version": "8.23.0", "dev": true, @@ -15900,14 +13520,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pirates": { - "version": "4.0.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/pkce-challenge": { "version": "5.0.1", "license": "MIT", @@ -15915,65 +13527,6 @@ "node": ">=16.20.0" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/playwright": { "version": "1.62.1", "devOptional": true, @@ -16216,21 +13769,6 @@ "node": ">=6" } }, - "node_modules/pure-rand": { - "version": "7.0.1", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, "node_modules/qrcode": { "version": "1.5.4", "license": "MIT", @@ -16917,25 +14455,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/resolve-from": { "version": "4.0.0", "dev": true, @@ -16990,6 +14509,40 @@ "node": ">=0.10.0" } }, + "node_modules/rolldown": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.6.tgz", + "integrity": "sha512-vMM4q3aixf46GiF1Kok8jDPFsEpXgFWGjUHXNkNHNm+Y2adXAG2dbX91jkti3i0ZRsOlcmbuzAz1poObSHCmUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.147.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm-eabi": "1.2.6", + "@rolldown/binding-android-arm64": "1.2.6", + "@rolldown/binding-darwin-arm64": "1.2.6", + "@rolldown/binding-darwin-x64": "1.2.6", + "@rolldown/binding-freebsd-x64": "1.2.6", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.6", + "@rolldown/binding-linux-arm64-gnu": "1.2.6", + "@rolldown/binding-linux-arm64-musl": "1.2.6", + "@rolldown/binding-linux-ppc64-gnu": "1.2.6", + "@rolldown/binding-linux-s390x-gnu": "1.2.6", + "@rolldown/binding-linux-x64-gnu": "1.2.6", + "@rolldown/binding-linux-x64-musl": "1.2.6", + "@rolldown/binding-openharmony-arm64": "1.2.6", + "@rolldown/binding-win32-arm64-msvc": "1.2.6", + "@rolldown/binding-win32-x64-msvc": "1.2.6" + } + }, "node_modules/router": { "version": "2.2.0", "license": "MIT", @@ -17004,11 +14557,6 @@ "node": ">= 18" } }, - "node_modules/rrweb-cssom": { - "version": "0.8.0", - "dev": true, - "license": "MIT" - }, "node_modules/run-applescript": { "version": "7.1.0", "dev": true, @@ -17477,6 +15025,8 @@ }, "node_modules/sharp": { "version": "0.35.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.4.tgz", + "integrity": "sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -17615,6 +15165,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "4.1.0", "license": "ISC", @@ -17640,16 +15197,8 @@ }, "node_modules/sisteransi": { "version": "1.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/slash": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "dev": true, + "license": "MIT" }, "node_modules/smart-buffer": { "version": "4.2.0", @@ -17695,23 +15244,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.13", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/space-separated-tokens": { "version": "2.0.2", "license": "MIT", @@ -17756,24 +15288,12 @@ "dev": true, "license": "MIT" }, - "node_modules/stack-utils": { - "version": "2.0.6", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "MIT" }, "node_modules/standardwebhooks": { "version": "1.0.0", @@ -17790,6 +15310,13 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", + "dev": true, + "license": "MIT" + }, "node_modules/stdin-discarder": { "version": "0.2.2", "dev": true, @@ -17821,18 +15348,6 @@ "node": ">=0.6.19" } }, - "node_modules/string-length": { - "version": "4.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/string-width": { "version": "5.1.2", "license": "MIT", @@ -18045,14 +15560,6 @@ "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/strip-bom-string": { "version": "1.0.0", "license": "MIT", @@ -18079,17 +15586,6 @@ "node": ">=8" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/style-to-js": { "version": "1.1.21", "license": "MIT", @@ -18174,20 +15670,6 @@ "node": ">=16" } }, - "node_modules/supports-color": { - "version": "8.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "dev": true, @@ -18239,968 +15721,1310 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/test-exclude": { - "version": "6.0.0", + "node_modules/tiny-invariant": { + "version": "1.3.3", "dev": true, - "license": "ISC", + "license": "MIT" + }, + "node_modules/tiny-secp256k1": { + "version": "2.2.4", + "license": "MIT", "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "uint8array-tools": "0.0.7" }, "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.18", + "node_modules/tiny-secp256k1/node_modules/uint8array-tools": { + "version": "0.0.7", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.2.4", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=18" } }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "fdir": "^6.5.0", + "picomatch": "^4.0.4" }, "engines": { - "node": "*" + "node": ">=12.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.5", + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinyrainbow": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", + "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", + "dev": true, + "license": "MIT", "engines": { - "node": "*" + "node": ">=14.0.0" } }, - "node_modules/tiny-invariant": { - "version": "1.3.3", + "node_modules/tldts": { + "version": "7.4.11", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.11.tgz", + "integrity": "sha512-aBiNayCfTQxuIJBm06M+xR14cYaYlDlSXZbgsnKzKNxDKUVq7KFwTjwBSsb7m9Y5xO8WfPnBc63WaYFMTGlvqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^7.4.11" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "7.4.11", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.11.tgz", + "integrity": "sha512-CW3WN2rIIE/Of21mulhgnGOwoDyEFNygyIBOONSdyAuSATgMMUCpLeUlB+E8sAwA5xRV9hYPl+kyZ9citHCaKg==", "dev": true, "license": "MIT" }, - "node_modules/tiny-secp256k1": { - "version": "2.2.4", + "node_modules/to-regex-range": { + "version": "5.0.1", + "dev": true, "license": "MIT", "dependencies": { - "uint8array-tools": "0.0.7" + "is-number": "^7.0.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=8.0" } }, - "node_modules/tiny-secp256k1/node_modules/uint8array-tools": { - "version": "0.0.7", + "node_modules/to-valid-identifier": { + "version": "1.0.0", + "dev": true, "license": "MIT", + "dependencies": { + "@sindresorhus/base62": "^1.0.0", + "reserved-identifiers": "^1.0.0" + }, "engines": { - "node": ">=14.0.0" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tinyexec": { - "version": "1.2.4", + "node_modules/toidentifier": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/totalist": { + "version": "3.0.1", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=6" + } + }, + "node_modules/tough-cookie": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.2.tgz", + "integrity": "sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^7.0.5" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-morph": { + "version": "26.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@ts-morph/common": "~0.27.0", + "code-block-writer": "^13.0.3" } }, - "node_modules/tinyglobby": { - "version": "0.2.15", + "node_modules/tsconfig-paths": { + "version": "3.15.0", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" } }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", "dev": true, "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" + "dependencies": { + "minimist": "^1.2.0" }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "bin": { + "json5": "lib/cli.js" } }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.4", + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=4" } }, - "node_modules/tmpl": { - "version": "1.0.5", - "dev": true, - "license": "BSD-3-Clause" + "node_modules/tslib": { + "version": "2.8.1", + "license": "0BSD" }, - "node_modules/to-regex-range": { - "version": "5.0.1", + "node_modules/type-check": { + "version": "0.4.0", "dev": true, "license": "MIT", "dependencies": { - "is-number": "^7.0.0" + "prelude-ls": "^1.2.1" }, "engines": { - "node": ">=8.0" + "node": ">= 0.8.0" } }, - "node_modules/to-valid-identifier": { - "version": "1.0.0", - "dev": true, + "node_modules/type-is": { + "version": "2.1.0", "license": "MIT", "dependencies": { - "@sindresorhus/base62": "^1.0.0", - "reserved-identifiers": "^1.0.0" + "content-type": "^2.0.0", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" }, "engines": { - "node": ">=20" + "node": ">= 18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/toidentifier": { - "version": "1.0.1", + "node_modules/type-is/node_modules/content-type": { + "version": "2.0.0", "license": "MIT", "engines": { - "node": ">=0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/totalist": { - "version": "3.0.1", + "node_modules/typed-array-buffer": { + "version": "1.0.3", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/tough-cookie": { - "version": "5.1.2", + "node_modules/typed-array-byte-length": { + "version": "1.0.3", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "tldts": "^6.1.32" + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { - "node": ">=16" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tough-cookie/node_modules/tldts": { - "version": "6.1.86", + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.86" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, - "bin": { - "tldts": "bin/cli.js" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tough-cookie/node_modules/tldts-core": { - "version": "6.1.86", - "dev": true, - "license": "MIT" - }, - "node_modules/tr46": { - "version": "5.1.1", + "node_modules/typed-array-length": { + "version": "1.0.7", "dev": true, "license": "MIT", "dependencies": { - "punycode": "^2.3.1" + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tree-kill": { - "version": "1.2.2", - "dev": true, - "license": "MIT", - "bin": { - "tree-kill": "cli.js" - } + "node_modules/typeforce": { + "version": "1.18.0", + "license": "MIT" }, - "node_modules/trim-lines": { - "version": "3.0.1", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/typescript": { + "version": "5.9.3", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" } }, - "node_modules/trough": { - "version": "2.2.0", + "node_modules/typescript-eslint": { + "version": "8.65.0", + "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.65.0", + "@typescript-eslint/parser": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.0", + "@typescript-eslint/utils": "8.65.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/ts-api-utils": { - "version": "2.5.0", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.65.0", "dev": true, "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.65.0", + "@typescript-eslint/type-utils": "8.65.0", + "@typescript-eslint/utils": "8.65.0", + "@typescript-eslint/visitor-keys": "8.65.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, "engines": { - "node": ">=18.12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4" + "@typescript-eslint/parser": "^8.65.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/ts-jest": { - "version": "29.4.12", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": { + "version": "8.65.0", "dev": true, "license": "MIT", "dependencies": { - "bs-logger": "^0.2.6", - "fast-json-stable-stringify": "^2.1.0", - "handlebars": "^4.7.9", - "json5": "^2.2.3", - "lodash.memoize": "^4.1.2", - "make-error": "^1.3.6", - "semver": "^7.8.5", - "type-fest": "^4.41.0", - "yargs-parser": "^21.1.1" - }, - "bin": { - "ts-jest": "cli.js" + "@typescript-eslint/scope-manager": "8.65.0", + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.0", + "@typescript-eslint/visitor-keys": "8.65.0", + "debug": "^4.4.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/transform": "^29.0.0 || ^30.0.0", - "@jest/types": "^29.0.0 || ^30.0.0", - "babel-jest": "^29.0.0 || ^30.0.0", - "jest": "^29.0.0 || ^30.0.0", - "jest-util": "^29.0.0 || ^30.0.0", - "typescript": ">=4.3 <7" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/transform": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "jest-util": { - "optional": true - } + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/ts-jest/node_modules/type-fest": { - "version": "4.41.0", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/type-utils": { + "version": "8.65.0", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.0", + "@typescript-eslint/utils": "8.65.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, "engines": { - "node": ">=16" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/ts-morph": { - "version": "26.0.0", - "dev": true, + "node_modules/uint8array-tools": { + "version": "0.0.8", "license": "MIT", - "dependencies": { - "@ts-morph/common": "~0.27.0", - "code-block-writer": "^13.0.3" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", + "node_modules/unbox-primitive": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", + "node_modules/uncrypto": { + "version": "0.1.3", + "license": "MIT" + }, + "node_modules/undici": { + "version": "7.29.0", "dev": true, "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" + "engines": { + "node": ">=20.18.1" } }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", + "node_modules/undici-types": { + "version": "8.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tslib": { - "version": "2.8.1", - "license": "0BSD" - }, - "node_modules/type-check": { - "version": "0.4.0", - "dev": true, + "node_modules/unified": { + "version": "11.0.5", "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1" + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" }, - "engines": { - "node": ">= 0.8.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "dev": true, + "node_modules/unist-util-is": { + "version": "6.0.1", "license": "MIT", - "engines": { - "node": ">=4" + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/type-is": { - "version": "2.1.0", + "node_modules/unist-util-position": { + "version": "5.0.0", "license": "MIT", "dependencies": { - "content-type": "^2.0.0", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 18" + "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://opencollective.com/unified" } }, - "node_modules/type-is/node_modules/content-type": { + "node_modules/unist-util-position-from-estree": { "version": "2.0.0", "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://opencollective.com/unified" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "dev": true, + "node_modules/unist-util-remove": { + "version": "4.0.0", "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, - "engines": { - "node": ">= 0.4" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "dev": true, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" + "@types/unist": "^3.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "dev": true, + "node_modules/unist-util-visit": { + "version": "5.1.0", "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" - }, - "engines": { - "node": ">= 0.4" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "dev": true, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/typeforce": { - "version": "1.18.0", - "license": "MIT" + "node_modules/universal-user-agent": { + "version": "7.0.3", + "license": "ISC" }, - "node_modules/typescript": { - "version": "5.9.3", - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "node_modules/universalify": { + "version": "2.0.1", + "dev": true, + "license": "MIT", "engines": { - "node": ">=14.17" + "node": ">= 10.0.0" } }, - "node_modules/typescript-eslint": { - "version": "8.65.0", + "node_modules/unpipe": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", "dev": true, + "hasInstallScript": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.65.0", - "@typescript-eslint/parser": "8.65.0", - "@typescript-eslint/typescript-estree": "8.65.0", - "@typescript-eslint/utils": "8.65.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "napi-postinstall": "^0.3.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://opencollective.com/unrs-resolver" }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.65.0", + "node_modules/update-browserslist-db": { + "version": "1.2.2", "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": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.65.0", - "@typescript-eslint/type-utils": "8.65.0", - "@typescript-eslint/utils": "8.65.0", - "@typescript-eslint/visitor-keys": "8.65.0", - "ignore": "^7.0.5", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "bin": { + "update-browserslist-db": "cli.js" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.65.0", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "browserslist": ">= 4.21.0" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": { - "version": "8.65.0", + "node_modules/uri-js": { + "version": "4.4.1", "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-callback-ref": { + "version": "1.3.3", "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.65.0", - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/typescript-estree": "8.65.0", - "@typescript-eslint/visitor-keys": "8.65.0", - "debug": "^4.4.3" + "tslib": "^2.0.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=10" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/type-utils": { - "version": "8.65.0", - "dev": true, + "node_modules/use-sidecar": { + "version": "1.1.3", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/typescript-estree": "8.65.0", - "@typescript-eslint/utils": "8.65.0", - "debug": "^4.4.3", - "ts-api-utils": "^2.5.0" + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=10" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/uglify-js": { - "version": "3.19.3", + "node_modules/util-deprecate": { + "version": "1.0.2", "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } + "license": "MIT" }, - "node_modules/uint8array-tools": { - "version": "0.0.8", + "node_modules/uuid": { + "version": "14.0.0", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", - "engines": { - "node": ">=14.0.0" + "bin": { + "uuid": "dist-node/bin/uuid" } }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "dev": true, + "node_modules/valibot": { + "version": "1.4.2", "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" + "peerDependencies": { + "typescript": ">=5" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/uncrypto": { - "version": "0.1.3", - "license": "MIT" - }, - "node_modules/undici": { - "version": "7.29.0", + "node_modules/validate-npm-package-name": { + "version": "7.0.2", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">=20.18.1" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/undici-types": { - "version": "8.3.0", - "dev": true, - "license": "MIT" + "node_modules/varuint-bitcoin": { + "version": "1.1.2", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.1" + } }, - "node_modules/unicorn-magic": { - "version": "0.3.0", - "dev": true, + "node_modules/vary": { + "version": "1.1.2", "license": "MIT", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8" } }, - "node_modules/unified": { - "version": "11.0.5", + "node_modules/vfile": { + "version": "6.0.3", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" + "vfile-message": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-is": { - "version": "6.0.1", + "node_modules/vfile-matter": { + "version": "5.0.1", "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "vfile": "^6.0.0", + "yaml": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-position": { - "version": "5.0.0", + "node_modules/vfile-message": { + "version": "4.0.3", "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-position-from-estree": { - "version": "2.0.0", + "node_modules/vite": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.2.tgz", + "integrity": "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "lightningcss": "^1.33.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.26", + "rolldown": "~1.2.4", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.4.0 || ^0.5.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "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/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-remove": { - "version": "4.0.0", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/vite/node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/parcel" } }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" + "node_modules/vite/node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/parcel" } }, - "node_modules/unist-util-visit": { - "version": "5.1.0", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" + "node_modules/vite/node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/parcel" } }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.2", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" + "node_modules/vite/node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/parcel" } }, - "node_modules/universal-user-agent": { - "version": "7.0.3", - "license": "ISC" - }, - "node_modules/universalify": { - "version": "2.0.1", + "node_modules/vite/node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "license": "MIT", + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.8" - } - }, - "node_modules/unrs-resolver": { - "version": "1.11.1", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "napi-postinstall": "^0.3.0" + "node": ">= 12.0.0" }, "funding": { - "url": "https://opencollective.com/unrs-resolver" - }, - "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.11.1", - "@unrs/resolver-binding-android-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-x64": "1.11.1", - "@unrs/resolver-binding-freebsd-x64": "1.11.1", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", - "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-musl": "1.11.1", - "@unrs/resolver-binding-wasm32-wasi": "1.11.1", - "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", - "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", - "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/update-browserslist-db": { - "version": "1.2.2", + "node_modules/vite/node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], "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" - } + "libc": [ + "glibc" ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/uri-js": { - "version": "4.4.1", + "node_modules/vite/node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/use-callback-ref": { - "version": "1.3.3", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" - }, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + "node": ">= 12.0.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/use-sidecar": { - "version": "1.1.3", - "license": "MIT", - "dependencies": { - "detect-node-es": "^1.1.0", - "tslib": "^2.0.0" - }, + "node_modules/vite/node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + "node": ">= 12.0.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", + "node_modules/vite/node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT" - }, - "node_modules/uuid": { - "version": "14.0.0", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" + "libc": [ + "musl" ], - "license": "MIT", - "bin": { - "uuid": "dist-node/bin/uuid" + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", + "node_modules/vite/node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/valibot": { - "version": "1.4.2", - "license": "MIT", - "peerDependencies": { - "typescript": ">=5" + "node": ">= 12.0.0" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/validate-npm-package-name": { - "version": "7.0.2", + "node_modules/vite/node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/varuint-bitcoin": { - "version": "1.1.2", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.1" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/vary": { - "version": "1.1.2", + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vfile": { - "version": "6.0.3", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/vfile-matter": { - "version": "5.0.1", + "node_modules/vitest": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.11.tgz", + "integrity": "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==", + "dev": true, "license": "MIT", "dependencies": { - "vfile": "^6.0.0", - "yaml": "^2.0.0" + "@vitest/expect": "4.1.11", + "@vitest/mocker": "4.1.11", + "@vitest/pretty-format": "4.1.11", + "@vitest/runner": "4.1.11", + "@vitest/snapshot": "4.1.11", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.11", + "@vitest/browser-preview": "4.1.11", + "@vitest/browser-webdriverio": "4.1.11", + "@vitest/coverage-istanbul": "4.1.11", + "@vitest/coverage-v8": "4.1.11", + "@vitest/ui": "4.1.11", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } } }, - "node_modules/vfile-message": { - "version": "4.0.3", + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" + "engines": { + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/w3c-xmlserializer": { @@ -19214,14 +17038,6 @@ "node": ">=18" } }, - "node_modules/walker": { - "version": "1.0.8", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "makeerror": "1.0.12" - } - }, "node_modules/web-streams-polyfill": { "version": "3.3.3", "dev": true, @@ -19231,53 +17047,38 @@ } }, "node_modules/webidl-conversions": { - "version": "7.0.0", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", "dev": true, "license": "BSD-2-Clause", "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-encoding": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/whatwg-encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" + "node": ">=20" } }, "node_modules/whatwg-mimetype": { - "version": "4.0.0", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/whatwg-url": { - "version": "14.2.0", + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz", + "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", "dev": true, "license": "MIT", "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" + "@exodus/bytes": "^1.11.0", + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.1" }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, "node_modules/which": { @@ -19378,6 +17179,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wif": { "version": "5.0.0", "license": "MIT", @@ -19393,11 +17211,6 @@ "node": ">=0.10.0" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/wrap-ansi": { "version": "8.1.0", "license": "MIT", @@ -19502,18 +17315,6 @@ "version": "1.0.2", "license": "ISC" }, - "node_modules/write-file-atomic": { - "version": "5.0.1", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/ws": { "version": "8.21.3", "dev": true, @@ -19596,57 +17397,6 @@ "url": "https://github.com/sponsors/eemeli" } }, - "node_modules/yargs": { - "version": "17.7.2", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "dev": true, diff --git a/package.json b/package.json index ae55d6bf5..6c655abae 100644 --- a/package.json +++ b/package.json @@ -45,20 +45,20 @@ "check:user-scoped-deletes": "node scripts/check-user-scoped-deletes.mjs", "check:ai-models": "node scripts/check-ai-models.mjs", "check:mdx": "node scripts/check-mdx.mjs", - "verify": "npm run ci:docs && npm run check:accent-ink && npm run type-check && npm run type-check:scripts && npm run check:sizes && npm run audit:routes && npm run lint && npm run check:duplication && npm run check:dead-fields && npm run check:dead-labels && npm run check:migration-versions && npm run check:schema-columns && npm run check:currency-units && npm run check:rpc-exists && npm run check:one-current-user && npm run check:app-locale && npm run check:type-scale && npm run check:client-ip && npm run check:user-scoped-deletes && npm run check:mdx && npm run test:unit -- --watchAll=false", + "verify": "npm run ci:docs && npm run check:accent-ink && npm run type-check && npm run type-check:scripts && npm run check:sizes && npm run audit:routes && npm run lint && npm run check:duplication && npm run check:dead-fields && npm run check:dead-labels && npm run check:migration-versions && npm run check:schema-columns && npm run check:currency-units && npm run check:rpc-exists && npm run check:one-current-user && npm run check:app-locale && npm run check:type-scale && npm run check:client-ip && npm run check:user-scoped-deletes && npm run check:mdx && npm run test:unit", "audit:schema": "node scripts/db/audit-schema-drift.mjs", "audit:routes": "node scripts/audit-routes.mjs", "gen:types": "bash scripts/db/gen-types.sh", - "test": "jest", - "test:watch": "jest --watch", - "test:ci": "jest --ci --coverage --watchAll=false", - "test:security": "jest --testPathPatterns \"(security|ssrf|crypto|signing|idempotency)\" --passWithNoTests", - "test:unit": "jest --testPathPatterns \"(__tests__|tests)/(unit|smoke|create|env)\"", - "test:auth": "jest --testPathPatterns \"auth\" --watchAll=false", - "test:integration": "jest --testPathPatterns \"__tests__/integration\" --passWithNoTests", - "test:performance": "jest --testPathPatterns \"performance\" --passWithNoTests", - "test:coverage": "jest --coverage", - "test:smoke:auth": "jest --runTestsByPath __tests__/smoke/auth-login.test.ts", + "test": "vitest run", + "test:watch": "vitest", + "test:ci": "vitest run --coverage", + "test:security": "vitest run security ssrf crypto signing idempotency --passWithNoTests", + "test:unit": "vitest run __tests__/unit __tests__/smoke __tests__/create tests/unit tests/env.test.ts", + "test:auth": "vitest run auth", + "test:integration": "vitest run __tests__/integration --passWithNoTests", + "test:performance": "vitest run performance --passWithNoTests", + "test:coverage": "vitest run --coverage", + "test:smoke:auth": "vitest run __tests__/smoke/auth-login.test.ts", "test:e2e": "playwright test", "test:e2e:ui": "playwright test --ui", "test:e2e:brave": "playwright test --project=brave", @@ -90,7 +90,6 @@ "mcp:shell": "node mcp-servers/shell-server.js", "mcp:git": "node mcp-servers/git-server.js", "mcp:lint": "node mcp-servers/lint-server.js", - "mcp:jest": "node mcp-servers/jest-server.js", "mcp:orchestrate": "node scripts/mcp-orchestrate.mjs", "browser": "node scripts/browser-automation.js", "format": "prettier --write .", @@ -204,12 +203,12 @@ "@testing-library/jest-dom": "^7.0.0", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.4", - "@types/jest": "^30.0.0", "@types/node": "^26.3.0", "@types/react": "^19.2.18", "@types/react-dom": "^19.2.4", "@typescript-eslint/eslint-plugin": "^8.67.0", "@typescript-eslint/parser": "^8.67.0", + "@vitest/coverage-v8": "^4.1.11", "chalk": "^6.0.0", "concurrently": "^10.0.4", "dotenv": "^16.5.0", @@ -218,9 +217,8 @@ "eslint-plugin-jsdoc": "^63.3.3", "eslint-plugin-unused-imports": "^4.4.1", "husky": "^9.1.7", - "jest": "^30.3.0", - "jest-environment-jsdom": "^30.2.0", "jscpd": "5.0.16", + "jsdom": "^29.1.1", "lint-staged": "^17.3.0", "node-fetch": "^3.3.2", "pg": "^8.23.0", @@ -228,7 +226,7 @@ "prettier": "^3.6.2", "shadcn": "^4.19.0", "supabase": "^2.115.0", - "ts-jest": "^29.4.12", + "vitest": "^4.1.11", "ws": "^8.21.3" }, "optionalDependencies": { diff --git a/tests/TestWrapper.tsx b/tests/TestWrapper.tsx index 4abe57c64..36558309f 100644 --- a/tests/TestWrapper.tsx +++ b/tests/TestWrapper.tsx @@ -1,19 +1,19 @@ -import { RouterContext } from 'next/dist/shared/lib/router-context.shared-runtime' -import { NextRouter } from 'next/router' -import { ReactNode } from 'react' +import { RouterContext } from 'next/dist/shared/lib/router-context.shared-runtime'; +import { NextRouter } from 'next/router'; +import { ReactNode } from 'react'; interface TestWrapperProps { - children: ReactNode - router?: Partial + children: ReactNode; + router?: Partial; } const createRouter = (router?: Partial): NextRouter => ({ - push: jest.fn(), - replace: jest.fn(), - prefetch: jest.fn(), - back: jest.fn(), - reload: jest.fn(), - forward: jest.fn(), + push: vi.fn(), + replace: vi.fn(), + prefetch: vi.fn(), + back: vi.fn(), + reload: vi.fn(), + forward: vi.fn(), pathname: '/', route: '/', query: {}, @@ -23,26 +23,22 @@ const createRouter = (router?: Partial): NextRouter => ({ isReady: true, isPreview: false, events: { - on: jest.fn(), - off: jest.fn(), - emit: jest.fn(), + on: vi.fn(), + off: vi.fn(), + emit: vi.fn(), }, isFallback: false, - beforePopState: jest.fn(), + beforePopState: vi.fn(), ...router, -}) +}); export function TestWrapper({ children, router }: TestWrapperProps) { - const mockRouter = createRouter(router) - + const mockRouter = createRouter(router); + if (typeof window !== 'undefined') { // @ts-ignore - Set global mockRouter for tests - window.mockRouter = mockRouter + window.mockRouter = mockRouter; } - return ( - - {children} - - ) -} \ No newline at end of file + return {children}; +} diff --git a/tests/jest-dom.d.ts b/tests/jest-dom.d.ts deleted file mode 100644 index 350ccc5a9..000000000 --- a/tests/jest-dom.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { TestingLibraryMatchers } from '@testing-library/jest-dom/matchers'; - -declare module '@jest/expect' { - // eslint-disable-next-line @typescript-eslint/no-empty-object-type, @typescript-eslint/no-explicit-any - interface Matchers> extends TestingLibraryMatchers< - typeof expect.stringContaining, - R - > {} -} diff --git a/tests/setup.ts b/tests/setup.ts index 8c2be5c56..f67465f10 100644 --- a/tests/setup.ts +++ b/tests/setup.ts @@ -1,11 +1,11 @@ import '@testing-library/jest-dom'; // Mock next/router -jest.mock('next/router', () => ({ +vi.mock('next/router', () => ({ useRouter: () => ({ - push: jest.fn(), + push: vi.fn(), }), })); // Mock window.alert -window.alert = jest.fn(); \ No newline at end of file +window.alert = vi.fn(); diff --git a/tests/unit/Button.test.tsx b/tests/unit/Button.test.tsx index 231a215b9..7927932e4 100644 --- a/tests/unit/Button.test.tsx +++ b/tests/unit/Button.test.tsx @@ -15,8 +15,8 @@ import { render, screen, fireEvent } from '@testing-library/react'; import '@testing-library/jest-dom'; import Button from '@/components/ui/Button'; -jest.mock('next/link', () => { - return function MockLink({ +vi.mock('next/link', () => ({ + default: function MockLink({ children, href, ...props @@ -26,8 +26,8 @@ jest.mock('next/link', () => { {children} ); - }; -}); + }, +})); describe('Button', () => { describe('rendering', () => { @@ -75,14 +75,14 @@ describe('Button', () => { describe('interactivity', () => { it('calls onClick when clicked', () => { - const onClick = jest.fn(); + const onClick = vi.fn(); render(); fireEvent.click(screen.getByRole('button')); expect(onClick).toHaveBeenCalledTimes(1); }); it('does not call onClick when disabled', () => { - const onClick = jest.fn(); + const onClick = vi.fn(); render(