{"version":3,"file":"HttpError.mjs","names":[],"sources":["../../../../../../http/src/HttpError.ts"],"sourcesContent":["import type { OutgoingRequest } from \"./Http.types\";\nimport { redactHeaders } from \"./utils/redact\";\n\n/**\n * Structured error thrown (or returned) by every Http method.\n *\n * All properties and predicates are accessible without calling a function:\n *   if (error.isAborted)        { return; }\n *   if (error.isNotFound)       { return null; }\n *   if (error.isValidationError) { return showErrors(error.body); }\n *   console.log(error.headers?.['x-request-id']);\n */\nexport class HttpError extends Error {\n  /** HTTP status code, or null for network/abort/timeout errors. */\n  public readonly status: number | null;\n\n  /** Parsed response body (JSON if Content-Type is application/json, else raw text). */\n  public readonly body: unknown;\n\n  /** The raw Response object, if a response was received. */\n  public readonly response: Response | null;\n\n  /** True when the request was cancelled via AbortController. */\n  public readonly isAborted: boolean;\n\n  /** True when the request hit the timeout limit. */\n  public readonly isTimeout: boolean;\n\n  /** True for network-level failures (DNS, CORS, no connection). */\n  public readonly isNetwork: boolean;\n\n  /**\n   * Response headers as a plain object. null when no response was received\n   * (network error, timeout, or abort).\n   *\n   * Shortcut so you don't have to reach into `error.response?.headers.get(...)`:\n   *   const remaining = error.headers?.['x-rate-limit-remaining'];\n   */\n  public readonly headers: Record<string, string> | null;\n\n  /**\n   * The outgoing request that triggered this error, with sensitive headers\n   * (Authorization, Cookie, …) redacted — safe to log directly.\n   * Useful in `throw: true` mode where you only have the HttpError (no HttpResult).\n   *\n   * Use `rawRequest` if you need the live, unredacted headers.\n   */\n  public readonly request: OutgoingRequest | null;\n\n  /**\n   * The outgoing request with its original, unredacted headers.\n   * May contain live `Authorization`/`Cookie` values — do not log this without\n   * redacting first.\n   */\n  public readonly rawRequest: OutgoingRequest | null;\n\n  constructor(opts: {\n    message: string;\n    status?: number | null;\n    body?: unknown;\n    response?: Response | null;\n    isAborted?: boolean;\n    isTimeout?: boolean;\n    isNetwork?: boolean;\n    headers?: Record<string, string> | null;\n    request?: OutgoingRequest | null;\n  }) {\n    super(opts.message);\n    this.name = \"HttpError\";\n    this.status = opts.status ?? null;\n    this.body = opts.body ?? null;\n    this.response = opts.response ?? null;\n    this.isAborted = opts.isAborted ?? false;\n    this.isTimeout = opts.isTimeout ?? false;\n    this.isNetwork = opts.isNetwork ?? false;\n    this.headers = opts.headers ?? null;\n    this.rawRequest = opts.request ?? null;\n    this.request = opts.request\n      ? { ...opts.request, headers: redactHeaders(opts.request.headers) }\n      : null;\n\n    // Preserve prototype chain in transpiled ES5 environments.\n    Object.setPrototypeOf(this, new.target.prototype);\n  }\n\n  // ─── Status predicates (getters — no () needed) ──────────────────────────────\n\n  /** 4xx status code. */\n  get isClientError(): boolean {\n    return this.status !== null && this.status >= 400 && this.status < 500;\n  }\n\n  /** 5xx status code. */\n  get isServerError(): boolean {\n    return this.status !== null && this.status >= 500 && this.status < 600;\n  }\n\n  /** 401 Unauthorized. */\n  get isUnauthorized(): boolean {\n    return this.status === 401;\n  }\n\n  /** 403 Forbidden. */\n  get isForbidden(): boolean {\n    return this.status === 403;\n  }\n\n  /** 404 Not Found. */\n  get isNotFound(): boolean {\n    return this.status === 404;\n  }\n\n  /** 422 Unprocessable Entity — typical validation error. */\n  get isValidationError(): boolean {\n    return this.status === 422;\n  }\n\n  /** 429 Too Many Requests. */\n  get isRateLimited(): boolean {\n    return this.status === 429;\n  }\n\n  toJSON(): Record<string, unknown> {\n    return {\n      name: this.name,\n      message: this.message,\n      status: this.status,\n      body: this.body,\n      isAborted: this.isAborted,\n      isTimeout: this.isTimeout,\n      isNetwork: this.isNetwork,\n      headers: this.headers,\n      // `request` is intentionally omitted — it may contain raw Authorization / Cookie headers.\n    };\n  }\n}\n"],"mappings":";;;;;;;;;;;;AAYA,IAAa,YAAb,cAA+B,MAAM;CA4CnC,YAAY,MAUT;EACD,MAAM,KAAK,OAAO;EAClB,KAAK,OAAO;EACZ,KAAK,SAAS,KAAK,UAAU;EAC7B,KAAK,OAAO,KAAK,QAAQ;EACzB,KAAK,WAAW,KAAK,YAAY;EACjC,KAAK,YAAY,KAAK,aAAa;EACnC,KAAK,YAAY,KAAK,aAAa;EACnC,KAAK,YAAY,KAAK,aAAa;EACnC,KAAK,UAAU,KAAK,WAAW;EAC/B,KAAK,aAAa,KAAK,WAAW;EAClC,KAAK,UAAU,KAAK,UAChB;GAAE,GAAG,KAAK;GAAS,SAAS,cAAc,KAAK,QAAQ,OAAO;EAAE,IAChE;EAGJ,OAAO,eAAe,MAAM,IAAI,OAAO,SAAS;CAClD;;CAKA,IAAI,gBAAyB;EAC3B,OAAO,KAAK,WAAW,QAAQ,KAAK,UAAU,OAAO,KAAK,SAAS;CACrE;;CAGA,IAAI,gBAAyB;EAC3B,OAAO,KAAK,WAAW,QAAQ,KAAK,UAAU,OAAO,KAAK,SAAS;CACrE;;CAGA,IAAI,iBAA0B;EAC5B,OAAO,KAAK,WAAW;CACzB;;CAGA,IAAI,cAAuB;EACzB,OAAO,KAAK,WAAW;CACzB;;CAGA,IAAI,aAAsB;EACxB,OAAO,KAAK,WAAW;CACzB;;CAGA,IAAI,oBAA6B;EAC/B,OAAO,KAAK,WAAW;CACzB;;CAGA,IAAI,gBAAyB;EAC3B,OAAO,KAAK,WAAW;CACzB;CAEA,SAAkC;EAChC,OAAO;GACL,MAAM,KAAK;GACX,SAAS,KAAK;GACd,QAAQ,KAAK;GACb,MAAM,KAAK;GACX,WAAW,KAAK;GAChB,WAAW,KAAK;GAChB,WAAW,KAAK;GAChB,SAAS,KAAK;EAEhB;CACF;AACF"}