UNPKG

@kellanjs/actioncraft

Version:

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

114 lines 4.17 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", }; export const NO_INPUT_SCHEMA_ERROR = { type: "NO_INPUT_SCHEMA", message: "Cannot validate input: no input schema defined for this action", }; // =========================================================================== // 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, actionName) { const message = actionName ? `An unhandled error occurred in action "${actionName}"` : "An unhandled error occurred"; return err({ ...UNHANDLED_ERROR, message }, actionId); } /** * Creates Result objects for implicit return errors. */ export function createImplicitReturnErrorResult(actionId, actionName) { const message = actionName ? `Action handler "${actionName}" must return a value` : "Action handler must return a value"; return err({ ...IMPLICIT_RETURN_ERROR, message }, 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, actionName) { const enhancedMessage = actionName ? `${message} in action "${actionName}"` : message; if ("issues" in errorStructure) { return _buildFlattenedValidationError(type, enhancedMessage, errorStructure.issues); } return _buildNestedValidationError(type, enhancedMessage, errorStructure.formErrors, errorStructure.fieldErrors); } //# sourceMappingURL=errors.js.map