const JSON_FIELD_KEYS = ["fieldErrors", "fields", "errors", "data"];
const ISSUE_KEYS = ["details", "issues", "errors"];
function coerceFieldErrors(input) {
  if (!input || typeof input !== "object") return null;
  const result = {};
  for (const [rawKey, rawValue] of Object.entries(input)) {
    const key = typeof rawKey === "string" && rawKey.trim().length > 0 ? rawKey.trim() : null;
    if (!key) continue;
    if (rawValue === void 0 || rawValue === null) continue;
    const message = typeof rawValue === "string" ? rawValue : typeof rawValue?.message === "string" ? rawValue.message : String(rawValue);
    if (!message) continue;
    result[key] = message;
  }
  return Object.keys(result).length ? result : null;
}
function mapIssueArray(issues) {
  if (!Array.isArray(issues)) return null;
  const result = {};
  for (const issue of issues) {
    if (!issue || typeof issue !== "object") continue;
    const pathValue = Array.isArray(issue.path) ? issue.path : [];
    let field = null;
    for (const part of pathValue) {
      if (typeof part === "string" && part.trim().length > 0) {
        field = part.trim();
        break;
      }
    }
    if (!field && typeof issue.field === "string") {
      const fromField = issue.field.trim();
      field = fromField.length > 0 ? fromField : null;
    }
    if (!field && pathValue.length > 0) {
      const joined = pathValue.map((part) => String(part)).join(".");
      if (joined) field = joined;
    }
    if (!field) continue;
    const message = typeof issue.message === "string" ? issue.message : null;
    if (!message) continue;
    result[field] = message;
  }
  return Object.keys(result).length ? result : null;
}
function tryParseJson(text) {
  try {
    return JSON.parse(text);
  } catch {
    return null;
  }
}
function collectCandidatePayloads(err) {
  const candidates = [];
  if (!err) return candidates;
  candidates.push(err);
  if (typeof err === "string") {
    const parsed = tryParseJson(err);
    if (parsed) candidates.push(parsed);
  } else if (err instanceof Error) {
    if (typeof err.message === "string" && err.message.trim()) {
      const parsed = tryParseJson(err.message.trim());
      if (parsed) candidates.push(parsed);
    }
    if (err.cause) {
      candidates.push(err.cause);
    }
  } else if (typeof err === "object") {
    const maybeMessage = err?.message;
    if (typeof maybeMessage === "string") {
      const parsed = tryParseJson(maybeMessage);
      if (parsed) candidates.push(parsed);
    }
    if (err?.body) candidates.push(err.body);
    if (err?.response) candidates.push(err.response);
    if (err?.data) candidates.push(err.data);
  }
  return candidates;
}
function normalizeCrudServerError(err) {
  let message;
  let fieldErrors;
  const processed = /* @__PURE__ */ new Set();
  const queue = collectCandidatePayloads(err);
  while (queue.length) {
    const current = queue.shift();
    if (!current || processed.has(current)) continue;
    processed.add(current);
    if (typeof current === "string") {
      if (!message) message = current;
      const parsed = tryParseJson(current);
      if (parsed) queue.push(parsed);
      continue;
    }
    if (current instanceof Response) {
      const body = current?._bodyInit;
      if (body) queue.push(body);
      continue;
    }
    if (typeof current !== "object") continue;
    const candidateMessage = typeof current.error === "string" ? current.error : typeof current.message === "string" ? current.message : void 0;
    if (candidateMessage && !message) message = candidateMessage;
    for (const key of JSON_FIELD_KEYS) {
      const value = current[key];
      if (value && typeof value === "object") {
        const mapped = coerceFieldErrors(value);
        if (mapped) {
          fieldErrors = { ...fieldErrors || {}, ...mapped };
        }
      }
    }
    for (const key of ISSUE_KEYS) {
      const value = current[key];
      const mapped = mapIssueArray(value);
      if (mapped) {
        fieldErrors = { ...fieldErrors || {}, ...mapped };
      }
    }
    const nestedKeys = ["body", "response", "data", "details"];
    for (const nestedKey of nestedKeys) {
      const nested = current[nestedKey];
      if (nested && !processed.has(nested)) queue.push(nested);
    }
  }
  if (!message && fieldErrors && Object.keys(fieldErrors).length === 1) {
    const [, firstMessage] = Object.entries(fieldErrors)[0];
    message = firstMessage;
  }
  if (!message && err instanceof Error && err.message) {
    message = err.message;
  } else if (!message && typeof err === "string") {
    message = err;
  }
  return { message, fieldErrors };
}
function mapServerFieldNameToFormId(field, options) {
  const trimmed = field.trim();
  const customEntity = !!options?.customEntity;
  if (customEntity) {
    if (trimmed.startsWith("cf_")) return trimmed.slice(3);
    if (trimmed.startsWith("cf:")) return trimmed.slice(3);
    return trimmed;
  }
  if (trimmed.startsWith("cf_")) return trimmed;
  if (trimmed.startsWith("cf:")) return `cf_${trimmed.slice(3)}`;
  return trimmed;
}
function mapCrudServerErrorToFormErrors(err, options) {
  const normalized = normalizeCrudServerError(err);
  const fieldErrors = normalized.fieldErrors;
  if (!fieldErrors) return { message: normalized.message };
  const mapped = {};
  for (const [key, value] of Object.entries(fieldErrors)) {
    const formId = mapServerFieldNameToFormId(key, options);
    if (!formId) continue;
    mapped[formId] = value;
  }
  let message = normalized.message;
  const firstEntry = Object.entries(mapped)[0];
  if (firstEntry && (!message || typeof message === "string" && message.trim().toLowerCase() === "invalid input")) {
    const [, fieldMessage] = firstEntry;
    if (typeof fieldMessage === "string" && fieldMessage.trim().length) {
      message = fieldMessage;
    }
  }
  return {
    message,
    fieldErrors: mapped
  };
}
function parseServerMessage(input) {
  const trimmed = input.trim();
  if (!trimmed) return trimmed;
  if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
    try {
      const parsed = JSON.parse(trimmed);
      const text = typeof parsed?.error === "string" && parsed.error.trim() ? parsed.error.trim() : typeof parsed?.message === "string" && parsed.message.trim() ? parsed.message.trim() : null;
      if (text) return text;
    } catch {
    }
  }
  return trimmed;
}
function buildHttpError(message, extras) {
  const error = new Error(message);
  if (!extras) return error;
  for (const [key, value] of Object.entries(extras)) {
    error[key] = value;
  }
  return error;
}
async function raiseCrudError(res, fallbackMessage) {
  let raw = null;
  try {
    raw = await res.text();
  } catch {
    raw = null;
  }
  const trimmed = raw && raw.trim() ? raw.trim() : null;
  const parsed = trimmed ? tryParseJson(trimmed) : null;
  if (parsed && typeof parsed === "object") {
    const data = parsed;
    const rawMessage = typeof data.error === "string" && data.error.trim() ? data.error.trim() : typeof data.message === "string" && data.message.trim() ? data.message.trim() : fallbackMessage ?? `Request failed (${res.status})`;
    const message2 = parseServerMessage(rawMessage);
    throw buildHttpError(message2, {
      ...data,
      status: res.status,
      raw: trimmed ?? null
    });
  }
  const message = parseServerMessage(fallbackMessage ?? `Request failed (${res.status})`);
  throw buildHttpError(message, { status: res.status, raw: trimmed ?? null });
}
function createCrudFormError(message, fieldErrors, extras) {
  const error = new Error(message);
  if (fieldErrors && Object.keys(fieldErrors).length) error.fieldErrors = fieldErrors;
  if (extras?.status !== void 0) error.status = extras.status;
  if (extras?.details !== void 0) error.details = extras.details;
  return error;
}
async function readJsonSafe(res, fallback = null) {
  try {
    const text = await res.text();
    if (!text) return fallback;
    return JSON.parse(text);
  } catch {
    return fallback;
  }
}
export {
  createCrudFormError,
  mapCrudServerErrorToFormErrors,
  mapServerFieldNameToFormId,
  normalizeCrudServerError,
  parseServerMessage,
  raiseCrudError,
  readJsonSafe
};
//# sourceMappingURL=serverErrors.js.map
