mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-07-16 11:31:04 +02:00
feat: billing and credit management v2 (#429)
* feat: use mps generated correlation ID * chore: update pipecat submodule * feat: add credit purchase URL * feat: carve out billing page and show credit ledger * feat: deprecate dograh based quota tracking * fix: remove cost calculation from dograh codebase * fix: create mps account on migrate to v2 * chore: update pipecat
This commit is contained in:
parent
97d7103480
commit
1f1149f4d5
80 changed files with 3335 additions and 2057 deletions
|
|
@ -2,18 +2,33 @@
|
|||
* Extract a human-readable message from a backend error response.
|
||||
*
|
||||
* The generated API client returns `{ error }` on failure (it does not throw),
|
||||
* and FastAPI shapes that error as either `{ detail: string }` (HTTPException)
|
||||
* or `{ detail: [{ msg, loc, ... }] }` (422 validation). This normalizes both
|
||||
* to a single string so it can be rendered or thrown directly — never pass the
|
||||
* raw `detail` to React, as the 422 array crashes rendering.
|
||||
* and FastAPI shapes that error as `{ detail: string }`, `{ detail:
|
||||
* [{ msg, loc, ... }] }`, or backend validation arrays like `{ detail:
|
||||
* [{ model, message }] }`. This normalizes those to a single string so it can
|
||||
* be rendered or thrown directly.
|
||||
*/
|
||||
export function detailFromError(err: unknown, fallback = "Request failed"): string {
|
||||
if (typeof err === "string") return err;
|
||||
const e = err as { detail?: unknown };
|
||||
if (typeof e?.detail === "string") return e.detail;
|
||||
if (Array.isArray(e?.detail) && e.detail.length > 0) {
|
||||
const first = e.detail[0] as { msg?: string };
|
||||
if (first?.msg) return first.msg;
|
||||
const messages = e.detail
|
||||
.map((item) => {
|
||||
if (typeof item === "string") return item;
|
||||
if (!item || typeof item !== "object") return null;
|
||||
const detail = item as { message?: unknown; msg?: unknown; model?: unknown };
|
||||
const message = typeof detail.message === "string"
|
||||
? detail.message
|
||||
: typeof detail.msg === "string"
|
||||
? detail.msg
|
||||
: null;
|
||||
if (!message) return null;
|
||||
return typeof detail.model === "string" && detail.model
|
||||
? `${detail.model}: ${message}`
|
||||
: message;
|
||||
})
|
||||
.filter((message): message is string => Boolean(message));
|
||||
if (messages.length > 0) return messages.join("\n");
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue