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": {}
}
}