mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-05 02:41:56 +00:00
* feat(ui): add the typed openapi-fetch client (fetchClient) as the dashboard fetch foundation
Introduces fetchClient (openapi-fetch) bound to schema.d.ts, used inside ordinary TanStack Query hooks so path/query/body types come from the proxy's OpenAPI spec. A small runtime registry feeds the client the base URL and auth header name (registered by networking) and the session token (published by AuthContext), so call sites carry no token plumbing; auth-header injection and ApiError mapping live in openapi-fetch middleware reusing deriveErrorMessage/ApiError from client.ts, and non-2xx maps to a thrown ApiError so query functions just read .data.
The base URL default resolves from NEXT_PUBLIC_BASE_URL so a request still targets the right origin if it fires before networking registers its getter. AuthContext clears accessToken alongside the token on logout so no query fires unauthenticated after the session ends.
Foundation only; callers migrate one at a time, each fully typed, in follow-up changes.
* feat(ui): migrate useCustomers to the typed fetchClient
Converts useCustomers from allEndUsersCall to fetchClient.GET("/customer/list"); the response is typed as LiteLLM_EndUserTable[] from the schema, so the hand-written Customer/CustomersResponse types are deleted. They were also inaccurate (allowed_model_region was string but is "eu"|"us", and a budget_id the table has no field for). No cast; the schema type flows to the one consumer. First caller on the new pattern.
* fix(ui): route typed-client errors through the session-expiry handler
The typed fetchClient middleware threw ApiError without invoking the
handleError side effect that the legacy createApiClient wires via
onError, so a migrated caller hitting an expired key no longer triggered
the auto-logout. Add an error-handler seam to runtime.ts, register
handleError from networking.tsx alongside the base-url/header getters,
and call it in the middleware before throwing so both clients behave the
same. Regression test asserts the handler fires with the derived message
on non-2xx and stays silent on success
* fix(ui): point the customers EndUser type at CustomerResponse
The /customer/list response model was renamed to CustomerResponse on
staging; the merged branch still aliased EndUser to LiteLLM_EndUserTable,
so the exported type and its test mock had drifted from what the schema
actually returns. CustomerResponse is also the accurate shape (it types
allowed_model_region as 'eu' | 'us' and carries budget_id)
* chore(ui): refresh eslint-metrics baseline after staging merge
The recorded baseline predated the litellm_internal_staging merge, so its
no-explicit-any and no-large-inline-object-arg counts were higher than the
merged tree actually has. Regenerate via npm run lint:metrics so the gate
reflects current reality
* refactor(ui): source the typed client token from the session cookie, not AuthContext
The typed client read its bearer from a runtime value that AuthContext pushed
via setAuthToken, but migrated hooks gate enabled on useAuthorized, which
decodes the cookie directly. Two independent derivations of the same cookie with
different timing: on first load the query fires (useAuthorized sees the token)
before AuthContext's async effect publishes it, so the first request goes out
unauthenticated and only succeeds on a React Query retry.
Make the token a registered getter like the base-url and header-name getters,
reading the same cookie useAuthorized decodes, so the client's token and the
gate can't diverge. Revert the AuthContext changes entirely; nothing is pushed
from React state anymore.
109 lines
3.3 KiB
JSON
109 lines
3.3 KiB
JSON
{
|
|
"name": "litellm-dashboard",
|
|
"version": "0.1.0",
|
|
"private": true,
|
|
"scripts": {
|
|
"dev": "next dev",
|
|
"dev:webpack": "next dev --webpack",
|
|
"build": "next build",
|
|
"start": "next start",
|
|
"lint": "eslint .",
|
|
"lint:metrics": "node scripts/update-lint-metrics.mjs",
|
|
"test": "vitest",
|
|
"test:dot": "vitest --reporter=dot",
|
|
"test:watch": "vitest -w",
|
|
"test:coverage": "vitest run --coverage",
|
|
"format": "prettier --write .",
|
|
"format:check": "prettier --check .",
|
|
"e2e": "playwright test --config e2e_tests/playwright.config.ts",
|
|
"e2e:ui": "playwright test --ui --config e2e_tests/playwright.config.ts",
|
|
"e2e:migration": "playwright test e2e_tests/tests/migration/migratedPages.spec.ts --config e2e_tests/playwright.config.ts",
|
|
"e2e:migration:root": "playwright test --config e2e_tests/migration.serverRootPath.config.ts",
|
|
"knip": "knip",
|
|
"knip:fix": "knip --fix",
|
|
"gen:api": "node scripts/gen-api-types.mjs"
|
|
},
|
|
"dependencies": {
|
|
"@ant-design/cssinjs": "1.24.0",
|
|
"@ant-design/icons": "5.6.1",
|
|
"@anthropic-ai/sdk": "0.92.0",
|
|
"@base-ui/react": "^1.6.0",
|
|
"@headlessui/tailwindcss": "0.2.2",
|
|
"@heroicons/react": "1.0.6",
|
|
"@tanstack/react-pacer": "0.2.0",
|
|
"@tanstack/react-query": "5.100.7",
|
|
"@tanstack/react-table": "8.21.3",
|
|
"@tremor/react": "3.18.7",
|
|
"@types/papaparse": "5.5.2",
|
|
"antd": "5.29.3",
|
|
"cva": "1.0.0-beta.4",
|
|
"date-fns": "^4.4.0",
|
|
"dayjs": "1.11.19",
|
|
"jwt-decode": "4.0.0",
|
|
"lucide-react": "0.513.0",
|
|
"moment": "2.30.1",
|
|
"next": "16.2.6",
|
|
"openai": "4.104.0",
|
|
"openapi-fetch": "^0.17.0",
|
|
"papaparse": "5.5.3",
|
|
"react": "18.3.1",
|
|
"react-copy-to-clipboard": "5.1.1",
|
|
"react-dom": "18.3.1",
|
|
"react-json-view-lite": "2.5.0",
|
|
"react-markdown": "9.1.0",
|
|
"react-syntax-highlighter": "15.6.6",
|
|
"recharts": "3.9.2",
|
|
"remark-gfm": "4.0.1",
|
|
"tailwind-merge": "3.4.0",
|
|
"uuid": "14.0.0"
|
|
},
|
|
"devDependencies": {
|
|
"@eslint/js": "9.39.2",
|
|
"@playwright/test": "1.58.1",
|
|
"@tailwindcss/forms": "0.5.11",
|
|
"@tailwindcss/postcss": "4.3.2",
|
|
"@testing-library/dom": "10.4.1",
|
|
"@testing-library/jest-dom": "6.9.1",
|
|
"@testing-library/react": "16.3.2",
|
|
"@testing-library/user-event": "14.6.1",
|
|
"@types/lodash": "4.17.23",
|
|
"@types/node": "20.19.37",
|
|
"@types/react": "18.2.48",
|
|
"@types/react-copy-to-clipboard": "5.0.7",
|
|
"@types/react-dom": "18.3.7",
|
|
"@types/react-syntax-highlighter": "15.5.13",
|
|
"@vitest/coverage-v8": "3.2.6",
|
|
"@vitest/ui": "3.2.6",
|
|
"eslint": "9.39.2",
|
|
"eslint-config-next": "16.2.6",
|
|
"eslint-config-prettier": "10.1.8",
|
|
"eslint-plugin-unused-imports": "4.3.0",
|
|
"jsdom": "27.4.0",
|
|
"knip": "5.83.1",
|
|
"openapi-typescript": "7.13.0",
|
|
"postcss": "8.5.13",
|
|
"prettier": "3.2.5",
|
|
"tailwindcss": "4.3.2",
|
|
"tw-animate-css": "1.4.0",
|
|
"typescript": "5.9.3",
|
|
"typescript-eslint": "8.60.1",
|
|
"vitest": "3.2.6"
|
|
},
|
|
"overrides": {
|
|
"prismjs": "1.30.0",
|
|
"js-yaml": "4.2.0",
|
|
"glob": "13.0.0",
|
|
"minimatch": "10.2.4",
|
|
"lodash": "4.18.1",
|
|
"ws": "8.21.0",
|
|
"braces": "3.0.3",
|
|
"axios": "1.13.6",
|
|
"postcss": "8.5.13",
|
|
"esbuild": "0.28.1",
|
|
"date-fns": "^4.4.0"
|
|
},
|
|
"engines": {
|
|
"node": ">=20.9.0",
|
|
"npm": ">=8.3.0"
|
|
}
|
|
}
|