UNPKG

guardz

Version:

A simple and lightweight TypeScript type guard library for runtime type validation.

80 lines (79 loc) 4.25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateObject = void 0; const isNonNullObject_1 = require("../typeguards/isNonNullObject"); const createValidationResult_1 = require("./createValidationResult"); const createValidationError_1 = require("./createValidationError"); const createTreeNode_1 = require("./createTreeNode"); const combineResults_1 = require("./combineResults"); const validateProperty_1 = require("./validateProperty"); /** * Validate an object with multiple properties using functional approach * @param value - The value to validate * @param propsTypesToCheck - Object containing type guards for each property * @param context - The validation context * @returns A ValidationResult for the entire object */ const validateObject = (value, propsTypesToCheck, context) => { // Handle non-object values functionally const handleNonObjectValue = () => { const error = (0, createValidationError_1.createValidationError)(context.path, 'non-null object', value, `Expected ${context.path} (${JSON.stringify(value)}) to be "non-null object"`); const treeNode = (0, createTreeNode_1.createTreeNode)(context.path, false, 'non-null object', value); treeNode.errors = [error]; // For JSON mode, don't include the error in the result.errors array const errorMode = context.config?.errorMode || 'multi'; return errorMode === 'json' ? (0, createValidationResult_1.createValidationResult)(false, [], treeNode) : (0, createValidationResult_1.createValidationResult)(false, [error], treeNode); }; // Handle single error mode functionally const handleSingleErrorMode = () => { const keys = Object.keys(propsTypesToCheck); // Handle empty schema case if (keys.length === 0) { return (0, createValidationResult_1.createValidationResult)(true, [], (0, createTreeNode_1.createTreeNode)(context.path, true, 'object', value)); } const findFirstError = (keys) => { const [key, ...remainingKeys] = keys; // Object.keys() only returns string keys, so key is guaranteed to be a string const keyStr = key; const typeGuard = propsTypesToCheck[keyStr]; const propertyValue = value[keyStr]; // Use validateProperty to avoid duplicate validation logic const propertyResult = (0, validateProperty_1.validateProperty)(keyStr, propertyValue, typeGuard, context); return propertyResult.valid ? (remainingKeys.length === 0 ? (0, createValidationResult_1.createValidationResult)(true, [], (0, createTreeNode_1.createTreeNode)(context.path, true, 'object', value)) : findFirstError(remainingKeys)) : propertyResult; }; return findFirstError(keys); }; // Handle multi/json error mode functionally const handleMultiJsonMode = () => { const results = Object.keys(propsTypesToCheck).map(key => { const typeGuard = propsTypesToCheck[key]; return (0, validateProperty_1.validateProperty)(key, value[key], typeGuard, context); }); const combinedResult = (0, combineResults_1.combineResults)(results, context.path); const rootTree = (0, createTreeNode_1.createTreeNode)(context.path, combinedResult.valid, 'object', value); rootTree.children = {}; results.forEach(result => { if (result.tree) { const key = result.tree.path.split('.').pop() || 'unknown'; rootTree.children[key] = result.tree; } }); return (0, createValidationResult_1.createValidationResult)(combinedResult.valid, combinedResult.errors, rootTree); }; // Main validation logic using functional composition return !(0, isNonNullObject_1.isNonNullObject)(value, null) ? handleNonObjectValue() : (() => { const errorMode = context.config?.errorMode || 'multi'; return errorMode === 'single' ? handleSingleErrorMode() : handleMultiJsonMode(); })(); }; exports.validateObject = validateObject;