UNPKG

@kellanjs/actioncraft

Version:

Fluent, type-safe builder for Next.js server actions.

101 lines 3.55 kB
import { EXTERNAL_ERROR_TYPES, INTERNAL_ERROR_TYPES } from "../types/errors.js"; import { err } from "../types/result.js"; // =========================================================================== // CONSTANTS // =========================================================================== export const UNHANDLED_ERROR = { type: EXTERNAL_ERROR_TYPES.UNHANDLED, message: "An unhandled error occurred", }; export const IMPLICIT_RETURN_ERROR = { type: INTERNAL_ERROR_TYPES.IMPLICIT_RETURN, message: "Action handler must return a value", }; // =========================================================================== // FACTORY HELPERS // =========================================================================== /** * Creates internal logic errors with custom messages. */ export const createInternalLogicError = (message) => ({ type: INTERNAL_ERROR_TYPES.INTERNAL_LOGIC, message, }); /** * Creates Result objects for unhandled errors. */ export function createUnhandledErrorResult(actionId) { return err({ ...UNHANDLED_ERROR }, actionId); } /** * Creates Result objects for implicit return errors. */ export function createImplicitReturnErrorResult(actionId) { return err({ ...IMPLICIT_RETURN_ERROR }, actionId); } // =========================================================================== // VALIDATION-ERROR STRUCTURING HELPERS // =========================================================================== /** * Normalises Standard Schema path segments to string|number for serialization. */ function _normalisePath(path) { if (!path) return []; return path .map((segment) => { if (typeof segment === "symbol") return undefined; if (typeof segment === "object" && segment !== null && "key" in segment) { const key = segment.key; return typeof key === "symbol" ? undefined : key; } return segment; }) .filter((p) => p !== undefined); } /** * Formats validation issues into structured error objects based on the configured format. */ export function formatValidationIssues(issues, format) { if (format === "nested") { const formErrors = []; const fieldErrors = {}; for (const issue of issues) { const currentPath = _normalisePath(issue.path); if (currentPath.length === 0) { formErrors.push(issue.message); } else { const pathKey = currentPath.join("."); if (!fieldErrors[pathKey]) fieldErrors[pathKey] = []; fieldErrors[pathKey].push(issue.message); } } return { formErrors, fieldErrors }; } // Default to 'flattened' return { issues: issues.map(({ path, message }) => ({ path: _normalisePath(path), message, })), }; } function _buildFlattenedValidationError(type, message, issues) { return { type, message, issues }; } function _buildNestedValidationError(type, message, formErrors, fieldErrors) { return { type, message, formErrors, fieldErrors }; } /** * Creates validation error objects. */ export function createValidationError(type, message, errorStructure) { if ("issues" in errorStructure) { return _buildFlattenedValidationError(type, message, errorStructure.issues); } return _buildNestedValidationError(type, message, errorStructure.formErrors, errorStructure.fieldErrors); } //# sourceMappingURL=errors.js.map