All files / src/lib form-errors.ts

81.81% Statements 9/11
84.61% Branches 11/13
100% Functions 3/3
80% Lines 8/10

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47                          2x 1x   1x               1x                       2x 1x   1x       1x      
import { ApiError } from "./api/base";
 
/**
 * Map per-field validation errors from an ApiError into a lookup record for
 * inline form display. Returns an empty object for unrelated errors so callers
 * can spread it unconditionally.
 *
 * Usage:
 *   const fieldErrors = extractFieldErrors(err);
 *   setPhoneError(fieldErrors.phone);
 *   const generalMessage = hasFieldErrors(err) ? null : err.message;
 */
export function extractFieldErrors(err: unknown): Record<string, string> {
	if (err instanceof ApiError && err.fieldErrors) {
		return err.fieldErrors;
	}
	return {};
}
 
/**
 * True when the error carries field-specific messages. Useful to decide
 * whether to show a form-level banner vs. rely on inline field errors.
 */
export function hasFieldErrors(err: unknown): boolean {
	return (
		err instanceof ApiError &&
		!!err.fieldErrors &&
		Object.keys(err.fieldErrors).length > 0
	);
}
 
/**
 * Produce a compact, user-facing summary when no field errors are present.
 * Hides internal codes and falls back to a generic message.
 */
export function getFormSubmitError(err: unknown): string | null {
	if (err instanceof ApiError) {
		Eif (hasFieldErrors(err)) {
			// Field errors render inline — no need for a duplicate banner.
			return null;
		}
		return err.message;
	}
	Eif (err instanceof Error) return err.message;
	return "Something went wrong";
}