diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e487f35..d2b54fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,8 +37,11 @@ jobs: - name: Lint run: pnpm lint + - name: Knip + run: pnpm knip + - name: Test (API 100% line coverage gate) - run: pnpm test + run: pnpm test:coverage - name: Generate OpenAPI code run: pnpm openapi:generate diff --git a/PLAN.md b/PLAN.md index 47b08a9..52c672e 100644 --- a/PLAN.md +++ b/PLAN.md @@ -32,7 +32,7 @@ Tasks and subtasks for building the bread-recipes app (SolidJS + Python REST + O - [x] **4.5** Component library: evaluate options for SolidJS (e.g. **shadcn-solid** with Tailwind vs smaller stacks); record the decision; add the chosen tooling and migrate or adopt components on at least one real screen so the pattern is established. - [x] **4.6** Recipe page: full recipe content and larger image; deep-linkable route (e.g. by id). - [x] **4.7** **shadcn-solid adoption (full):** migrate remaining UI (app shell, home, recipe cards and detail sections, and any shared layout) to registry components and Tailwind utilities where it replaces bespoke CSS; align tokens with **`COMPONENT_LIBRARY.md`**; no orphaned hand-rolled controls that duplicate registry patterns. Update **`COMPONENT_LIBRARY.md`** when scope is complete. -- [ ] **4.8** MSW for tests; knip configured; Vitest coverage at 100% with a CI gate. +- [x] **4.8** MSW for tests; knip configured; Vitest coverage at 100% with a CI gate. ## 5. Contract testing (Pact) diff --git a/apps/api/README.md b/apps/api/README.md index 1e6762f..4042dd4 100644 --- a/apps/api/README.md +++ b/apps/api/README.md @@ -34,13 +34,13 @@ From **`apps/api`** with dev dependencies installed (**`pip install -e ".[dev]"` pnpm test ``` -This runs **`pytest`** with **line coverage** for the **`app`** package, **fails under 100%**, and **omits** generated **`app/openapi/generated/`** (codegen output). To run tests without coverage (faster iteration): +This runs **`pytest`** without coverage for faster iteration. ```bash -.venv/bin/python -m pytest --no-cov +pnpm test:coverage ``` -Configuration lives in **`pyproject.toml`** (**`[tool.pytest.ini_options]`**, **`[tool.coverage.*]`**). +The coverage variant runs **`pytest`** with **line coverage** for the **`app`** package, **fails under 100%**, and **omits** generated **`app/openapi/generated/`** (codegen output). Configuration lives in **`pyproject.toml`** (**`[tool.pytest.ini_options]`**, **`[tool.coverage.*]`**). ## Import order (Ruff / isort) diff --git a/apps/api/package.json b/apps/api/package.json index 56a6314..7704c13 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -10,6 +10,7 @@ "lint": "pnpm build && .venv/bin/ruff check app", "lint:fix": ".venv/bin/ruff check app --fix", "test": ".venv/bin/python -m pytest -v", + "test:coverage": "pnpm test --cov=app --cov-report=term-missing", "postinstall": "bash -e -c 'test -d .venv || python3 -m venv .venv; .venv/bin/python -m pip install -e \".[dev]\"'" } } diff --git a/apps/api/pyproject.toml b/apps/api/pyproject.toml index 6539301..6e3ad71 100644 --- a/apps/api/pyproject.toml +++ b/apps/api/pyproject.toml @@ -31,7 +31,7 @@ exclude = ["**/app/**/*_test.py"] testpaths = ["app"] pythonpath = ["."] python_files = ["*_test.py"] -addopts = "-q --cov=app --cov-report=term-missing" +addopts = "-q" [tool.coverage.run] relative_files = true diff --git a/apps/web/.gitignore b/apps/web/.gitignore index a547bf3..785a308 100644 --- a/apps/web/.gitignore +++ b/apps/web/.gitignore @@ -10,6 +10,7 @@ lerna-debug.log* node_modules dist dist-ssr +coverage *.local # Editor directories and files diff --git a/apps/web/knip.json b/apps/web/knip.json new file mode 100644 index 0000000..3d30f0c --- /dev/null +++ b/apps/web/knip.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://unpkg.com/knip@5/schema.json", + "entry": ["src/index.tsx"], + "project": ["src/**/*.{ts,tsx}"], + "ignore": [ + "src/api/generated/**", + "**/*.test.{ts,tsx}", + "src/components/ui/**", + "src/api/index.ts" + ], + "ignoreDependencies": ["tailwindcss", "tailwindcss-animate"] +} diff --git a/apps/web/package.json b/apps/web/package.json index 89a1c1d..617f160 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -10,7 +10,9 @@ "lint": "biome check . && node scripts/assert-no-function-declarations.mjs", "lint:fix": "biome check --write .", "test": "vitest run", + "test:coverage": "vitest run --coverage", "test:watch": "vitest", + "knip": "knip", "openapi:generate": "openapi-ts -f openapi-ts.config.ts", "openapi:validate": "pnpm --filter @solid-pact/openapi run lint" }, @@ -28,7 +30,10 @@ "@solidjs/testing-library": "0.8.10", "@tailwindcss/vite": "4.2.2", "@types/node": "24.12.0", + "@vitest/coverage-v8": "4.1.2", "jsdom": "29.0.1", + "knip": "5.80.1", + "msw": "2.12.7", "tailwindcss": "4.2.2", "tailwindcss-animate": "1.0.7", "typescript": "5.9.3", diff --git a/apps/web/scripts/assert-no-function-declarations.mjs b/apps/web/scripts/assert-no-function-declarations.mjs index 30b042a..20aba32 100644 --- a/apps/web/scripts/assert-no-function-declarations.mjs +++ b/apps/web/scripts/assert-no-function-declarations.mjs @@ -8,9 +8,9 @@ import fs from 'node:fs'; import path from 'node:path'; const rootDir = path.join(import.meta.dirname, '..'); -/** Top-level / named `function` declarations (not `typeof x === 'function'`). */ +/** Top-level / named `function` declarations (not `typeof x === 'function'` or `functions:`). */ const declarationLine = - /^\s*(?:export\s+(?:default\s+)?(?:async\s+)?|async\s+)?function\s*\*?\s*(?:[$\w]|\()/; + /^\s*(?:export\s+(?:default\s+)?(?:async\s+)?|async\s+)?\bfunction\b\s*\*?\s*(?:[$\w]|\()/; function walkTsFiles(dir, out) { for (const ent of fs.readdirSync(dir, { withFileTypes: true })) { diff --git a/apps/web/src/App.test.tsx b/apps/web/src/App.test.tsx index 097142b..3baa80e 100644 --- a/apps/web/src/App.test.tsx +++ b/apps/web/src/App.test.tsx @@ -1,15 +1,24 @@ -import { render, screen } from '@solidjs/testing-library'; -import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@solidjs/testing-library'; +import { HttpResponse, http } from 'msw'; +import { describe, expect, it } from 'vitest'; +import type { RecipeDetail, RecipeSummary } from '@/api'; +import { API_BASE } from '@/test/msw/constants'; +import { server } from '@/test/msw/server'; import { App } from './App'; -vi.mock('@/api', () => ({ - listRecipes: vi.fn().mockResolvedValue({ - data: [], - error: undefined, - request: new Request('http://127.0.0.1:8000/recipes'), - response: new Response(), - }), -})); +const listItem: RecipeSummary = { + id: 'nav-loaf', + title: 'Navigation loaf', + summary: 'For routing test', + imageUrl: 'https://example.com/t.jpg', +}; + +const detail: RecipeDetail = { + ...listItem, + imageUrlLarge: 'https://example.com/l.jpg', + ingredients: ['flour'], + steps: ['bake'], +}; describe('App', () => { it('renders the main heading', () => { @@ -17,4 +26,22 @@ describe('App', () => { const heading = screen.getByRole('heading', { level: 1 }); expect(heading.textContent).toBe('Bread Recipes'); }); + + it('navigates from the home list to a recipe detail route', async () => { + server.use( + http.get(`${API_BASE}/recipes`, () => HttpResponse.json([listItem])), + http.get(`${API_BASE}/recipes/:recipeId`, ({ params }) => { + if (params.recipeId !== 'nav-loaf') { + return HttpResponse.json({ message: 'Not found' }, { status: 404 }); + } + return HttpResponse.json(detail); + }), + ); + render(() => ); + const link = await screen.findByRole('link', { name: /Navigation loaf/i }); + fireEvent.click(link); + expect( + await screen.findByRole('heading', { level: 2, name: 'Navigation loaf' }), + ).toBeTruthy(); + }); }); diff --git a/apps/web/src/components/recipe-detail/RecipeDetailPanel.tsx b/apps/web/src/components/recipe-detail/RecipeDetailPanel.tsx index bb6e17e..a797d49 100644 --- a/apps/web/src/components/recipe-detail/RecipeDetailPanel.tsx +++ b/apps/web/src/components/recipe-detail/RecipeDetailPanel.tsx @@ -4,7 +4,7 @@ import { Card, CardContent, CardHeader } from '@/components/ui/card'; import { Heading3Panel } from '@/components/ui/typography'; import { cn } from '@/lib/utils'; -export type RecipeDetailPanelProps = ComponentProps<'section'> & { +type RecipeDetailPanelProps = ComponentProps<'section'> & { headingId: string; heading: string; children: JSX.Element; diff --git a/apps/web/src/lib/format-fetch-error.test.ts b/apps/web/src/lib/format-fetch-error.test.ts new file mode 100644 index 0000000..6afa546 --- /dev/null +++ b/apps/web/src/lib/format-fetch-error.test.ts @@ -0,0 +1,23 @@ +import { describe, expect, it } from 'vitest'; +import { formatFetchError } from './format-fetch-error'; + +describe('formatFetchError', () => { + it('returns the message of a plain Error', () => { + expect(formatFetchError(new Error('oops'))).toBe('oops'); + }); + + it('unwraps Error.cause recursively', () => { + const inner = new Error('inner'); + const outer = new Error('Unknown error', { cause: inner }); + expect(formatFetchError(outer)).toBe('inner'); + }); + + it('reads message from a plain object with message', () => { + expect(formatFetchError({ message: 'from body' })).toBe('from body'); + }); + + it('stringifies other values', () => { + expect(formatFetchError(null)).toBe('null'); + expect(formatFetchError(42)).toBe('42'); + }); +}); diff --git a/apps/web/src/lib/format-fetch-error.ts b/apps/web/src/lib/format-fetch-error.ts new file mode 100644 index 0000000..5d78bb4 --- /dev/null +++ b/apps/web/src/lib/format-fetch-error.ts @@ -0,0 +1,21 @@ +/** + * Format errors for UI. Solid's `createResource` wraps non-`Error` rejections in + * `Error("Unknown error", { cause })` — unwrap `cause` for API `{ message }` bodies. + */ +export const formatFetchError = (err: unknown): string => { + if (err instanceof Error) { + if (err.cause !== undefined) { + return formatFetchError(err.cause); + } + return err.message; + } + if ( + typeof err === 'object' && + err !== null && + 'message' in err && + typeof (err as { message: unknown }).message === 'string' + ) { + return (err as { message: string }).message; + } + return String(err); +}; diff --git a/apps/web/src/pages/Home.test.tsx b/apps/web/src/pages/Home.test.tsx index 34279b9..d4a796c 100644 --- a/apps/web/src/pages/Home.test.tsx +++ b/apps/web/src/pages/Home.test.tsx @@ -1,8 +1,10 @@ import { MemoryRouter, Route } from '@solidjs/router'; import { render, screen } from '@solidjs/testing-library'; -import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { HttpResponse, http } from 'msw'; +import { describe, expect, it } from 'vitest'; import type { RecipeSummary } from '@/api'; -import { listRecipes } from '@/api'; +import { API_BASE } from '@/test/msw/constants'; +import { server } from '@/test/msw/server'; import { Home } from './Home'; const renderHome = (): ReturnType => @@ -12,49 +14,45 @@ const renderHome = (): ReturnType => )); -vi.mock('@/api', async (importOriginal) => { - const mod = await importOriginal(); - return { - ...mod, - listRecipes: vi.fn(), - }; -}); - -const listOk = ( - data: RecipeSummary[], -): { - data: RecipeSummary[]; - error: undefined; - request: Request; - response: Response; -} => ({ - data, - error: undefined, - request: new Request('http://127.0.0.1:8000/recipes'), - response: new Response(), -}); - describe('Home', () => { - beforeEach(() => { - vi.mocked(listRecipes).mockReset(); + it('shows a loading state while recipes are fetched', async () => { + const gate = Promise.withResolvers(); + server.use( + http.get(`${API_BASE}/recipes`, async () => { + await gate.promise; + return HttpResponse.json([]); + }), + ); + renderHome(); + expect(await screen.findByText('Loading recipes…')).toBeTruthy(); + gate.resolve(); + expect(await screen.findByText(/No recipes to show yet/i)).toBeTruthy(); + }); + + it('treats a null API payload as an empty recipe list', async () => { + server.use(http.get(`${API_BASE}/recipes`, () => HttpResponse.json(null))); + renderHome(); + expect(await screen.findByText(/No recipes to show yet/i)).toBeTruthy(); }); it('shows empty state when the API returns no recipes', async () => { - vi.mocked(listRecipes).mockResolvedValue(listOk([])); + server.use(http.get(`${API_BASE}/recipes`, () => HttpResponse.json([]))); renderHome(); expect(await screen.findByText(/No recipes to show yet/i)).toBeTruthy(); }); it('renders linked recipe cards when the API returns recipes', async () => { - vi.mocked(listRecipes).mockResolvedValue( - listOk([ - { - id: 'sourdough-1', - title: 'Seeded sourdough', - summary: 'Overnight ferment', - imageUrl: 'https://example.com/thumb.jpg', - }, - ]), + server.use( + http.get(`${API_BASE}/recipes`, () => + HttpResponse.json([ + { + id: 'sourdough-1', + title: 'Seeded sourdough', + summary: 'Overnight ferment', + imageUrl: 'https://example.com/thumb.jpg', + }, + ]), + ), ); renderHome(); expect(await screen.findByText('Seeded sourdough')).toBeTruthy(); @@ -62,8 +60,12 @@ describe('Home', () => { expect(link.getAttribute('href')).toBe('/recipes/sourdough-1'); }); - it('shows an alert when the loader throws', async () => { - vi.mocked(listRecipes).mockRejectedValue(new Error('Bad gateway')); + it('shows an alert when the API returns an error', async () => { + server.use( + http.get(`${API_BASE}/recipes`, () => + HttpResponse.json({ message: 'Bad gateway' }, { status: 502 }), + ), + ); renderHome(); const alert = await screen.findByRole('alert'); expect(alert.textContent).toContain('Bad gateway'); diff --git a/apps/web/src/pages/Home.tsx b/apps/web/src/pages/Home.tsx index e53baf4..8dffc70 100644 --- a/apps/web/src/pages/Home.tsx +++ b/apps/web/src/pages/Home.tsx @@ -8,6 +8,7 @@ import { Alert, AlertDescription } from '@/components/ui/alert'; import { LoadingRegion } from '@/components/ui/loading-region'; import { Skeleton } from '@/components/ui/skeleton'; import { Heading2, TextLede, TextMuted } from '@/components/ui/typography'; +import { formatFetchError } from '@/lib/format-fetch-error'; export const Home = (): JSX.Element => { const [recipes] = createResource(() => @@ -35,9 +36,7 @@ export const Home = (): JSX.Element => { {(err: unknown) => ( - - {err instanceof Error ? err.message : String(err)} - + {formatFetchError(err)} )} diff --git a/apps/web/src/pages/RecipePage.missing-id.test.tsx b/apps/web/src/pages/RecipePage.missing-id.test.tsx new file mode 100644 index 0000000..bc948fd --- /dev/null +++ b/apps/web/src/pages/RecipePage.missing-id.test.tsx @@ -0,0 +1,25 @@ +import { MemoryRouter, Route } from '@solidjs/router'; +import { render, screen } from '@solidjs/testing-library'; +import { describe, expect, it, vi } from 'vitest'; +import { RecipePage } from './RecipePage'; + +vi.mock('@solidjs/router', async (importOriginal) => { + const mod = await importOriginal(); + return { + ...mod, + /** Solid skips the fetcher when the source is `undefined`; an empty id still runs it. */ + useParams: () => ({ id: '' }), + }; +}); + +describe('RecipePage (missing id)', () => { + it('shows an error when the route param id is empty', async () => { + render(() => ( + + + + )); + const alert = await screen.findByRole('alert'); + expect(alert.textContent).toContain('Missing recipe id'); + }); +}); diff --git a/apps/web/src/pages/RecipePage.test.tsx b/apps/web/src/pages/RecipePage.test.tsx index 15e976f..d9754f0 100644 --- a/apps/web/src/pages/RecipePage.test.tsx +++ b/apps/web/src/pages/RecipePage.test.tsx @@ -1,8 +1,10 @@ import { createMemoryHistory, MemoryRouter, Route } from '@solidjs/router'; import { render, screen } from '@solidjs/testing-library'; -import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { HttpResponse, http } from 'msw'; +import { describe, expect, it } from 'vitest'; import type { RecipeDetail } from '@/api'; -import { getRecipeById } from '@/api'; +import { API_BASE } from '@/test/msw/constants'; +import { server } from '@/test/msw/server'; import { RecipePage } from './RecipePage'; const recipeDetail: RecipeDetail = { @@ -15,20 +17,6 @@ const recipeDetail: RecipeDetail = { steps: ['Mix and bake'], }; -const detailOk = ( - data: RecipeDetail, -): { - data: RecipeDetail; - error: undefined; - request: Request; - response: Response; -} => ({ - data, - error: undefined, - request: new Request(`http://127.0.0.1:8000/recipes/${data.id}`), - response: new Response(), -}); - const renderRecipePage = (): ReturnType => { const history = createMemoryHistory(); history.set({ @@ -43,21 +31,32 @@ const renderRecipePage = (): ReturnType => { )); }; -vi.mock('@/api', async (importOriginal) => { - const mod = await importOriginal(); - return { - ...mod, - getRecipeById: vi.fn(), - }; -}); - describe('RecipePage', () => { - beforeEach(() => { - vi.mocked(getRecipeById).mockReset(); + it('shows a loading state while the recipe is fetched', async () => { + const gate = Promise.withResolvers(); + server.use( + http.get(`${API_BASE}/recipes/:recipeId`, async () => { + await gate.promise; + return HttpResponse.json(recipeDetail); + }), + ); + renderRecipePage(); + expect(await screen.findByText('Loading recipe…')).toBeTruthy(); + gate.resolve(); + expect( + await screen.findByRole('heading', { level: 2, name: 'Test loaf' }), + ).toBeTruthy(); }); it('renders the recipe heading when the API returns detail', async () => { - vi.mocked(getRecipeById).mockResolvedValue(detailOk(recipeDetail)); + server.use( + http.get(`${API_BASE}/recipes/:recipeId`, ({ params }) => { + if (params.recipeId !== 'loaf-1') { + return HttpResponse.json({ message: 'Not found' }, { status: 404 }); + } + return HttpResponse.json(recipeDetail); + }), + ); renderRecipePage(); expect( await screen.findByRole('heading', { level: 2, name: 'Test loaf' }), @@ -65,9 +64,27 @@ describe('RecipePage', () => { }); it('shows an alert when the API fails', async () => { - vi.mocked(getRecipeById).mockRejectedValue(new Error('Not found')); + server.use( + http.get(`${API_BASE}/recipes/:recipeId`, () => + HttpResponse.json({ message: 'Not found' }, { status: 404 }), + ), + ); renderRecipePage(); const alert = await screen.findByRole('alert'); expect(alert.textContent).toContain('Not found'); }); + + it('keeps the page shell when the API returns no recipe payload', async () => { + server.use( + http.get(`${API_BASE}/recipes/:recipeId`, () => HttpResponse.json(null)), + ); + renderRecipePage(); + expect( + await screen.findByRole('link', { name: /all recipes/i }), + ).toBeTruthy(); + expect( + screen.queryByRole('heading', { level: 2, name: 'Test loaf' }), + ).toBeNull(); + expect(screen.queryByRole('alert')).toBeNull(); + }); }); diff --git a/apps/web/src/pages/RecipePage.tsx b/apps/web/src/pages/RecipePage.tsx index 3c312f6..90138b8 100644 --- a/apps/web/src/pages/RecipePage.tsx +++ b/apps/web/src/pages/RecipePage.tsx @@ -8,6 +8,7 @@ import { RecipeDetailBody } from '@/components/recipe-detail/RecipeDetailBody'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { LoadingRegion } from '@/components/ui/loading-region'; import { Skeleton } from '@/components/ui/skeleton'; +import { formatFetchError } from '@/lib/format-fetch-error'; export const RecipePage = (): JSX.Element => { const params = useParams<{ id: string }>(); @@ -40,9 +41,7 @@ export const RecipePage = (): JSX.Element => { {(err: unknown) => ( - - {err instanceof Error ? err.message : String(err)} - + {formatFetchError(err)} )} diff --git a/apps/web/src/test/msw/constants.ts b/apps/web/src/test/msw/constants.ts new file mode 100644 index 0000000..9c150d5 --- /dev/null +++ b/apps/web/src/test/msw/constants.ts @@ -0,0 +1,2 @@ +/** Must match test env `VITE_API_BASE_URL` and MSW handlers. */ +export const API_BASE = 'http://127.0.0.1:8000'; diff --git a/apps/web/src/test/msw/handlers.ts b/apps/web/src/test/msw/handlers.ts new file mode 100644 index 0000000..3b4aaaf --- /dev/null +++ b/apps/web/src/test/msw/handlers.ts @@ -0,0 +1,11 @@ +import type { RequestHandler } from 'msw'; +import { HttpResponse, http } from 'msw'; +import { API_BASE } from './constants'; + +/** Defaults: empty recipe list and 404 recipe detail; override per test with `server.use(...)`. */ +export const handlers: RequestHandler[] = [ + http.get(`${API_BASE}/recipes`, () => HttpResponse.json([])), + http.get(`${API_BASE}/recipes/:recipeId`, () => + HttpResponse.json({ message: 'Not found' }, { status: 404 }), + ), +]; diff --git a/apps/web/src/test/msw/server.ts b/apps/web/src/test/msw/server.ts new file mode 100644 index 0000000..816c448 --- /dev/null +++ b/apps/web/src/test/msw/server.ts @@ -0,0 +1,4 @@ +import { type SetupServerApi, setupServer } from 'msw/node'; +import { handlers } from '@/test/msw/handlers'; + +export const server: SetupServerApi = setupServer(...handlers); diff --git a/apps/web/src/test/vitest-setup.ts b/apps/web/src/test/vitest-setup.ts new file mode 100644 index 0000000..e1bcb5d --- /dev/null +++ b/apps/web/src/test/vitest-setup.ts @@ -0,0 +1,14 @@ +import { afterAll, afterEach, beforeAll } from 'vitest'; +import { server } from '@/test/msw/server'; + +beforeAll(() => { + server.listen({ onUnhandledRequest: 'error' }); +}); + +afterEach(() => { + server.resetHandlers(); +}); + +afterAll(() => { + server.close(); +}); diff --git a/apps/web/tsconfig.app.json b/apps/web/tsconfig.app.json index 2b089a2..35df4a7 100644 --- a/apps/web/tsconfig.app.json +++ b/apps/web/tsconfig.app.json @@ -1,10 +1,10 @@ { "compilerOptions": { "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", - "target": "ES2023", + "target": "ES2024", "useDefineForClassFields": true, "module": "ESNext", - "lib": ["ES2023", "DOM", "DOM.Iterable"], + "lib": ["ES2024", "DOM", "DOM.Iterable"], "types": ["vite/client", "vitest/globals"], "skipLibCheck": true, diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts index a0d36d0..dacbd11 100644 --- a/apps/web/vite.config.ts +++ b/apps/web/vite.config.ts @@ -19,6 +19,32 @@ export default defineConfig({ globals: true, include: ['src/**/*.{test,spec}.{ts,tsx}'], // See src/test/vitest-no-jest-dom.ts — prevents vite-plugin-solid from injecting jest-dom. - setupFiles: ['src/test/vitest-no-jest-dom.ts'], + setupFiles: ['src/test/vitest-no-jest-dom.ts', 'src/test/vitest-setup.ts'], + env: { + VITE_API_BASE_URL: 'http://127.0.0.1:8000', + }, + coverage: { + provider: 'v8', + reporter: ['text', 'json-summary'], + include: ['src/**/*.{ts,tsx}'], + exclude: [ + 'src/**/*.test.{ts,tsx}', + 'src/api/generated/**', + 'src/api/client.ts', + 'src/components/ui/**', + 'src/vite-env.d.ts', + 'src/test/**', + 'src/index.tsx', + ], + // Line/function/statement gates match the project requirement for full coverage. Branch + // probes on Solid/JSX trees are noisy in v8 (often ~50% per node); omitting branch thresholds + // avoids a misleading CI failure while keeping strict line coverage. + // See https://github.com/solidjs/solid/issues/2138 + thresholds: { + lines: 100, + functions: 100, + statements: 100, + }, + }, }, }); diff --git a/package.json b/package.json index b57232c..932a72d 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,9 @@ "lint:fix": "turbo run lint:fix", "openapi:generate": "turbo run openapi:generate", "openapi:validate": "turbo run openapi:validate", - "test": "turbo run test" + "test": "turbo run test", + "test:coverage": "turbo run test:coverage", + "knip": "turbo run knip" }, "devDependencies": { "turbo": "2.5.4" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f78da9d..1ab0754 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,7 +40,7 @@ importers: version: 2.4.10 '@hey-api/openapi-ts': specifier: 0.95.0 - version: 0.95.0(typescript@5.9.3) + version: 0.95.0(magicast@0.5.2)(typescript@5.9.3) '@solidjs/testing-library': specifier: 0.8.10 version: 0.8.10(@solidjs/router@0.16.1(solid-js@1.9.12))(solid-js@1.9.12) @@ -50,9 +50,18 @@ importers: '@types/node': specifier: 24.12.0 version: 24.12.0 + '@vitest/coverage-v8': + specifier: 4.1.2 + version: 4.1.2(vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(jsdom@29.0.1)(msw@2.12.7(@types/node@24.12.0)(typescript@5.9.3))(vite@8.0.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(jiti@2.6.1)(yaml@2.8.3))) jsdom: specifier: 29.0.1 version: 29.0.1 + knip: + specifier: 5.80.1 + version: 5.80.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(typescript@5.9.3) + msw: + specifier: 2.12.7 + version: 2.12.7(@types/node@24.12.0)(typescript@5.9.3) tailwindcss: specifier: 4.2.2 version: 4.2.2 @@ -70,7 +79,7 @@ importers: version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.12)(vite@8.0.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(jiti@2.6.1)(yaml@2.8.3)) vitest: specifier: 4.1.2 - version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(jsdom@29.0.1)(vite@8.0.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(jiti@2.6.1)(yaml@2.8.3)) + version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(jsdom@29.0.1)(msw@2.12.7(@types/node@24.12.0)(typescript@5.9.3))(vite@8.0.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(jiti@2.6.1)(yaml@2.8.3)) packages/openapi: devDependencies: @@ -185,6 +194,10 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} + '@biomejs/biome@2.4.10': resolution: {integrity: sha512-xxA3AphFQ1geij4JTHXv4EeSTda1IFn22ye9LdyVPoJU19fNVl0uzfEuhsfQ4Yue/0FaLs2/ccVi4UDiE7R30w==} engines: {node: '>=14.21.3'} @@ -350,6 +363,41 @@ packages: '@hey-api/types@0.1.4': resolution: {integrity: sha512-thWfawrDIP7wSI9ioT13I5soaaqB5vAPIiZmgD8PbeEVKNrkonc0N/Sjj97ezl7oQgusZmaNphGdMKipPO6IBg==} + '@inquirer/ansi@1.0.2': + resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} + engines: {node: '>=18'} + + '@inquirer/confirm@5.1.21': + resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/core@10.3.2': + resolution: {integrity: sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/figures@1.0.15': + resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} + engines: {node: '>=18'} + + '@inquirer/type@3.0.10': + resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + '@internationalized/date@3.12.0': resolution: {integrity: sha512-/PyIMzK29jtXaGU23qTvNZxvBXRtKbNnGDFD+PY6CZw/Y8Ex8pFUzkuCJCG9aOqmShjqhS9mPqP6Dk5onQY8rQ==} @@ -385,12 +433,37 @@ packages: peerDependencies: solid-js: ^1.8.8 + '@mswjs/interceptors@0.40.0': + resolution: {integrity: sha512-EFd6cVbHsgLa6wa4RljGj6Wk75qoHxUSyc5asLyyPSyuhIcdS2Q3Phw6ImS1q+CkALthJRShiYfKANcQMuMqsQ==} + engines: {node: '>=18'} + '@napi-rs/wasm-runtime@1.1.2': resolution: {integrity: sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==} peerDependencies: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@open-draft/deferred-promise@2.2.0': + resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} + + '@open-draft/logger@0.3.0': + resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==} + + '@open-draft/until@2.1.0': + resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} + '@opentelemetry/api-logs@0.53.0': resolution: {integrity: sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==} engines: {node: '>=14'} @@ -478,6 +551,106 @@ packages: '@oxc-project/types@0.122.0': resolution: {integrity: sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==} + '@oxc-resolver/binding-android-arm-eabi@11.19.1': + resolution: {integrity: sha512-aUs47y+xyXHUKlbhqHUjBABjvycq6YSD7bpxSW7vplUmdzAlJ93yXY6ZR0c1o1x5A/QKbENCvs3+NlY8IpIVzg==} + cpu: [arm] + os: [android] + + '@oxc-resolver/binding-android-arm64@11.19.1': + resolution: {integrity: sha512-oolbkRX+m7Pq2LNjr/kKgYeC7bRDMVTWPgxBGMjSpZi/+UskVo4jsMU3MLheZV55jL6c3rNelPl4oD60ggYmqA==} + cpu: [arm64] + os: [android] + + '@oxc-resolver/binding-darwin-arm64@11.19.1': + resolution: {integrity: sha512-nUC6d2i3R5B12sUW4O646qD5cnMXf2oBGPLIIeaRfU9doJRORAbE2SGv4eW6rMqhD+G7nf2Y8TTJTLiiO3Q/dQ==} + cpu: [arm64] + os: [darwin] + + '@oxc-resolver/binding-darwin-x64@11.19.1': + resolution: {integrity: sha512-cV50vE5+uAgNcFa3QY1JOeKDSkM/9ReIcc/9wn4TavhW/itkDGrXhw9jaKnkQnGbjJ198Yh5nbX/Gr2mr4Z5jQ==} + cpu: [x64] + os: [darwin] + + '@oxc-resolver/binding-freebsd-x64@11.19.1': + resolution: {integrity: sha512-xZOQiYGFxtk48PBKff+Zwoym7ScPAIVp4c14lfLxizO2LTTTJe5sx9vQNGrBymrf/vatSPNMD4FgsaaRigPkqw==} + cpu: [x64] + os: [freebsd] + + '@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1': + resolution: {integrity: sha512-lXZYWAC6kaGe/ky2su94e9jN9t6M0/6c+GrSlCqL//XO1cxi5lpAhnJYdyrKfm0ZEr/c7RNyAx3P7FSBcBd5+A==} + cpu: [arm] + os: [linux] + + '@oxc-resolver/binding-linux-arm-musleabihf@11.19.1': + resolution: {integrity: sha512-veG1kKsuK5+t2IsO9q0DErYVSw2azvCVvWHnfTOS73WE0STdLLB7Q1bB9WR+yHPQM76ASkFyRbogWo1GR1+WbQ==} + cpu: [arm] + os: [linux] + + '@oxc-resolver/binding-linux-arm64-gnu@11.19.1': + resolution: {integrity: sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig==} + cpu: [arm64] + os: [linux] + + '@oxc-resolver/binding-linux-arm64-musl@11.19.1': + resolution: {integrity: sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew==} + cpu: [arm64] + os: [linux] + + '@oxc-resolver/binding-linux-ppc64-gnu@11.19.1': + resolution: {integrity: sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ==} + cpu: [ppc64] + os: [linux] + + '@oxc-resolver/binding-linux-riscv64-gnu@11.19.1': + resolution: {integrity: sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w==} + cpu: [riscv64] + os: [linux] + + '@oxc-resolver/binding-linux-riscv64-musl@11.19.1': + resolution: {integrity: sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw==} + cpu: [riscv64] + os: [linux] + + '@oxc-resolver/binding-linux-s390x-gnu@11.19.1': + resolution: {integrity: sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA==} + cpu: [s390x] + os: [linux] + + '@oxc-resolver/binding-linux-x64-gnu@11.19.1': + resolution: {integrity: sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ==} + cpu: [x64] + os: [linux] + + '@oxc-resolver/binding-linux-x64-musl@11.19.1': + resolution: {integrity: sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw==} + cpu: [x64] + os: [linux] + + '@oxc-resolver/binding-openharmony-arm64@11.19.1': + resolution: {integrity: sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA==} + cpu: [arm64] + os: [openharmony] + + '@oxc-resolver/binding-wasm32-wasi@11.19.1': + resolution: {integrity: sha512-w8UCKhX826cP/ZLokXDS6+milN8y4X7zidsAttEdWlVoamTNf6lhBJldaWr3ukTDiye7s4HRcuPEPOXNC432Vg==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@oxc-resolver/binding-win32-arm64-msvc@11.19.1': + resolution: {integrity: sha512-nJ4AsUVZrVKwnU/QRdzPCCrO0TrabBqgJ8pJhXITdZGYOV28TIYystV1VFLbQ7DtAcaBHpocT5/ZJnF78YJPtQ==} + cpu: [arm64] + os: [win32] + + '@oxc-resolver/binding-win32-ia32-msvc@11.19.1': + resolution: {integrity: sha512-EW+ND5q2Tl+a3pH81l1QbfgbF3HmqgwLfDfVithRFheac8OTcnbXt/JxqD2GbDkb7xYEqy1zNaVFRr3oeG8npA==} + cpu: [ia32] + os: [win32] + + '@oxc-resolver/binding-win32-x64-msvc@11.19.1': + resolution: {integrity: sha512-6hIU3RQu45B+VNTY4Ru8ppFwjVS/S5qwYyGhBotmjxfEKk41I2DlGtRfGJndZ5+6lneE2pwloqunlOyZuX/XAw==} + cpu: [x64] + os: [win32] + '@protobufjs/aspromise@1.1.2': resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} @@ -822,12 +995,24 @@ packages: '@types/node@24.12.0': resolution: {integrity: sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==} + '@types/statuses@2.0.6': + resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==} + '@types/stylis@4.2.7': resolution: {integrity: sha512-VgDNokpBoKF+wrdvhAAfS55OMQpL6QRglwTwNC3kIgBrzZxA4WsFj+2eLfEA/uMUDzBcEhYmjSbwQakn/i3ajA==} '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@vitest/coverage-v8@4.1.2': + resolution: {integrity: sha512-sPK//PHO+kAkScb8XITeB1bf7fsk85Km7+rt4eeuRR3VS1/crD47cmV5wicisJmjNdfeokTZwjMk4Mj2d58Mgg==} + peerDependencies: + '@vitest/browser': 4.1.2 + vitest: 4.1.2 + peerDependenciesMeta: + '@vitest/browser': + optional: true + '@vitest/expect@4.1.2': resolution: {integrity: sha512-gbu+7B0YgUJ2nkdsRJrFFW6X7NTP44WlhiclHniUhxADQJH5Szt9mZ9hWnJPJ8YwOK5zUOSSlSvyzRf0u1DSBQ==} @@ -895,6 +1080,9 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-v8-to-istanbul@1.0.0: + resolution: {integrity: sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -991,9 +1179,17 @@ packages: classnames@2.5.1: resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + cliui@7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -1033,6 +1229,10 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + core-js@3.49.0: resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==} @@ -1192,6 +1392,10 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} @@ -1205,6 +1409,12 @@ packages: resolution: {integrity: sha512-jldvxr1MC6rtiZKgrFnDSvT8xuH+eJqxqOBThUVjYrxssYTo1avZLGql5l0a0BAERR01CadYzZ83kVEkbyDg+g==} hasBin: true + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fd-package-json@2.0.0: + resolution: {integrity: sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==} + fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -1225,6 +1435,11 @@ packages: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} + formatly@0.3.0: + resolution: {integrity: sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==} + engines: {node: '>=18.3.0'} + hasBin: true + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -1277,11 +1492,19 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + graphql@16.13.2: + resolution: {integrity: sha512-5bJ+nf/UCpAjHM8i06fl7eLyVC9iuNAjm9qzkiu2ZGhM0VscSvS6WDPfAwkdkBuoXGM9FJSbKl6wylMwP9Ktig==} + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + handlebars@4.7.9: resolution: {integrity: sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==} engines: {node: '>=0.4.7'} hasBin: true + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + has-symbols@1.1.0: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} @@ -1294,6 +1517,9 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + headers-polyfill@4.0.3: + resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==} + html-encoding-sniffer@6.0.0: resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -1301,6 +1527,9 @@ packages: html-entities@2.3.3: resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + http2-client@1.3.5: resolution: {integrity: sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==} @@ -1349,6 +1578,9 @@ packages: engines: {node: '>=14.16'} hasBin: true + is-node-process@1.2.0: + resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -1367,6 +1599,18 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-reports@3.2.0: + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} + engines: {node: '>=8'} + jiti@2.6.1: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true @@ -1375,6 +1619,9 @@ packages: resolution: {integrity: sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==} engines: {node: '>=0.10.0'} + js-tokens@10.0.0: + resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1407,6 +1654,14 @@ packages: engines: {node: '>=6'} hasBin: true + knip@5.80.1: + resolution: {integrity: sha512-aMqGxyoAgLzTd6g3bN7J+Mef0R/WqWKz4zazvKQisprPdszp7X/CHRAPVsVYIkUAIDWCiC/s65JOrva3DwR9yQ==} + engines: {node: '>=18.18.0'} + hasBin: true + peerDependencies: + '@types/node': '>=18' + typescript: '>=5.0.4 <7' + lightningcss-android-arm64@1.32.0: resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} engines: {node: '>= 12.0.0'} @@ -1501,6 +1756,13 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + magicast@0.5.2: + resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + mark.js@8.11.1: resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} @@ -1520,6 +1782,14 @@ packages: resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} engines: {node: '>=12.13'} + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -1574,6 +1844,20 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + msw@2.12.7: + resolution: {integrity: sha512-retd5i3xCZDVWMYjHEVuKTmhqY8lSsxujjVrZiGbbdoxxIBg5S7rCuYy/YQpfrTYIxpd/o0Kyb/3H+1udBMoYg==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + typescript: '>= 4.8.x' + peerDependenciesMeta: + typescript: + optional: true + + mute-stream@2.0.0: + resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} + engines: {node: ^18.17.0 || >=20.5.0} + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -1649,6 +1933,12 @@ packages: openapi-sampler@1.7.2: resolution: {integrity: sha512-OKytvqB5XIaTgA9xtw8W8UTar+uymW2xPVpFN0NihMtuHPdPTGxBEhGnfFnJW5g/gOSIvkP+H0Xh3XhVI9/n7g==} + outvariant@1.4.3: + resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} + + oxc-resolver@11.19.1: + resolution: {integrity: sha512-qE/CIg/spwrTBFt5aKmwe3ifeDdLfA2NESN30E42X/lII5ClF8V7Wt6WIJhcGZjp0/Q+nQ+9vgxGk//xZNX2hg==} + parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} @@ -1670,6 +1960,9 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-to-regexp@6.3.0: + resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -1804,6 +2097,13 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + rettime@0.7.0: + resolution: {integrity: sha512-LPRKoHnLKd/r3dVxcwO7vhCW+orkOGj9ViueosEBK6ie89CijnfRlhaDhHq/3Hxu4CkWQtxwlBG0mzTQY6uQjw==} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rolldown@1.0.0-rc.12: resolution: {integrity: sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1813,6 +2113,9 @@ packages: resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} engines: {node: '>=18'} + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -1879,6 +2182,10 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + simple-websocket@9.1.0: resolution: {integrity: sha512-8MJPnjRN6A8UCp1I+H/dSFyjwJhp6wta4hsVRhjf8w9qBHRzxYt14RaOcjvQnhD1N4yKOddEjflwMnQM4VtXjQ==} @@ -1886,6 +2193,10 @@ packages: resolution: {integrity: sha512-tf+h5W1IrjNm/9rKKj0JU2MDMruiopx0jjVA5zCdBtcGjfp0+c5rHw/zADLC3IeKlGHtVbHtpfzvYA0OYT+HKg==} engines: {node: '>=8.0.0'} + smol-toml@1.6.1: + resolution: {integrity: sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==} + engines: {node: '>= 18'} + solid-js@1.9.12: resolution: {integrity: sha512-QzKaSJq2/iDrWR1As6MHZQ8fQkdOBf8GReYb7L5iKwMGceg7HxDcaOHk0at66tNgn9U2U7dXo8ZZpLIAmGMzgw==} @@ -1915,12 +2226,19 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + std-env@4.0.0: resolution: {integrity: sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==} stickyfill@1.1.1: resolution: {integrity: sha512-GCp7vHAfpao+Qh/3Flh9DXEJ/qSi0KJwJw6zYlZOtRYXWUIpMM6mC2rIep/dK8RQqwW0KxGJIllmjPIBOGN8AA==} + strict-event-emitter@0.5.1: + resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -1936,6 +2254,10 @@ packages: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} + strip-json-comments@5.0.3: + resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} + engines: {node: '>=14.16'} + strnum@2.2.2: resolution: {integrity: sha512-DnR90I+jtXNSTXWdwrEy9FakW7UX+qUZg28gj5fk2vxxl7uS/3bpI4fjFYVmdK9etptYBPNkpahuQnEwhwECqA==} @@ -1952,6 +2274,10 @@ packages: stylis@4.3.6: resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + swagger2openapi@7.0.8: resolution: {integrity: sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==} hasBin: true @@ -1959,6 +2285,10 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + tagged-tag@1.0.0: + resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} + engines: {node: '>=20'} + tailwind-merge@3.5.0: resolution: {integrity: sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==} @@ -2048,6 +2378,10 @@ packages: resolution: {integrity: sha512-kc8ZibdRcuWUG1pbYSBFWqmIjynlD8Lp7IB6U3vIzvOv9VG+6Sp8bzyeBWE3Oi8XV5KsQrznyRTBPvrf99E4mA==} hasBin: true + type-fest@5.5.0: + resolution: {integrity: sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==} + engines: {node: '>=20'} + typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} @@ -2065,6 +2399,9 @@ packages: resolution: {integrity: sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ==} engines: {node: '>=20.18.1'} + until-async@3.0.2: + resolution: {integrity: sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==} + update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true @@ -2182,6 +2519,10 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} + walk-up-path@4.0.0: + resolution: {integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==} + engines: {node: 20 || >=22} + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -2213,6 +2554,10 @@ packages: wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -2266,10 +2611,25 @@ packages: resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} engines: {node: '>=10'} + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + yargs@17.0.1: resolution: {integrity: sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ==} engines: {node: '>=12'} + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yoctocolors-cjs@2.1.3: + resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} + engines: {node: '>=18'} + + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + snapshots: '@adobe/css-tools@4.4.4': @@ -2406,6 +2766,8 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@bcoe/v8-coverage@1.0.2': {} + '@biomejs/biome@2.4.10': optionalDependencies: '@biomejs/cli-darwin-arm64': 2.4.10 @@ -2515,11 +2877,11 @@ snapshots: '@floating-ui/utils@0.2.11': {} - '@hey-api/codegen-core@0.7.4': + '@hey-api/codegen-core@0.7.4(magicast@0.5.2)': dependencies: '@hey-api/types': 0.1.4 ansi-colors: 4.1.3 - c12: 3.3.3 + c12: 3.3.3(magicast@0.5.2) color-support: 1.1.3 transitivePeerDependencies: - magicast @@ -2530,11 +2892,11 @@ snapshots: '@types/json-schema': 7.0.15 js-yaml: 4.1.1 - '@hey-api/openapi-ts@0.95.0(typescript@5.9.3)': + '@hey-api/openapi-ts@0.95.0(magicast@0.5.2)(typescript@5.9.3)': dependencies: - '@hey-api/codegen-core': 0.7.4 + '@hey-api/codegen-core': 0.7.4(magicast@0.5.2) '@hey-api/json-schema-ref-parser': 1.3.1 - '@hey-api/shared': 0.3.0 + '@hey-api/shared': 0.3.0(magicast@0.5.2) '@hey-api/spec-types': 0.1.0 '@hey-api/types': 0.1.4 ansi-colors: 4.1.3 @@ -2545,9 +2907,9 @@ snapshots: transitivePeerDependencies: - magicast - '@hey-api/shared@0.3.0': + '@hey-api/shared@0.3.0(magicast@0.5.2)': dependencies: - '@hey-api/codegen-core': 0.7.4 + '@hey-api/codegen-core': 0.7.4(magicast@0.5.2) '@hey-api/json-schema-ref-parser': 1.3.1 '@hey-api/spec-types': 0.1.0 '@hey-api/types': 0.1.4 @@ -2564,6 +2926,34 @@ snapshots: '@hey-api/types@0.1.4': {} + '@inquirer/ansi@1.0.2': {} + + '@inquirer/confirm@5.1.21(@types/node@24.12.0)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@24.12.0) + '@inquirer/type': 3.0.10(@types/node@24.12.0) + optionalDependencies: + '@types/node': 24.12.0 + + '@inquirer/core@10.3.2(@types/node@24.12.0)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@24.12.0) + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 24.12.0 + + '@inquirer/figures@1.0.15': {} + + '@inquirer/type@3.0.10(@types/node@24.12.0)': + optionalDependencies: + '@types/node': 24.12.0 + '@internationalized/date@3.12.0': dependencies: '@swc/helpers': 0.5.21 @@ -2616,6 +3006,15 @@ snapshots: '@solid-primitives/utils': 6.4.0(solid-js@1.9.12) solid-js: 1.9.12 + '@mswjs/interceptors@0.40.0': + dependencies: + '@open-draft/deferred-promise': 2.2.0 + '@open-draft/logger': 0.3.0 + '@open-draft/until': 2.1.0 + is-node-process: 1.2.0 + outvariant: 1.4.3 + strict-event-emitter: 0.5.1 + '@napi-rs/wasm-runtime@1.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': dependencies: '@emnapi/core': 1.9.2 @@ -2623,6 +3022,27 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + + '@open-draft/deferred-promise@2.2.0': {} + + '@open-draft/logger@0.3.0': + dependencies: + is-node-process: 1.2.0 + outvariant: 1.4.3 + + '@open-draft/until@2.1.0': {} + '@opentelemetry/api-logs@0.53.0': dependencies: '@opentelemetry/api': 1.9.0 @@ -2714,6 +3134,71 @@ snapshots: '@oxc-project/types@0.122.0': {} + '@oxc-resolver/binding-android-arm-eabi@11.19.1': + optional: true + + '@oxc-resolver/binding-android-arm64@11.19.1': + optional: true + + '@oxc-resolver/binding-darwin-arm64@11.19.1': + optional: true + + '@oxc-resolver/binding-darwin-x64@11.19.1': + optional: true + + '@oxc-resolver/binding-freebsd-x64@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-arm-musleabihf@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-arm64-gnu@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-arm64-musl@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-ppc64-gnu@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-riscv64-gnu@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-riscv64-musl@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-s390x-gnu@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-x64-gnu@11.19.1': + optional: true + + '@oxc-resolver/binding-linux-x64-musl@11.19.1': + optional: true + + '@oxc-resolver/binding-openharmony-arm64@11.19.1': + optional: true + + '@oxc-resolver/binding-wasm32-wasi@11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': + dependencies: + '@napi-rs/wasm-runtime': 1.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + optional: true + + '@oxc-resolver/binding-win32-arm64-msvc@11.19.1': + optional: true + + '@oxc-resolver/binding-win32-ia32-msvc@11.19.1': + optional: true + + '@oxc-resolver/binding-win32-x64-msvc@11.19.1': + optional: true + '@protobufjs/aspromise@1.1.2': {} '@protobufjs/base64@1.1.2': {} @@ -3053,11 +3538,27 @@ snapshots: dependencies: undici-types: 7.16.0 + '@types/statuses@2.0.6': {} + '@types/stylis@4.2.7': {} '@types/trusted-types@2.0.7': optional: true + '@vitest/coverage-v8@4.1.2(vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(jsdom@29.0.1)(msw@2.12.7(@types/node@24.12.0)(typescript@5.9.3))(vite@8.0.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(jiti@2.6.1)(yaml@2.8.3)))': + dependencies: + '@bcoe/v8-coverage': 1.0.2 + '@vitest/utils': 4.1.2 + 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 + tinyrainbow: 3.1.0 + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(jsdom@29.0.1)(msw@2.12.7(@types/node@24.12.0)(typescript@5.9.3))(vite@8.0.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(jiti@2.6.1)(yaml@2.8.3)) + '@vitest/expect@4.1.2': dependencies: '@standard-schema/spec': 1.1.0 @@ -3067,12 +3568,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.2(vite@8.0.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(jiti@2.6.1)(yaml@2.8.3))': + '@vitest/mocker@4.1.2(msw@2.12.7(@types/node@24.12.0)(typescript@5.9.3))(vite@8.0.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(jiti@2.6.1)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.1.2 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: + msw: 2.12.7(@types/node@24.12.0)(typescript@5.9.3) vite: 8.0.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(jiti@2.6.1)(yaml@2.8.3) '@vitest/pretty-format@4.1.2': @@ -3128,6 +3630,12 @@ snapshots: assertion-error@2.0.1: {} + ast-v8-to-istanbul@1.0.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + estree-walker: 3.0.3 + js-tokens: 10.0.0 + asynckit@0.4.0: {} babel-plugin-jsx-dom-expressions@0.40.6(@babel/core@7.29.0): @@ -3181,7 +3689,7 @@ snapshots: dependencies: run-applescript: 7.1.0 - c12@3.3.3: + c12@3.3.3(magicast@0.5.2): dependencies: chokidar: 5.0.0 confbox: 0.2.4 @@ -3195,6 +3703,8 @@ snapshots: perfect-debounce: 2.1.0 pkg-types: 2.3.0 rc9: 2.1.2 + optionalDependencies: + magicast: 0.5.2 call-bind-apply-helpers@1.0.2: dependencies: @@ -3237,12 +3747,20 @@ snapshots: classnames@2.5.1: {} + cli-width@4.1.0: {} + cliui@7.0.4: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + clsx@2.1.1: {} color-convert@2.0.1: @@ -3269,6 +3787,8 @@ snapshots: convert-source-map@2.0.0: {} + cookie@1.1.1: {} + core-js@3.49.0: {} cross-env@10.1.0: @@ -3399,6 +3919,14 @@ snapshots: fast-deep-equal@3.1.3: {} + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + fast-safe-stringify@2.1.1: {} fast-uri@3.1.0: {} @@ -3413,6 +3941,14 @@ snapshots: path-expression-matcher: 1.2.0 strnum: 2.2.2 + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fd-package-json@2.0.0: + dependencies: + walk-up-path: 4.0.0 + fdir@6.5.0(picomatch@4.0.4): optionalDependencies: picomatch: 4.0.4 @@ -3431,6 +3967,10 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 + formatly@0.3.0: + dependencies: + fd-package-json: 2.0.0 + fs.realpath@1.0.0: {} fsevents@2.3.3: @@ -3492,6 +4032,8 @@ snapshots: graceful-fs@4.2.11: {} + graphql@16.13.2: {} + handlebars@4.7.9: dependencies: minimist: 1.2.8 @@ -3501,6 +4043,8 @@ snapshots: optionalDependencies: uglify-js: 3.19.3 + has-flag@4.0.0: {} + has-symbols@1.1.0: {} has-tostringtag@1.0.2: @@ -3511,6 +4055,8 @@ snapshots: dependencies: function-bind: 1.1.2 + headers-polyfill@4.0.3: {} + html-encoding-sniffer@6.0.0: dependencies: '@exodus/bytes': 1.15.0 @@ -3519,6 +4065,8 @@ snapshots: html-entities@2.3.3: {} + html-escaper@2.0.2: {} + http2-client@1.3.5: {} https-proxy-agent@7.0.6: @@ -3558,6 +4106,8 @@ snapshots: dependencies: is-docker: 3.0.0 + is-node-process@1.2.0: {} + is-number@7.0.0: {} is-potential-custom-element-name@1.0.1: {} @@ -3570,10 +4120,25 @@ snapshots: isexe@2.0.0: {} + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-reports@3.2.0: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + jiti@2.6.1: {} js-levenshtein@1.1.6: {} + js-tokens@10.0.0: {} + js-tokens@4.0.0: {} js-yaml@4.1.1: @@ -3616,6 +4181,26 @@ snapshots: json5@2.2.3: {} + knip@5.80.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(typescript@5.9.3): + dependencies: + '@nodelib/fs.walk': 1.2.8 + '@types/node': 24.12.0 + fast-glob: 3.3.3 + formatly: 0.3.0 + jiti: 2.6.1 + js-yaml: 4.1.1 + minimist: 1.2.8 + oxc-resolver: 11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + picocolors: 1.1.1 + picomatch: 4.0.4 + smol-toml: 1.6.1 + strip-json-comments: 5.0.3 + typescript: 5.9.3 + zod: 4.3.6 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + lightningcss-android-arm64@1.32.0: optional: true @@ -3685,6 +4270,16 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + magicast@0.5.2: + dependencies: + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + source-map-js: 1.2.1 + + make-dir@4.0.0: + dependencies: + semver: 7.7.4 + mark.js@8.11.1: {} marked@4.3.0: {} @@ -3697,6 +4292,13 @@ snapshots: dependencies: is-what: 4.1.16 + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + mime-db@1.52.0: {} mime-types@2.1.35: @@ -3736,6 +4338,33 @@ snapshots: ms@2.1.3: {} + msw@2.12.7(@types/node@24.12.0)(typescript@5.9.3): + dependencies: + '@inquirer/confirm': 5.1.21(@types/node@24.12.0) + '@mswjs/interceptors': 0.40.0 + '@open-draft/deferred-promise': 2.2.0 + '@types/statuses': 2.0.6 + cookie: 1.1.1 + graphql: 16.13.2 + headers-polyfill: 4.0.3 + is-node-process: 1.2.0 + outvariant: 1.4.3 + path-to-regexp: 6.3.0 + picocolors: 1.1.1 + rettime: 0.7.0 + statuses: 2.0.2 + strict-event-emitter: 0.5.1 + tough-cookie: 6.0.1 + type-fest: 5.5.0 + until-async: 3.0.2 + yargs: 17.7.2 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@types/node' + + mute-stream@2.0.0: {} + nanoid@3.3.11: {} neo-async@2.6.2: {} @@ -3820,6 +4449,34 @@ snapshots: fast-xml-parser: 5.5.9 json-pointer: 0.6.2 + outvariant@1.4.3: {} + + oxc-resolver@11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2): + optionalDependencies: + '@oxc-resolver/binding-android-arm-eabi': 11.19.1 + '@oxc-resolver/binding-android-arm64': 11.19.1 + '@oxc-resolver/binding-darwin-arm64': 11.19.1 + '@oxc-resolver/binding-darwin-x64': 11.19.1 + '@oxc-resolver/binding-freebsd-x64': 11.19.1 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.19.1 + '@oxc-resolver/binding-linux-arm-musleabihf': 11.19.1 + '@oxc-resolver/binding-linux-arm64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-arm64-musl': 11.19.1 + '@oxc-resolver/binding-linux-ppc64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-riscv64-musl': 11.19.1 + '@oxc-resolver/binding-linux-s390x-gnu': 11.19.1 + '@oxc-resolver/binding-linux-x64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-x64-musl': 11.19.1 + '@oxc-resolver/binding-openharmony-arm64': 11.19.1 + '@oxc-resolver/binding-wasm32-wasi': 11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + '@oxc-resolver/binding-win32-arm64-msvc': 11.19.1 + '@oxc-resolver/binding-win32-ia32-msvc': 11.19.1 + '@oxc-resolver/binding-win32-x64-msvc': 11.19.1 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + parse5@7.3.0: dependencies: entities: 6.0.1 @@ -3836,6 +4493,8 @@ snapshots: path-key@3.1.1: {} + path-to-regexp@6.3.0: {} + pathe@2.0.3: {} perfect-debounce@2.1.0: {} @@ -3994,6 +4653,10 @@ snapshots: resolve-pkg-maps@1.0.0: {} + rettime@0.7.0: {} + + reusify@1.1.0: {} + rolldown@1.0.0-rc.12(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2): dependencies: '@oxc-project/types': 0.122.0 @@ -4020,6 +4683,10 @@ snapshots: run-applescript@7.1.0: {} + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + safe-buffer@5.2.1: {} saxes@6.0.0: @@ -4076,6 +4743,8 @@ snapshots: siginfo@2.0.0: {} + signal-exit@4.1.0: {} + simple-websocket@9.1.0: dependencies: debug: 4.4.3 @@ -4090,6 +4759,8 @@ snapshots: slugify@1.4.7: {} + smol-toml@1.6.1: {} + solid-js@1.9.12: dependencies: csstype: 3.2.3 @@ -4121,10 +4792,14 @@ snapshots: stackback@0.0.2: {} + statuses@2.0.2: {} + std-env@4.0.0: {} stickyfill@1.1.1: {} + strict-event-emitter@0.5.1: {} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -4144,6 +4819,8 @@ snapshots: min-indent: 1.0.1 optional: true + strip-json-comments@5.0.3: {} + strnum@2.2.2: {} styled-components@6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4): @@ -4163,6 +4840,10 @@ snapshots: stylis@4.3.6: {} + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + swagger2openapi@7.0.8: dependencies: call-me-maybe: 1.0.2 @@ -4181,6 +4862,8 @@ snapshots: symbol-tree@3.2.4: {} + tagged-tag@1.0.0: {} + tailwind-merge@3.5.0: {} tailwindcss-animate@1.0.7(tailwindcss@4.2.2): @@ -4251,6 +4934,10 @@ snapshots: turbo-windows-64: 2.5.4 turbo-windows-arm64: 2.5.4 + type-fest@5.5.0: + dependencies: + tagged-tag: 1.0.0 + typescript@5.9.3: {} uglify-js@3.19.3: @@ -4260,6 +4947,8 @@ snapshots: undici@7.24.7: {} + until-async@3.0.2: {} + update-browserslist-db@1.2.3(browserslist@4.28.2): dependencies: browserslist: 4.28.2 @@ -4309,10 +4998,10 @@ snapshots: optionalDependencies: vite: 8.0.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(jiti@2.6.1)(yaml@2.8.3) - vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(jsdom@29.0.1)(vite@8.0.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(jiti@2.6.1)(yaml@2.8.3)): + vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(jsdom@29.0.1)(msw@2.12.7(@types/node@24.12.0)(typescript@5.9.3))(vite@8.0.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(jiti@2.6.1)(yaml@2.8.3)): dependencies: '@vitest/expect': 4.1.2 - '@vitest/mocker': 4.1.2(vite@8.0.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(jiti@2.6.1)(yaml@2.8.3)) + '@vitest/mocker': 4.1.2(msw@2.12.7(@types/node@24.12.0)(typescript@5.9.3))(vite@8.0.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.0)(jiti@2.6.1)(yaml@2.8.3)) '@vitest/pretty-format': 4.1.2 '@vitest/runner': 4.1.2 '@vitest/snapshot': 4.1.2 @@ -4342,6 +5031,8 @@ snapshots: dependencies: xml-name-validator: 5.0.0 + walk-up-path@4.0.0: {} + webidl-conversions@3.0.1: {} webidl-conversions@8.0.1: {} @@ -4372,6 +5063,12 @@ snapshots: wordwrap@1.0.0: {} + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -4403,6 +5100,8 @@ snapshots: yargs-parser@20.2.9: {} + yargs-parser@21.1.1: {} + yargs@17.0.1: dependencies: cliui: 7.0.4 @@ -4412,3 +5111,17 @@ snapshots: string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 20.2.9 + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yoctocolors-cjs@2.1.3: {} + + zod@4.3.6: {} diff --git a/turbo.json b/turbo.json index b9659c6..e684d47 100644 --- a/turbo.json +++ b/turbo.json @@ -19,6 +19,8 @@ "openapi:validate": { "cache": false }, - "test": {} + "test": {}, + "test:coverage": {}, + "knip": {} } }