UNPKG

qgenutils

Version:

A security-first Node.js utility library providing authentication, HTTP operations, URL processing, validation, datetime formatting, and template rendering. Designed as a lightweight alternative to heavy npm packages with comprehensive error handling and

150 lines (137 loc) 7.31 kB
/* * WHY THIS MODULE EXISTS: * - Provide a single place for request field validation logic. * - Avoid repeated manual checks in multiple Express controllers. * * MAIN PROBLEMS SOLVED: * - Ensures consistent error messaging when required fields are missing. * - Simplifies controllers by returning boolean success instead of throwing. * * EXPRESS ASSUMPTIONS: * - Functions are called from route handlers with an Express `res` object. */ /* * Validation Utility Module * * This module provides field validation utilities for API endpoints that need to * verify required fields are present and properly formatted before processing. * * DESIGN PHILOSOPHY: * - Fail fast: Return detailed errors immediately when validation fails * - Developer friendly: List all missing fields at once (not just the first) * - Consistent responses: Use standardized error format across all endpoints * - Security minded: Validate input thoroughly before any processing * * COMMON USE CASES: * - API endpoint parameter validation * - Form submission verification * - Database input sanitization * - User registration field checking * QGenUtils Field Validation Utilities * * Centralizes checks that required request fields exist before processing * continues. Following a fail-fast, fail-closed philosophy, any value that * resolves to false (undefined, null, '', 0, false) is considered missing. * Error responses are sent immediately using response-utils to stop further * operations with invalid data and keep controller logic concise. */ const { qerrors } = require('qerrors'); // central error logging integration const logger = require('./logger'); // structured logger const { isValidObject } = require('./input-validation'); // utility to validate plain objects const { sendValidationError, sendServerError } = require('./response-utils'); // unified response helpers /** * Validate required fields in an object * * RATIONALE: API endpoints often require specific fields to be present before * processing can continue. Rather than checking each field individually with * repetitive if statements, this function centralizes the validation logic * and provides consistent error responses. * * IMPLEMENTATION DECISIONS: * - Use filter() to collect ALL missing fields, not just the first one * - Treat falsy values (null, '', 0, false) as "missing" for strict validation * - Return boolean to indicate success/failure to calling code * - Send error response immediately rather than throwing exceptions * * WHY FALSY VALUE CHECKING: * We check !obj[name] which catches: * - undefined (field not present) * - null (explicitly set to null) * - '' (empty string) * - 0 (zero number - might be valid in some contexts) * - false (boolean false - might be valid in some contexts) * * This is intentionally strict. If 0 or false are valid values for your use case, * use a different validation approach or modify the logic here. * * DEVELOPER EXPERIENCE BENEFITS: * - Lists ALL missing fields in one response (saves round trips) * - Clear error messages that specify exactly what's missing * - Consistent error format across all API endpoints * - Debugging logs show validation attempts and results * * ALTERNATIVE APPROACHES CONSIDERED: * - Schema validation libraries (Joi, Yup) - rejected for simplicity * - Throwing exceptions - rejected to avoid try/catch boilerplate * - Individual field checking - rejected due to code duplication * - Generic validation messages - rejected for poor developer experience * * ERROR RESPONSE FORMAT: * The error response follows a standard format that client applications can * reliably parse: * { * "error": "Missing required fields: field1, field2" * } * * This format allows clients to programmatically detect validation errors * and potentially highlight specific missing fields in their UI. * * @param {object} obj - The object to validate (typically req.body or req.query) // first param clarifies target object * @param {Array<string>} requiredFields - Array of field names that must be present and truthy // second param describes required fields * @param {object} res - Express response object for sending error responses // third param is response object for error handling * @returns {boolean} True if all fields are present and valid, false if validation failed */ function requireFields(obj, requiredFields, res) { console.log(`requireFields is running with ${requiredFields && Array.isArray(requiredFields) ? requiredFields.join(',') : 'undefined'}`); logger.debug(`requireFields is running with ${requiredFields && Array.isArray(requiredFields) ? requiredFields.join(',') : 'undefined'}`); // log invocation with field list try { // start validation if (!requiredFields || !Array.isArray(requiredFields)) { // verify requiredFields parameter console.log(`requireFields is returning false - invalid requiredFields parameter`); logger.debug(`requireFields is returning false - invalid requiredFields parameter`); // trace failure reason sendServerError(res, 'Internal validation error'); // consistent 500 response avoids exposing internals return false; // stop processing on invalid parameters } if (!isValidObject(obj)) { // ensure provided object is valid console.log(`requireFields is returning false - invalid obj parameter`); logger.debug(`requireFields is returning false - invalid obj parameter`); // trace object validation failure sendServerError(res, 'Internal validation error'); // uniform handling keeps client logic simple return false; // halt on invalid object } const missingFields = requiredFields.filter(field => !obj[field]); // collect fields with falsy values to force explicit input if (missingFields.length > 0) { // fail fast when any field is missing sendValidationError(res, 'Missing required fields', { missing: missingFields }); // immediate error stops processing console.log(`requireFields is returning false`); logger.debug(`requireFields is returning false`); // record validation failure return false; // signal failed validation } console.log(`requireFields is returning true`); logger.debug(`requireFields is returning true`); // record successful validation return true; // validation passed } catch (error) { qerrors(error, 'requireFields', { requiredFields, obj }); // central logging preserves stack trace for post-mortem analysis sendServerError(res, 'Internal validation error', error, 'requireFields'); // one path for all unexpected issues return false; // safe default on error } } /* * Module Export Strategy: * * We export the requireFields function as the primary validation utility. * This function covers the most common validation scenario: ensuring required * fields are present in request objects. * * FUTURE ENHANCEMENTS: * - Add type validation (string, number, email format, etc.) * - Add length validation (min/max string length, array size) * - Add custom validation rules support * - Add nested object validation * - Add conditional field validation (field X required if field Y is present) */ module.exports = { // expose validator for reuse requireFields // export main field validator };