From b67ebb90b17187282c3b97bab8a6a5a136904384 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Thu, 24 Sep 2026 13:07:46 +0000 Subject: [PATCH 1/2] fix(#475): seed E2E state through the app instead of poking the QueryClient MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `e2e/farm.spec.ts` seeded React Query data by reaching for `window.__queryClient` and calling `setQueryData(['pools'], …)` itself. That couples every spec to two things it should not know about: the QueryClient instance, and the literal spelling of each query key. Rename a key and an unrelated spec fails; drop the global and every spec breaks at once — which is exactly what the issue reports. `src/lib/e2eSeed.ts` owns that knowledge instead and exposes a small surface: window.__e2e.seedPools([pool]) window.__e2e.seedPositions(publicKey, [{ pool, position }]) window.__e2e.clearPositions(publicKey) window.__e2e.reset() The keys come from `QUERY_KEYS` in `useSorobanQuery`, which is where the hooks that read them are defined, so a rename moves both sides together. `src/context/index.tsx` installs it under the same development / NEXT_PUBLIC_E2E condition the raw client used to be exposed under, and no longer publishes `window.__queryClient` at all. `e2e/lock-unlock-lifecycle.spec.ts` used the same global for the same reason, so it is migrated too rather than leaving one spec coupled to an internal the app no longer offers. Tests — `src/lib/e2eSeed.test.ts`, 9 new: - pools land under the key `useSorobanQuery` reads; - positions land under the key the app invalidates, `['userPosition', 'all', pk]`; - positions are per account, so one seed cannot leak into another; - clearing positions leaves the pool list alone, and reset clears both; - the key spellings the specs rely on are pinned, so a rename fails next to the reason instead of inside an unrelated spec; - no file under `e2e/` or `tests/` mentions `__queryClient` any more, and `src/context/index.tsx` no longer hands it out — the same invariant, asserted rather than trusted. Verification: pnpm exec tsc --noEmit # clean pnpm exec eslint # 0 errors (2 pre-existing unused-const warnings) pnpm exec vitest run src/lib/e2eSeed.test.ts # 9 passed pnpm test # 357 passed, 23 failed The 23 failures are pre-existing: stashing these changes and running the same suite gives 348 passed and the same 23 failures in the same files, so this commit adds 9 passing tests and changes nothing else. Found on the way, unrelated to this issue: `pnpm install --frozen-lockfile` fails on `main` because `package.json` lists `next-intl` and `pnpm-lock.yaml` does not, so a locked install cannot resolve. Worth fixing separately — the lockfile here is untouched by this commit. --- e2e/farm.spec.ts | 13 +-- e2e/globals.d.ts | 16 ++++ e2e/lock-unlock-lifecycle.spec.ts | 13 +-- src/context/index.tsx | 12 ++- src/lib/e2eSeed.test.ts | 127 ++++++++++++++++++++++++++++++ src/lib/e2eSeed.ts | 68 ++++++++++++++++ 6 files changed, 229 insertions(+), 20 deletions(-) create mode 100644 e2e/globals.d.ts create mode 100644 src/lib/e2eSeed.test.ts create mode 100644 src/lib/e2eSeed.ts diff --git a/e2e/farm.spec.ts b/e2e/farm.spec.ts index 35462d6..8e34b93 100644 --- a/e2e/farm.spec.ts +++ b/e2e/farm.spec.ts @@ -173,8 +173,7 @@ function makeMockPosition(lockedAtMs: number) { async function seedPools(page: Page): Promise { await page.evaluate((pool) => { - const qc = (window as any).__queryClient; - if (qc) qc.setQueryData(['pools'], [pool]); + window.__e2e?.seedPools([pool]); }, MOCK_POOL); } @@ -182,10 +181,8 @@ async function seedPosition(page: Page, lockedAtMs: number): Promise { const pos = makeMockPosition(lockedAtMs); await page.evaluate( ({ pool, position, pubKey }) => { - const qc = (window as any).__queryClient; - if (!qc) return; - qc.setQueryData(['pools'], [pool]); - qc.setQueryData(['userPosition', 'all', pubKey], [{ pool, position }]); + window.__e2e?.seedPools([pool]); + window.__e2e?.seedPositions(pubKey, [{ pool, position }]); }, { pool: MOCK_POOL, position: pos, pubKey: TEST_PUBLIC_KEY }, ); @@ -350,8 +347,6 @@ test.describe('Farm E2E', () => { // After success, update cache to show 0 stake await page.evaluate( ({ pool, pubKey }) => { - const qc = (window as any).__queryClient; - if (!qc) return; const emptyPos = { user: pubKey, poolId: 'pool-xlm', @@ -361,7 +356,7 @@ test.describe('Farm E2E', () => { isLocked: false, unlockableAt: 0, }; - qc.setQueryData(['userPosition', 'all', pubKey], [{ pool, position: emptyPos }]); + window.__e2e?.seedPositions(pubKey, [{ pool, position: emptyPos }]); }, { pool: MOCK_POOL, pubKey: TEST_PUBLIC_KEY }, ); diff --git a/e2e/globals.d.ts b/e2e/globals.d.ts new file mode 100644 index 0000000..45e6269 --- /dev/null +++ b/e2e/globals.d.ts @@ -0,0 +1,16 @@ +import type { E2ESeedApi } from "../src/lib/e2eSeed"; + +declare global { + interface Window { + /** + * Installed by `src/context/index.tsx` in development and when + * NEXT_PUBLIC_E2E=true, which is what the Playwright config sets. + * + * Specs seed through this rather than through the QueryClient, so the query + * keys live in one place: `src/lib/e2eSeed.ts`. + */ + __e2e?: E2ESeedApi; + } +} + +export {}; diff --git a/e2e/lock-unlock-lifecycle.spec.ts b/e2e/lock-unlock-lifecycle.spec.ts index 3b3c272..0e7dd73 100644 --- a/e2e/lock-unlock-lifecycle.spec.ts +++ b/e2e/lock-unlock-lifecycle.spec.ts @@ -182,18 +182,15 @@ function makeMockPosition(lockedAtMs: number, amount = '10.0000000') { async function seedPools(page: Page): Promise { await page.evaluate((pool) => { - const qc = (window as any).__queryClient; - if (qc) qc.setQueryData(['pools'], [pool]); + window.__e2e?.seedPools([pool]); }, MOCK_POOL); } async function seedPosition(page: Page, lockedAtMs: number): Promise { await page.evaluate( ({ pool, position, pubKey }) => { - const qc = (window as any).__queryClient; - if (!qc) return; - qc.setQueryData(['pools'], [pool]); - qc.setQueryData(['userPosition', 'all', pubKey], [{ pool, position }]); + window.__e2e?.seedPools([pool]); + window.__e2e?.seedPositions(pubKey, [{ pool, position }]); }, { pool: MOCK_POOL, position: makeMockPosition(lockedAtMs), pubKey: TEST_PUBLIC_KEY }, ); @@ -202,9 +199,7 @@ async function seedPosition(page: Page, lockedAtMs: number): Promise { async function seedEmptyPosition(page: Page): Promise { await page.evaluate( ({ pool, position, pubKey }) => { - const qc = (window as any).__queryClient; - if (!qc) return; - qc.setQueryData(['userPosition', 'all', pubKey], [{ pool, position }]); + window.__e2e?.seedPositions(pubKey, [{ pool, position }]); }, { pool: MOCK_POOL, position: makeMockPosition(0, '0.0000000'), pubKey: TEST_PUBLIC_KEY }, ); diff --git a/src/context/index.tsx b/src/context/index.tsx index 42d1cb5..da3a8f3 100644 --- a/src/context/index.tsx +++ b/src/context/index.tsx @@ -9,9 +9,17 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { type ReactNode, useEffect, useState } from "react"; +import { createE2ESeedApi, type E2ESeedApi } from "@/lib/e2eSeed"; + declare global { interface Window { - __queryClient?: QueryClient; + /** + * Seeding surface for the end-to-end specs. Exposed in development and when + * NEXT_PUBLIC_E2E is set, and deliberately not the raw QueryClient: the specs + * ask for the state they want instead of spelling out query keys, so renaming + * a key cannot break a test in a file that has nothing to do with it. + */ + __e2e?: E2ESeedApi; } } @@ -25,7 +33,7 @@ function ContextProvider({ children }: { children: ReactNode }) { typeof window !== 'undefined' && (process.env.NODE_ENV !== 'production' || process.env.NEXT_PUBLIC_E2E === 'true') ) { - window.__queryClient = queryClient; + window.__e2e = createE2ESeedApi(queryClient); } }, [queryClient]); diff --git a/src/lib/e2eSeed.test.ts b/src/lib/e2eSeed.test.ts new file mode 100644 index 0000000..80c1f05 --- /dev/null +++ b/src/lib/e2eSeed.test.ts @@ -0,0 +1,127 @@ +// @vitest-environment jsdom +/** + * The seeding API is small, but it is the contract every E2E spec now depends + * on, so it is checked directly: which keys it writes, and that those keys are + * the ones the hooks read. jsdom because it imports `useSorobanQuery` for + * QUERY_KEYS, which is the whole point — the module under test and the specs + * both lean on that one spelling. + */ +import { QueryClient } from '@tanstack/react-query'; +import { describe, expect, it } from 'vitest'; +import { existsSync, readFileSync, readdirSync } from 'node:fs'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +import { ALL_POOLS, createE2ESeedApi } from './e2eSeed'; +import { QUERY_KEYS } from '../hooks/useSorobanQuery'; +import type { PoolInfo, UserPosition } from './soroban-parsers'; + +const here = dirname(fileURLToPath(import.meta.url)); +const repoRoot = join(here, '..', '..'); +const PUBLIC_KEY = 'GBQ3WPTHKJ5XKWLOKUZJLZL2GVXR6RWQCXUVDQZWM7Q2YNLDRVGM5ZWJ'; + +// The shapes come from the contract parsers, which the E2E stubs already fake +// with plain objects; these tests are about keys and lifetime, not parsing. +const POOL = { id: 'pool-xlm', assetCode: 'XLM' } as unknown as PoolInfo; +const POSITION = { + user: PUBLIC_KEY, + poolId: 'pool-xlm', + amount: '10.0000000', + lockedAt: 1_750_000_000_000, + credits: '0', + isLocked: true, + unlockableAt: 1_750_604_800_000, +} as unknown as UserPosition; + +function api(): { client: QueryClient; seed: ReturnType } { + const client = new QueryClient(); + return { client, seed: createE2ESeedApi(client) }; +} + +describe('e2e seeding API', () => { + it('writes pools under the key the hook reads', () => { + const { client, seed } = api(); + + seed.seedPools([POOL]); + + expect(client.getQueryData([QUERY_KEYS.POOLS])).toEqual([POOL]); + }); + + it('writes positions under the key the app invalidates', () => { + const { client, seed } = api(); + + seed.seedPositions(PUBLIC_KEY, [{ pool: POOL, position: POSITION }]); + + expect(client.getQueryData([QUERY_KEYS.USER_POSITION, 'all', PUBLIC_KEY])).toEqual([ + { pool: POOL, position: POSITION }, + ]); + }); + + it('keeps positions per account, so one seed cannot leak into another', () => { + const { client, seed } = api(); + const other = 'GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF'; + + seed.seedPositions(PUBLIC_KEY, [{ pool: POOL, position: POSITION }]); + + expect(client.getQueryData([QUERY_KEYS.USER_POSITION, 'all', other])).toBeUndefined(); + }); + + it('clears positions without touching the pool list', () => { + const { client, seed } = api(); + seed.seedPools([POOL]); + seed.seedPositions(PUBLIC_KEY, [{ pool: POOL, position: POSITION }]); + + seed.clearPositions(PUBLIC_KEY); + + expect(client.getQueryData([QUERY_KEYS.USER_POSITION, 'all', PUBLIC_KEY])).toEqual([]); + expect(client.getQueryData([QUERY_KEYS.POOLS])).toEqual([POOL]); + }); + + it('resets everything it seeded', () => { + const { client, seed } = api(); + seed.seedPools([POOL]); + seed.seedPositions(PUBLIC_KEY, [{ pool: POOL, position: POSITION }]); + + seed.reset(); + + expect(client.getQueryData([QUERY_KEYS.POOLS])).toBeUndefined(); + expect(client.getQueryData([QUERY_KEYS.USER_POSITION, 'all', PUBLIC_KEY])).toBeUndefined(); + }); + + it('pins the key spellings the specs rely on', () => { + // If the app renames a key, this fails here — next to the reason — rather + // than somewhere unrelated inside a spec. + expect(QUERY_KEYS.POOLS).toBe('pools'); + expect(QUERY_KEYS.USER_POSITION).toBe('userPosition'); + expect(ALL_POOLS).toBe('all'); + }); +}); + +describe('spec coupling', () => { + const specDirs = ['e2e', 'tests'] + .map((name) => join(repoRoot, name)) + .filter((path) => existsSync(path)); + + const specFiles = specDirs.flatMap((dir) => + readdirSync(dir) + .filter((name) => name.endsWith('.ts')) + .map((name) => join(dir, name)), + ); + + it('has specs to check, so this cannot pass vacuously', () => { + expect(specFiles.length).toBeGreaterThan(0); + }); + + it('leaves no spec reaching for the raw QueryClient', () => { + const offenders = specFiles.filter((file) => readFileSync(file, 'utf8').includes('__queryClient')); + + expect(offenders).toEqual([]); + }); + + it('no longer hands the raw QueryClient to the page', () => { + const context = readFileSync(join(repoRoot, 'src', 'context', 'index.tsx'), 'utf8'); + + expect(context).not.toContain('__queryClient'); + expect(context).toContain('createE2ESeedApi'); + }); +}); diff --git a/src/lib/e2eSeed.ts b/src/lib/e2eSeed.ts new file mode 100644 index 0000000..32400c4 --- /dev/null +++ b/src/lib/e2eSeed.ts @@ -0,0 +1,68 @@ +/** + * E2E seeding surface. + * + * The specs used to reach into `window.__queryClient` and call `setQueryData` + * themselves, which coupled every test to two things it should not know about: + * the QueryClient instance, and the literal spelling of each query key. Rename a + * key and an unrelated test starts failing; drop the global and every spec breaks + * at once. + * + * This module owns that knowledge instead — the keys sit next to the hooks that + * define them — and the app installs it under the same development/E2E condition + * the raw client used to be exposed under. The specs say *what* state they want + * rather than *where* it lives. + */ + +import type { QueryClient } from '@tanstack/react-query'; + +import { QUERY_KEYS } from '@/hooks/useSorobanQuery'; +import type { PoolInfo, UserPosition } from '@/lib/soroban-parsers'; + +/** + * The pool id the app uses for "every position of this account", as seen in + * `PoolDetailClient` and `UnlockModal`. Kept here so both the seeding and the + * spec that reads it agree on one spelling. + */ +export const ALL_POOLS = 'all'; + +export interface SeededPosition { + pool: PoolInfo; + position: UserPosition; +} + +export interface E2ESeedApi { + /** Replaces the cached pool list. */ + seedPools(pools: PoolInfo[]): void; + /** Caches positions for `publicKey` under the same key the app reads. */ + seedPositions(publicKey: string, entries: SeededPosition[]): void; + /** Clears the cached positions for `publicKey`. */ + clearPositions(publicKey: string): void; + /** Drops everything this API can seed, for a test that starts from nothing. */ + reset(): void; +} + +export function createE2ESeedApi(queryClient: QueryClient): E2ESeedApi { + const positionKey = (publicKey: string): [string, string, string] => [ + QUERY_KEYS.USER_POSITION, + ALL_POOLS, + publicKey, + ]; + + return { + seedPools: (pools) => { + queryClient.setQueryData([QUERY_KEYS.POOLS], pools); + }, + + seedPositions: (publicKey, entries) => { + queryClient.setQueryData(positionKey(publicKey), entries); + }, + + clearPositions: (publicKey) => { + queryClient.setQueryData(positionKey(publicKey), []); + }, + + reset: () => { + queryClient.clear(); + }, + }; +} From b228bf10463862605002cf7eb8d0ab7d93d1bf65 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Thu, 24 Sep 2026 16:03:28 +0000 Subject: [PATCH 2/2] fix(deps): sync the lockfile with next-intl so installs stop failing (cherry picked from commit df3163e77527932671c59e6c33fcf41fbdea7c0f) --- pnpm-lock.yaml | 491 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 439 insertions(+), 52 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3643c1e..7db46f5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,6 +43,9 @@ importers: next: specifier: 15.5.24 version: 15.5.24(@playwright/test@1.62.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + next-intl: + specifier: ^4.14.6 + version: 4.14.7(@types/react@19.2.17)(next@15.5.24(@playwright/test@1.62.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8) react: specifier: ^19.0.0 version: 19.2.8 @@ -288,6 +291,15 @@ packages: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} + '@eloqnt/config@0.1.0': + resolution: {integrity: sha512-SLR6ZSHxu6XdZtmOz3xRmC3gsY/sCzqtLMD1gxbW2I3XXPBbupwL5RZbkLU/NcZm74AKZrIUPfz3CtEJfxUKqQ==} + + '@eloqnt/format-json@0.1.0': + resolution: {integrity: sha512-4Pkb+HyzgWNJXoU48aJhUyNZSjZvMGooPCNG1ZFmBm55xTiNNPQCNXH66Ob6sXS6RvbWZrRpCf+Uo/Jz9K9g+A==} + + '@eloqnt/format-po@0.1.0': + resolution: {integrity: sha512-odgtuICWs67GdkNqY51/d2vaIukuOdlGalKASUGkI5c4cyWOmv/WIVyk5gZyn3xr614RzwWp57s9WB40lRLlBw==} + '@emnapi/core@1.10.0': resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} @@ -396,15 +408,33 @@ packages: '@formatjs/fast-memoize@2.2.7': resolution: {integrity: sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==} + '@formatjs/fast-memoize@3.1.7': + resolution: {integrity: sha512-zXfhLpvA6T7+efdt9JLbBwZ00tT7NsBMDVnDu8rpHeNNv8KfRZAMo2gkG0k9lK/Nzc//3kJ9pImsfuJxk3KhUA==} + '@formatjs/icu-messageformat-parser@2.11.4': resolution: {integrity: sha512-7kR78cRrPNB4fjGFZg3Rmj5aah8rQj9KPzuLsmcSn4ipLXQvC04keycTI1F7kJYDwIXtT2+7IDEto842CfZBtw==} + '@formatjs/icu-messageformat-parser@3.5.18': + resolution: {integrity: sha512-wX1efcL8d7K5QapOTRsP/OLTA/kpwe4LwqWyNxDNg5iRs8i9jJbCyxB5P8jc4KOW5oiLzz2DJr+BRY5xMV9+bA==} + + '@formatjs/icu-messageformat-parser@3.5.20': + resolution: {integrity: sha512-DUzCb2iskGDKvLU7P+nz/rjpmN59luoTRbWHFFNYNnZTxWCKvwPI94rNll99TGZaI6XoTbDF0QGegk21GFrQZQ==} + '@formatjs/icu-skeleton-parser@1.8.16': resolution: {integrity: sha512-H13E9Xl+PxBd8D5/6TVUluSpxGNvFSlN/b3coUp0e0JpuWXXnQDiavIpY3NnvSp4xhEMoXyyBvVfdFX8jglOHQ==} + '@formatjs/icu-skeleton-parser@2.1.11': + resolution: {integrity: sha512-j8cUmOJzVgkHuS0QiQ6ga76UIoLOFSAMWhs7aZJztH3aAdCOAE6vpC8KVvFB4cU10ON0y2/5oOVmPJ43s2lTwA==} + + '@formatjs/icu-skeleton-parser@2.1.12': + resolution: {integrity: sha512-ca7tZMLpfHX3sUD7hP6gE/qr6Iq89EDd3ZLeRhbsB7r0UD55DGJq+tmFLzrGrnx5StahUevQmQQVtbDRHsfDHA==} + '@formatjs/intl-localematcher@0.6.2': resolution: {integrity: sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==} + '@formatjs/intl-localematcher@0.8.14': + resolution: {integrity: sha512-8O7V38QmbB11+ryJ3KM/znrzXtiqgpXzqNoqDsndHZZ5/zDKTTL+cf5F0mzXkQEwhx8IlWnqYvEovf2S5EwLTw==} + '@humanwhocodes/config-array@0.13.0': resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} @@ -453,105 +483,89 @@ packages: resolution: {integrity: sha512-C0SqjoFKnszqa44EQ7xoaT48nnO0lOyXEULfXMWi8krrjOPGYkeK30Okzla6ATbBYsyZ0ySinK0FVkpv3DwzfQ==} cpu: [arm64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-arm@1.3.0': resolution: {integrity: sha512-A8UpHoUDW4DwnXoV6+q3C1s7QLRAHtPDEjWuNZjwHMyoCNZnm0GeNN8ls9f/bsEYTRQRW96C/n34XJQHJ2fT7A==} cpu: [arm] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-ppc64@1.3.0': resolution: {integrity: sha512-WOpkVxAjFd369iaIzEgNRreFD+gWdUMIGD5zplhNKNeqS6mm5dac3q2AFyCBmzYoAdouzZvRBgxy4z8QHZb4/A==} cpu: [ppc64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-riscv64@1.3.0': resolution: {integrity: sha512-DRWw0mOHusrCCuw2rqP87oLg6PGlkomVDFqw2hIwsSfwWpu4k3XLcBPaKKl6ct/GtL/cwNkgwjV/tc0Mqht3VA==} cpu: [riscv64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-s390x@1.3.0': resolution: {integrity: sha512-9APy+nFWhHS+kzLgWZfLcyrUd7YqnAQVa4BPOo4xkoHpdoktOAPG4cEr9+Jpl0TtqfVmcMJimNL5qNTyyOHZNA==} cpu: [s390x] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-x64@1.3.0': resolution: {integrity: sha512-y9RNUYDe2A1UAdhLyfeOodGRszQdaEoe4nfOpp/sNVPl2CWIcUyFaDoCh4vPLPxu19803j2naLqZup2WxDXCLA==} cpu: [x64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.3.0': resolution: {integrity: sha512-cC1wkC0Mlucd0KSiGrLkJnB/ZqPvZCntc/Lk7ZnYO5ZSbF2euNek4Xvxafojq+wN1q/W0eprdpUIjUr/EV2PBg==} cpu: [arm64] os: [linux] - libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.3.0': resolution: {integrity: sha512-LiYMhUZicB1QG//+RvmYZpXJO8fYRENfp+MZUCnG9aw+AKvGAy9gPaCnuwsPcBFs8EV66M0NNxj9VHcNklE8zw==} cpu: [x64] os: [linux] - libc: [musl] '@img/sharp-linux-arm64@0.35.0': resolution: {integrity: sha512-4+4XHLNT5wDT0roYlHTEmH9lDKt0acf9Tv+3hM3iceOirkxrR404/3WjAYZ9F9CkHrxeRcGLJXbi4vluMZ9O+A==} engines: {node: '>=20.9.0'} cpu: [arm64] os: [linux] - libc: [glibc] '@img/sharp-linux-arm@0.35.0': resolution: {integrity: sha512-VVlpEWwizEFIOom0zdoeKuO5nuTswzVE5uHcBNvHzmeHUpNFajY3HFfbQ+zIH4E2kVaZ/yVxmsShW56TtEy4uA==} engines: {node: '>=20.9.0'} cpu: [arm] os: [linux] - libc: [glibc] '@img/sharp-linux-ppc64@0.35.0': resolution: {integrity: sha512-N3hzbEpUTJC8pWpPVJvgzGxM+so/MAXc8O2s/53B0LL9ZGpfXpME7Wizkc5d/8fRBlBtkDjzoZGDCqqNDHqLEw==} engines: {node: '>=20.9.0'} cpu: [ppc64] os: [linux] - libc: [glibc] '@img/sharp-linux-riscv64@0.35.0': resolution: {integrity: sha512-l6vmKVPnbS0RhVMbyxP5meAARsbhCnBN4fy31qz0+3a6Rv4jEqfzDrT89y6ZPkCi0AJGnwp2En528yXo401Hpw==} engines: {node: '>=20.9.0'} cpu: [riscv64] os: [linux] - libc: [glibc] '@img/sharp-linux-s390x@0.35.0': resolution: {integrity: sha512-MYlMiPFiv/EKPAHnp3yNZ9AAWFsxga9c5Bkc6wkar6bqzHLlkGVJHRm0u1ei+VXnZxp3Mz9MG9ZIsI8vSOf3sQ==} engines: {node: '>=20.9.0'} cpu: [s390x] os: [linux] - libc: [glibc] '@img/sharp-linux-x64@0.35.0': resolution: {integrity: sha512-TYaItB5oj1ioXjhyn2xrR208vf+YuIIcHptQWRRaBmFhvIvL9D72DXN8w75xup0KXA8UdEAhQ9Qb2S49FD/9Cw==} engines: {node: '>=20.9.0'} cpu: [x64] os: [linux] - libc: [glibc] '@img/sharp-linuxmusl-arm64@0.35.0': resolution: {integrity: sha512-DSTb6ijQzqe6DdAaOBVqJ/SYf1vO8EW5bK6X6LRXufEBebf2722VCdvBUtZ3rtV0x2ApfPNDy/p7LrrjaWjiyQ==} engines: {node: '>=20.9.0'} cpu: [arm64] os: [linux] - libc: [musl] '@img/sharp-linuxmusl-x64@0.35.0': resolution: {integrity: sha512-K7ykQ+26Rt6+4BTU80AuGgTPIYX86UxiAKT4rcXX/WNTo7k1ZxpKz+TguHnwVpCqQK3B5PK0vZ0ZBe6nz/ib1w==} engines: {node: '>=20.9.0'} cpu: [x64] os: [linux] - libc: [musl] '@img/sharp-wasm32@0.35.0': resolution: {integrity: sha512-9woLIFORERCr+6cWu87dQ22J34EExkhc73U1kZW0c+RclQqWetoodByp4dWZ/hN8/KVmTRAx2HOnUwib8AwZdA==} @@ -636,28 +650,24 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [glibc] '@next/swc-linux-arm64-musl@15.5.24': resolution: {integrity: sha512-TlNAnpsjxSF3aAUtqnfmtXXf8m9sIDBlmF3c7bTAlnshUYu2U0OxN2uf5d0gcFwqHVEdivJNBcCaqNOwPGNimw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [musl] '@next/swc-linux-x64-gnu@15.5.24': resolution: {integrity: sha512-7dwtlhr0SLndqTG1z9ncRkbJswDZiKWlxzFyXDvJ2RDZRDRHp8zyMJ4D9UH/FgnQeXxxB6gZy2pMcIUoNKQ4pA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [glibc] '@next/swc-linux-x64-musl@15.5.24': resolution: {integrity: sha512-kGZxM+WhkYs0276lFrMkj7PRtXT3Btp6cwvfSO/cCVLxJJttB5Ccnl2niaCgUja8HgSbEVnMHpg3FJWoOJ9e/g==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [musl] '@next/swc-win32-arm64-msvc@15.5.24': resolution: {integrity: sha512-jBDDkZ/qKAqkWivWDMkJSXUzbzV0QKRBKJjEHUAvSB97Hzw7NLzJ6yV56Lts/wjir7s4P31GYgpbS6ZL+hasAA==} @@ -705,6 +715,82 @@ packages: '@oxc-project/types@0.139.0': resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + '@parcel/watcher-android-arm64@2.6.0': + resolution: {integrity: sha512-trgpLSCKRC/huFjXX/Smh+0sWe4+YtKfktIToiMl59ghz7z+qkH6kMvNnUbLyRs9N11t8l4svSCs1+5B3rOAhA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.6.0': + resolution: {integrity: sha512-Y3QV0gl7Q1zbfueunkWIERICbEojQFCgpyG7YqOGNFLsckXyI1xu9mAIUpKY9QBYzBtSkN8dBPwd3yiAO9ovMw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.6.0': + resolution: {integrity: sha512-Ohv6OpzhUfKYD7Beb8kDvG0jbIxORCYY1JRdZnaBtnjjkJxgD7ZVL0nw2sCYd0yTMKTvz3nnTnOF3cDifK+kvw==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.6.0': + resolution: {integrity: sha512-5HmXvDgs8VK+74jF9y9/2FE3/OnlcKmc56tjmSrEuZjpSZOGL+fvAu+HKJBdPs9uwoP2hE6TlSUpXZ/C5jUFmQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.6.0': + resolution: {integrity: sha512-Ps/hui3A+vMbjdqlqAowK2ZL8+BO8dBjxeWXj6npTBs3jx4wWmbPpaLuqwrQrSqIVMCnpWo238bJ1U37GhQOYg==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + + '@parcel/watcher-linux-arm-musl@2.6.0': + resolution: {integrity: sha512-9c6AUHgHoG+IY88MRIHupztQiQnrbqHYQjkM2btA+Bf/wQnQMuiD0Wfk1EVv3TlNT3x41uU71rn6E4xh/+zvkw==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + + '@parcel/watcher-linux-arm64-glibc@2.6.0': + resolution: {integrity: sha512-yHRqS2owEXe6Hic9z6Mh1ECsCd+ODVOGvZDyciqRd21+v+o+DnXMOrw50DSpIG2sb8GPEaPPmfeCAWKPJdq46g==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-arm64-musl@2.6.0': + resolution: {integrity: sha512-WhB2e/V7rqdHHWZusBSPuy5Ei8S6lSz6FE5TKKQz5h3a0O+C+mhY7vxU9b/stqvMb8beLnPY82ZrFTLKs+SrKA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-x64-glibc@2.6.0': + resolution: {integrity: sha512-ulGE6x6Oz6iAwg75T8YQSoguBWasniIbX+QWpaYPcCnDOpdWX3k+4xbEYPZVLxOuoJI+svJJPD3sEj8G7lrQ3A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-linux-x64-musl@2.6.0': + resolution: {integrity: sha512-tkBYKt7YQrjIJWYDnto2YgO8MRkjlMTSNoRHzsXinBqbLdeOM3L32wPZJvIZxqaLMfSlS/4sUjH/6STVP/XDLw==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-win32-arm64@2.6.0': + resolution: {integrity: sha512-gIZAP23jaHjGWasY/TY6yL7NHFClf0Ga7FN+iINvk+KN94rhm94lYZhFsbYFNcA04/onvGD9kKmiJLJB2HbNwQ==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-x64@2.6.0': + resolution: {integrity: sha512-cA+/pXV2YkfxlIcXOQ5fSWqAzzPyD78/x5qbK/I0vUkrlYHA8TIz+MXjAbGouguKVSI4bOmkTSJ1/poVSsgt+A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.6.0': + resolution: {integrity: sha512-7FNeNl8NCE7aINx7WXiKQrPYZWC/hvrTsmk6zmxbI7LTXE7hVek/n8AfVgpe2y82zl3w0HvCHN0bVKMBoJcC0w==} + engines: {node: '>= 10.0.0'} + '@paulirish/trace_engine@0.0.53': resolution: {integrity: sha512-PUl/vlfo08Oj804VI5nDPeSk9vyslnBlVzDDwFt8SUVxY8+KdGMkra/vrXjEEHe8gb7+RqVTfOIlGw0nyrEelA==} @@ -770,42 +856,36 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [glibc] '@rolldown/binding-linux-arm64-musl@1.1.5': resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [musl] '@rolldown/binding-linux-ppc64-gnu@1.1.5': resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - libc: [glibc] '@rolldown/binding-linux-s390x-gnu@1.1.5': resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] - libc: [glibc] '@rolldown/binding-linux-x64-gnu@1.1.5': resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [glibc] '@rolldown/binding-linux-x64-musl@1.1.5': resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [musl] '@rolldown/binding-openharmony-arm64@1.1.5': resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==} @@ -839,6 +919,9 @@ packages: '@rushstack/eslint-patch@1.16.1': resolution: {integrity: sha512-TvZbIpeKqGQQ7X0zSCvPH9riMSFQFSggnfBjFZ1mEoILW+UuXCKwOoPcgjMwiUtRqFZ8jWhPJc4um14vC6I4ag==} + '@schummar/icu-type-parser@1.21.5': + resolution: {integrity: sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==} + '@sentry-internal/tracing@7.120.4': resolution: {integrity: sha512-Fz5+4XCg3akeoFK+K7g+d7HqGMjmnLoY2eJlpONJmaeT9pXY7yfUyXKZMmMajdE2LxxKJgQ2YKvSCaGVamTjHw==} engines: {node: '>=8'} @@ -886,9 +969,96 @@ packages: engines: {node: '>=22.0.0'} hasBin: true + '@swc/core-darwin-arm64@1.16.2': + resolution: {integrity: sha512-i/j0HNbnn79qnTVPicvay92Nark8fW8NQqn1e2mGERjUXNpBV0+SwQxlRpk2zBhn6laJ8PDI6Kn1nHZhnz3LCA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + + '@swc/core-darwin-x64@1.16.2': + resolution: {integrity: sha512-HrwqHyEyHVXO3qTk8EkNK7/b6sOZSEoNh+pot6RdE5x0LbNqfo8LtJUvi3UTXr+5ja/o5HbJdW80eCXo+NjbiA==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + + '@swc/core-linux-arm-gnueabihf@1.16.2': + resolution: {integrity: sha512-MdXi83Z/gGp1LIrg+h7HKxiul/z/Bty/ZJSvYAFqDl9zteC1XLSAZdScquKtXPp50rdyXqritTDCqQBhwVfZKA==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + + '@swc/core-linux-arm64-gnu@1.16.2': + resolution: {integrity: sha512-/jcTmK6Ktz3owM3YtiKvjofV6p3VpHnYzTIrOGwDIOsDigRAAVuZ8east33wYO/7UTdKYFlyHNnJNT0WJqOA3Q==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-arm64-musl@1.16.2': + resolution: {integrity: sha512-4gFarKaFnlJTSlJYKmMhV4u+3YE4uYfiydpBoYjmgQhCf9lAieOq+WilZaK9vVSHeqLuQpTEiGULZqAdsRX5Dw==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-ppc64-gnu@1.16.2': + resolution: {integrity: sha512-syqSLGd6KlZ1PciNzs6bIUlhOuFztZufebOHaERjc4N4SqNZxyqYd4I+jj/EfOYnpe0kNjccn9HJLN1p5dz3+w==} + engines: {node: '>=10'} + cpu: [ppc64] + os: [linux] + + '@swc/core-linux-s390x-gnu@1.16.2': + resolution: {integrity: sha512-ZBBLK+ewGyXLzWeMS7wbKtWBdnif6etn7xvPY/iOfbdsjX/+bgkp1pQt2lWF2wlu2hXYZuhJ/tHZE/QR8/apzg==} + engines: {node: '>=10'} + cpu: [s390x] + os: [linux] + + '@swc/core-linux-x64-gnu@1.16.2': + resolution: {integrity: sha512-LyHJgxCA4Tje0ysBMbEb0tt/ie8kgUKoFE3JAKFhpevmTmhYEoC0H9s47WuDsqiFckF1ITUguZIXJG6K5e0dvg==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-linux-x64-musl@1.16.2': + resolution: {integrity: sha512-PghXJlVM1cgtLfNUR1vxFo1z+PDRAe8cWAJlZZ7spmeiN7BospGXg/MHUg7oNSgwSX7Zo//YKv9P5yD9apsFJQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-win32-arm64-msvc@1.16.2': + resolution: {integrity: sha512-StTOSefYBxemvNYYUI3UmO1a8y+hSPjjfHogC2TEHL+Z1PlEBim/XtLas5rS04jAzT9RrNmbtX911SZ42H9jSQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + + '@swc/core-win32-ia32-msvc@1.16.2': + resolution: {integrity: sha512-fycER209DYIzsibpTMC+chND05OfOjgztWL9U8OE6/uUlsOUZH3eh98isBLEnOymYUhlJLEt5++W1+KL/FOh5Q==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + + '@swc/core-win32-x64-msvc@1.16.2': + resolution: {integrity: sha512-cSd1z6ivSrJPVr+moVwOHWjeKy6TpO4/Shwcv5KCrKYXCccxwh4pRy1C3fDioNx2PF1jPZWHKZjtXt+Be9VbaQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + + '@swc/core@1.16.2': + resolution: {integrity: sha512-95I4kiSMeveI/Mhi+tE4fiWcWLUMfzfKrk0jtr8LRMqHgOgq+xHS+zExkDqoO4b5OeeuXHMWVdD5MeP3X6sULw==} + engines: {node: '>=10'} + peerDependencies: + '@swc/helpers': '>=0.5.17' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} + '@swc/types@0.1.28': + resolution: {integrity: sha512-V6Mnml8v09QALx6K0elJ7o9K/MkVDtW3t6L+7Ou/JcWtb3xwId2AH4FeOceySd2JaO87IMw4+6vSZxLm34LPbw==} + '@tailwindcss/node@4.3.3': resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} @@ -927,28 +1097,24 @@ packages: engines: {node: '>= 20'} cpu: [arm64] os: [linux] - libc: [glibc] '@tailwindcss/oxide-linux-arm64-musl@4.3.3': resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] - libc: [musl] '@tailwindcss/oxide-linux-x64-gnu@4.3.3': resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==} engines: {node: '>= 20'} cpu: [x64] os: [linux] - libc: [glibc] '@tailwindcss/oxide-linux-x64-musl@4.3.3': resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==} engines: {node: '>= 20'} cpu: [x64] os: [linux] - libc: [musl] '@tailwindcss/oxide-wasm32-wasi@4.3.3': resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==} @@ -1183,61 +1349,51 @@ packages: resolution: {integrity: sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==} cpu: [arm64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-arm64-musl@1.12.2': resolution: {integrity: sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==} cpu: [arm64] os: [linux] - libc: [musl] '@unrs/resolver-binding-linux-loong64-gnu@1.12.2': resolution: {integrity: sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==} cpu: [loong64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-loong64-musl@1.12.2': resolution: {integrity: sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==} cpu: [loong64] os: [linux] - libc: [musl] '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2': resolution: {integrity: sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==} cpu: [ppc64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2': resolution: {integrity: sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==} cpu: [riscv64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-riscv64-musl@1.12.2': resolution: {integrity: sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==} cpu: [riscv64] os: [linux] - libc: [musl] '@unrs/resolver-binding-linux-s390x-gnu@1.12.2': resolution: {integrity: sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==} cpu: [s390x] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-x64-gnu@1.12.2': resolution: {integrity: sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==} cpu: [x64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-x64-musl@1.12.2': resolution: {integrity: sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==} cpu: [x64] os: [linux] - libc: [musl] '@unrs/resolver-binding-openharmony-arm64@1.12.2': resolution: {integrity: sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==} @@ -1724,6 +1880,10 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} + content-type@2.1.0: + resolution: {integrity: sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==} + engines: {node: '>=18'} + convert-source-map@1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} @@ -2462,6 +2622,9 @@ packages: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} + icu-minify@4.14.7: + resolution: {integrity: sha512-cbBAiLGee7kzysqaoQLLaIXAYaKEhNRYo05ye9rLj8+MLq/VurqLBHv6vqhTVeyQ7jcvuTujkxmiR1Au4ku8nw==} + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -2512,6 +2675,9 @@ packages: intl-messageformat@10.7.18: resolution: {integrity: sha512-m3Ofv/X/tV8Y3tHXLohcuVuhWKo7BBq62cqY15etqmLxg2DZ34AGGgQDeR+SCta2+zICb1NX83af0GJmbQ1++g==} + intl-messageformat@11.2.15: + resolution: {integrity: sha512-W4VNytsXyWgW5lvVchmsb9xgA5rSKqoflu3/IQ9UCtB0z4R+Bx9MoEkwFT/+30RCl/KzUoH0QGGe9lppF5SuvQ==} + ip-address@10.5.0: resolution: {integrity: sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==} engines: {node: '>= 12'} @@ -2852,56 +3018,48 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] lightningcss-linux-arm64-gnu@1.33.0: resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] lightningcss-linux-arm64-musl@1.32.0: resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] lightningcss-linux-arm64-musl@1.33.0: resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] lightningcss-linux-x64-gnu@1.32.0: resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] lightningcss-linux-x64-gnu@1.33.0: resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] lightningcss-linux-x64-musl@1.32.0: resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] lightningcss-linux-x64-musl@1.33.0: resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] lightningcss-win32-arm64-msvc@1.32.0: resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} @@ -3100,10 +3258,27 @@ packages: resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} engines: {node: '>= 0.6'} + negotiator@1.1.0: + resolution: {integrity: sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==} + engines: {node: '>=18'} + netmask@2.1.1: resolution: {integrity: sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==} engines: {node: '>= 0.4.0'} + next-intl-swc-plugin-extractor@4.14.7: + resolution: {integrity: sha512-0KUc8helXuJfyXVUQDolz0wnRnaW+dkJf6ozX6A+O9x1dd1+cb4PpZqj6FfcDdJagMuIxtnDmeRT7yUhllMYKA==} + + next-intl@4.14.7: + resolution: {integrity: sha512-VQJu34ga2pG8EO7aQO7mzinoso/XpvQdMPfifBZIeWAoyGlKU3//nt7QVwWBZuOMBne4g6onsEFk+IA5ueF61g==} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + next: ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + next@15.5.24: resolution: {integrity: sha512-Y+xn8EQCoC3ZbsFPyzE+tE8XOdrWeUdUF7NeXbmg9DsgAxl5UYxlsrvgVESHTyTGigoTa1bCUrxn70F5bqt0Gw==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} @@ -3125,6 +3300,9 @@ packages: sass: optional: true + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + node-exports-info@1.6.2: resolution: {integrity: sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==} engines: {node: '>= 0.4'} @@ -3316,6 +3494,9 @@ packages: engines: {node: '>=20'} hasBin: true + po-parser@2.2.0: + resolution: {integrity: sha512-NdTrKgh0oO7+y+RFX8KKhOB438x/j94UGXEFzl/7pHH0JjWSn42iJ9tgmPksIO6n1JKDHmNDcejPJfKspljB9g==} + possible-typed-array-names@1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} @@ -3819,8 +4000,8 @@ packages: third-party-web@0.26.7: resolution: {integrity: sha512-buUzX4sXC4efFX6xg2bw6/eZsCUh8qQwSavC4D9HpONMFlRbcHhD8Je5qwYdCpViR6q0qla2wPP+t91a2vgolg==} - third-party-web@0.29.2: - resolution: {integrity: sha512-fegtha91tq2DHphyoiBXVHjVi2YG9zFaRnboT9C28tO1en9Y3wJsfspuy40F+u5wl3hHVbw7cnd1b67kEGHb8g==} + third-party-web@0.30.0: + resolution: {integrity: sha512-p+PfyL5U0ediGzvwPzMSdD9MnC8rHW6nWJJVLIQvqN7RsSqfaZ+7n4c9GILqH36EYR0eXB9CzAeCRnKFr/9uJg==} through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} @@ -4000,6 +4181,15 @@ packages: '@types/react': optional: true + use-intl@4.14.7: + resolution: {integrity: sha512-L7l2mo3KE8OetLkyIOdKZfN0J05+e9gB7cxgrVthkjIGu1nCW9KOBgZkVcK7w0tbc3WLfnEMgX3J+vSXMCZA/A==} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + use-sidecar@1.1.3: resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} engines: {node: '>=10'} @@ -4483,6 +4673,17 @@ snapshots: '@discoveryjs/json-ext@0.5.7': {} + '@eloqnt/config@0.1.0': {} + + '@eloqnt/format-json@0.1.0': + dependencies: + '@eloqnt/config': 0.1.0 + + '@eloqnt/format-po@0.1.0': + dependencies: + '@eloqnt/config': 0.1.0 + po-parser: 2.2.0 + '@emnapi/core@1.10.0': dependencies: '@emnapi/wasi-threads': 1.2.1 @@ -4641,21 +4842,39 @@ snapshots: dependencies: tslib: 2.8.1 + '@formatjs/fast-memoize@3.1.7': {} + '@formatjs/icu-messageformat-parser@2.11.4': dependencies: '@formatjs/ecma402-abstract': 2.3.6 '@formatjs/icu-skeleton-parser': 1.8.16 tslib: 2.8.1 + '@formatjs/icu-messageformat-parser@3.5.18': + dependencies: + '@formatjs/icu-skeleton-parser': 2.1.11 + + '@formatjs/icu-messageformat-parser@3.5.20': + dependencies: + '@formatjs/icu-skeleton-parser': 2.1.12 + '@formatjs/icu-skeleton-parser@1.8.16': dependencies: '@formatjs/ecma402-abstract': 2.3.6 tslib: 2.8.1 + '@formatjs/icu-skeleton-parser@2.1.11': {} + + '@formatjs/icu-skeleton-parser@2.1.12': {} + '@formatjs/intl-localematcher@0.6.2': dependencies: tslib: 2.8.1 + '@formatjs/intl-localematcher@0.8.14': + dependencies: + '@formatjs/fast-memoize': 3.1.7 + '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 @@ -4913,10 +5132,66 @@ snapshots: '@oxc-project/types@0.139.0': {} + '@parcel/watcher-android-arm64@2.6.0': + optional: true + + '@parcel/watcher-darwin-arm64@2.6.0': + optional: true + + '@parcel/watcher-darwin-x64@2.6.0': + optional: true + + '@parcel/watcher-freebsd-x64@2.6.0': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.6.0': + optional: true + + '@parcel/watcher-linux-arm-musl@2.6.0': + optional: true + + '@parcel/watcher-linux-arm64-glibc@2.6.0': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.6.0': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.6.0': + optional: true + + '@parcel/watcher-linux-x64-musl@2.6.0': + optional: true + + '@parcel/watcher-win32-arm64@2.6.0': + optional: true + + '@parcel/watcher-win32-x64@2.6.0': + optional: true + + '@parcel/watcher@2.6.0': + dependencies: + detect-libc: 2.1.2 + is-glob: 4.0.3 + node-addon-api: 7.1.1 + picomatch: 4.0.5 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.6.0 + '@parcel/watcher-darwin-arm64': 2.6.0 + '@parcel/watcher-darwin-x64': 2.6.0 + '@parcel/watcher-freebsd-x64': 2.6.0 + '@parcel/watcher-linux-arm-glibc': 2.6.0 + '@parcel/watcher-linux-arm-musl': 2.6.0 + '@parcel/watcher-linux-arm64-glibc': 2.6.0 + '@parcel/watcher-linux-arm64-musl': 2.6.0 + '@parcel/watcher-linux-x64-glibc': 2.6.0 + '@parcel/watcher-linux-x64-musl': 2.6.0 + '@parcel/watcher-win32-arm64': 2.6.0 + '@parcel/watcher-win32-x64': 2.6.0 + '@paulirish/trace_engine@0.0.53': dependencies: legacy-javascript: 0.0.1 - third-party-web: 0.29.2 + third-party-web: 0.30.0 '@playwright/test@1.62.0': dependencies: @@ -5008,6 +5283,8 @@ snapshots: '@rushstack/eslint-patch@1.16.1': {} + '@schummar/icu-type-parser@1.21.5': {} + '@sentry-internal/tracing@7.120.4': dependencies: '@sentry/core': 7.120.4 @@ -5078,10 +5355,70 @@ snapshots: - debug - supports-color + '@swc/core-darwin-arm64@1.16.2': + optional: true + + '@swc/core-darwin-x64@1.16.2': + optional: true + + '@swc/core-linux-arm-gnueabihf@1.16.2': + optional: true + + '@swc/core-linux-arm64-gnu@1.16.2': + optional: true + + '@swc/core-linux-arm64-musl@1.16.2': + optional: true + + '@swc/core-linux-ppc64-gnu@1.16.2': + optional: true + + '@swc/core-linux-s390x-gnu@1.16.2': + optional: true + + '@swc/core-linux-x64-gnu@1.16.2': + optional: true + + '@swc/core-linux-x64-musl@1.16.2': + optional: true + + '@swc/core-win32-arm64-msvc@1.16.2': + optional: true + + '@swc/core-win32-ia32-msvc@1.16.2': + optional: true + + '@swc/core-win32-x64-msvc@1.16.2': + optional: true + + '@swc/core@1.16.2': + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.28 + optionalDependencies: + '@swc/core-darwin-arm64': 1.16.2 + '@swc/core-darwin-x64': 1.16.2 + '@swc/core-linux-arm-gnueabihf': 1.16.2 + '@swc/core-linux-arm64-gnu': 1.16.2 + '@swc/core-linux-arm64-musl': 1.16.2 + '@swc/core-linux-ppc64-gnu': 1.16.2 + '@swc/core-linux-s390x-gnu': 1.16.2 + '@swc/core-linux-x64-gnu': 1.16.2 + '@swc/core-linux-x64-musl': 1.16.2 + '@swc/core-win32-arm64-msvc': 1.16.2 + '@swc/core-win32-ia32-msvc': 1.16.2 + '@swc/core-win32-x64-msvc': 1.16.2 + + '@swc/counter@0.1.3': {} + '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 + '@swc/types@0.1.28': + dependencies: + '@swc/counter': 0.1.3 + '@tailwindcss/node@4.3.3': dependencies: '@jridgewell/remapping': 2.3.5 @@ -5921,6 +6258,8 @@ snapshots: content-type@1.0.5: {} + content-type@2.1.0: {} + convert-source-map@1.9.0: {} convert-source-map@2.0.0: {} @@ -6831,6 +7170,10 @@ snapshots: dependencies: safer-buffer: 2.1.2 + icu-minify@4.14.7: + dependencies: + '@formatjs/icu-messageformat-parser': 3.5.20 + ieee754@1.2.1: {} ignore@5.3.2: {} @@ -6888,6 +7231,11 @@ snapshots: '@formatjs/icu-messageformat-parser': 2.11.4 tslib: 2.8.1 + intl-messageformat@11.2.15: + dependencies: + '@formatjs/fast-memoize': 3.1.7 + '@formatjs/icu-messageformat-parser': 3.5.18 + ip-address@10.5.0: {} ipaddr.js@1.9.1: {} @@ -7427,8 +7775,33 @@ snapshots: negotiator@0.6.4: {} + negotiator@1.1.0: + dependencies: + content-type: 2.1.0 + netmask@2.1.1: {} + next-intl-swc-plugin-extractor@4.14.7: {} + + next-intl@4.14.7(@types/react@19.2.17)(next@15.5.24(@playwright/test@1.62.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8): + dependencies: + '@eloqnt/config': 0.1.0 + '@eloqnt/format-json': 0.1.0 + '@eloqnt/format-po': 0.1.0 + '@formatjs/intl-localematcher': 0.8.14 + '@parcel/watcher': 2.6.0 + '@swc/core': 1.16.2 + icu-minify: 4.14.7 + negotiator: 1.1.0 + next: 15.5.24(@playwright/test@1.62.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + next-intl-swc-plugin-extractor: 4.14.7 + react: 19.2.8 + use-intl: 4.14.7(@types/react@19.2.17)(react@19.2.8) + optionalDependencies: + '@types/react': 19.2.17 + transitivePeerDependencies: + - '@swc/helpers' + next@15.5.24(@playwright/test@1.62.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8): dependencies: '@next/env': 15.5.24 @@ -7453,6 +7826,8 @@ snapshots: - '@babel/core' - babel-plugin-macros + node-addon-api@7.1.1: {} + node-exports-info@1.6.2: dependencies: array.prototype.flatmap: 1.3.3 @@ -7643,6 +8018,8 @@ snapshots: optionalDependencies: fsevents: 2.3.2 + po-parser@2.2.0: {} + possible-typed-array-names@1.1.0: {} postcss-value-parser@4.2.0: {} @@ -8285,7 +8662,7 @@ snapshots: third-party-web@0.26.7: {} - third-party-web@0.29.2: {} + third-party-web@0.30.0: {} through@2.3.8: {} @@ -8482,6 +8859,16 @@ snapshots: optionalDependencies: '@types/react': 19.2.17 + use-intl@4.14.7(@types/react@19.2.17)(react@19.2.8): + dependencies: + '@formatjs/fast-memoize': 3.1.7 + '@schummar/icu-type-parser': 1.21.5 + icu-minify: 4.14.7 + intl-messageformat: 11.2.15 + react: 19.2.8 + optionalDependencies: + '@types/react': 19.2.17 + use-sidecar@1.1.3(@types/react@19.2.17)(react@19.2.8): dependencies: detect-node-es: 1.1.0