UNPKG

@alexcatdad/calico-validators

Version:

Optional JSON Schema validator for @alexcatdad/calico. Tree-shakeable validation module for data validation before export.

122 lines (121 loc) 3.65 kB
// src/index.ts function validate(data, schema) { const errors = []; function validateNode(value, nodeSchema, path) { if (!nodeSchema) return; if (nodeSchema.type) { const type = nodeSchema.type; if (type === "string" && typeof value !== "string") { errors.push({ path, message: `Expected string, got ${typeof value}`, value }); } else if (type === "number" && typeof value !== "number") { errors.push({ path, message: `Expected number, got ${typeof value}`, value }); } else if (type === "boolean" && typeof value !== "boolean") { errors.push({ path, message: `Expected boolean, got ${typeof value}`, value }); } else if (type === "array" && !Array.isArray(value)) { errors.push({ path, message: `Expected array, got ${typeof value}`, value }); } else if (type === "object" && (typeof value !== "object" || value === null || Array.isArray(value))) { errors.push({ path, message: `Expected object, got ${typeof value}`, value }); } } if (nodeSchema.required && typeof value === "object" && value !== null) { for (const field of nodeSchema.required) { if (!(field in value)) { errors.push({ path: `${path}.${field}`, message: "Field is required", value: undefined }); } } } if (nodeSchema.properties && typeof value === "object" && value !== null) { for (const key in nodeSchema.properties) { if (key in value) { validateNode(value[key], nodeSchema.properties[key], `${path}.${key}`); } } } if (nodeSchema.items && Array.isArray(value)) { value.forEach((item, index) => { validateNode(item, nodeSchema.items, `${path}[${index}]`); }); } if (typeof value === "number") { if (nodeSchema.minimum !== undefined && value < nodeSchema.minimum) { errors.push({ path, message: `Value must be >= ${nodeSchema.minimum}`, value }); } if (nodeSchema.maximum !== undefined && value > nodeSchema.maximum) { errors.push({ path, message: `Value must be <= ${nodeSchema.maximum}`, value }); } } if (typeof value === "string") { if (nodeSchema.minLength !== undefined && value.length < nodeSchema.minLength) { errors.push({ path, message: `String length must be >= ${nodeSchema.minLength}`, value }); } if (nodeSchema.maxLength !== undefined && value.length > nodeSchema.maxLength) { errors.push({ path, message: `String length must be <= ${nodeSchema.maxLength}`, value }); } if (nodeSchema.pattern) { const regex = new RegExp(nodeSchema.pattern); if (!regex.test(value)) { errors.push({ path, message: `String does not match pattern ${nodeSchema.pattern}`, value }); } } if (nodeSchema.format === "email") { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(value)) { errors.push({ path, message: "Invalid email format", value }); } } } } validateNode(data, schema, "root"); return { valid: errors.length === 0, errors: errors.length > 0 ? errors : undefined }; } export { validate };