{"version":3,"sources":["../../src/types/ps-errors.ts"],"sourcesContent":["/**\n * Typed errors returned by Personal Server endpoints.\n *\n * @remarks\n * vana-connect (and other PS clients) need to branch on a small, stable set\n * of lowercase error codes. Personal Server routes currently return protocol\n * errors as `{ error: { code, errorCode, message } }`, while older PoC\n * clients used `{ code, message }`; the parser accepts both shapes.\n *\n * @category Auth\n */\n\n/** Stable error codes returned by Personal Server. */\nexport type PSErrorCode =\n  | \"missing_auth\"\n  | \"invalid_signature\"\n  | \"unregistered_builder\"\n  | \"not_owner\"\n  | \"expired_token\"\n  | \"grant_invalid\"\n  | \"grant_required\"\n  | \"grant_expired\"\n  | \"grant_revoked\"\n  | \"scope_mismatch\"\n  | \"fee_required\"\n  | \"ps_unavailable\"\n  | \"server_not_configured\"\n  | \"content_too_large\";\n\n/** Typed error wrapping a non-2xx Personal Server response. */\nexport class PSError extends Error {\n  constructor(\n    public readonly code: PSErrorCode,\n    message: string,\n  ) {\n    super(message);\n    this.name = \"PSError\";\n  }\n}\n\nconst KNOWN_CODES: ReadonlySet<PSErrorCode> = new Set<PSErrorCode>([\n  \"missing_auth\",\n  \"invalid_signature\",\n  \"unregistered_builder\",\n  \"not_owner\",\n  \"expired_token\",\n  \"grant_invalid\",\n  \"grant_required\",\n  \"grant_expired\",\n  \"grant_revoked\",\n  \"scope_mismatch\",\n  \"fee_required\",\n  \"ps_unavailable\",\n  \"server_not_configured\",\n  \"content_too_large\",\n]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction normalizeCode(value: unknown): PSErrorCode | null {\n  if (typeof value !== \"string\") {\n    return null;\n  }\n  const code = value.toLowerCase() as PSErrorCode;\n  return KNOWN_CODES.has(code) ? code : null;\n}\n\nfunction extractPSErrorBody(\n  body: unknown,\n): { code: PSErrorCode; message: string } | null {\n  if (!isRecord(body)) {\n    return null;\n  }\n\n  const nested = isRecord(body.error) ? body.error : null;\n  const code = normalizeCode(\n    nested?.errorCode ?? nested?.code ?? body.errorCode ?? body.code,\n  );\n  const message = nested?.message ?? body.message;\n\n  if (!code || typeof message !== \"string\") {\n    return null;\n  }\n\n  return { code, message };\n}\n\n/**\n * Read a Personal Server JSON error body from a non-2xx {@link Response} and\n * return the typed {@link PSError}. The returned code is always lowercase.\n *\n * @returns A {@link PSError} for non-2xx responses with a recognised code,\n *   or `null` for 2xx responses, malformed JSON, or unrecognised codes.\n */\nexport async function parsePSError(\n  response: Response,\n): Promise<PSError | null> {\n  if (response.ok) {\n    return null;\n  }\n\n  let body: unknown;\n  try {\n    body = await response.json();\n  } catch {\n    return null;\n  }\n\n  const errorBody = extractPSErrorBody(body);\n  return errorBody ? new PSError(errorBody.code, errorBody.message) : null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8BO,MAAM,gBAAgB,MAAM;AAAA,EACjC,YACkB,MAChB,SACA;AACA,UAAM,OAAO;AAHG;AAIhB,SAAK,OAAO;AAAA,EACd;AAAA,EALkB;AAMpB;AAEA,MAAM,cAAwC,oBAAI,IAAiB;AAAA,EACjE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,SAAS,OAAkD;AAClE,SAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,cAAc,OAAoC;AACzD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,OAAO,MAAM,YAAY;AAC/B,SAAO,YAAY,IAAI,IAAI,IAAI,OAAO;AACxC;AAEA,SAAS,mBACP,MAC+C;AAC/C,MAAI,CAAC,SAAS,IAAI,GAAG;AACnB,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,SAAS,KAAK,KAAK,IAAI,KAAK,QAAQ;AACnD,QAAM,OAAO;AAAA,IACX,QAAQ,aAAa,QAAQ,QAAQ,KAAK,aAAa,KAAK;AAAA,EAC9D;AACA,QAAM,UAAU,QAAQ,WAAW,KAAK;AAExC,MAAI,CAAC,QAAQ,OAAO,YAAY,UAAU;AACxC,WAAO;AAAA,EACT;AAEA,SAAO,EAAE,MAAM,QAAQ;AACzB;AASA,eAAsB,aACpB,UACyB;AACzB,MAAI,SAAS,IAAI;AACf,WAAO;AAAA,EACT;AAEA,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,SAAS,KAAK;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,mBAAmB,IAAI;AACzC,SAAO,YAAY,IAAI,QAAQ,UAAU,MAAM,UAAU,OAAO,IAAI;AACtE;","names":[]}