UNPKG

@apizr-io/class-utils

Version:

Package containing all class-validator function with all custom apizr class validation functions

101 lines 4.12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.IsRecord = void 0; const class_transformer_1 = require("class-transformer"); const class_validator_1 = require("class-validator"); const isObjectType = async (obj, type) => { switch (type) { case 'number': case 'boolean': case 'string': case 'object': return typeof obj === type; case 'null': return obj === null; case 'undefined': return obj === undefined; default: { if ('type' in type) { const types = Array.isArray(type.type) ? type.type : [type.type]; if (type.array && Array.isArray(obj)) { const results = await Promise.all(obj.map((el) => isOneOfTypes(types, el))); return results.reduce((acc, result) => acc && result, true); } return isOneOfTypes(types, obj); } const instance = (0, class_transformer_1.plainToInstance)(type, obj); const errors = await (0, class_validator_1.validate)(instance); return errors.length === 0; } } }; const isOneOfTypes = async (types, obj) => { for (const type of types) { const result = await isObjectType(obj, type); if (result === true) { return true; } } return false; }; const areKeysValid = (keys, type) => { const keysResults = keys.map((key) => { if (type === 'string') { return typeof key === 'string'; } return !isNaN(Number(key)); }); return keysResults.reduce((acc, result) => acc && result, true); }; const getTypeName = (type) => { if (typeof type === 'object') { const types = Array.isArray(type.type) ? type.type : [type.type]; const stringTypes = types.map((el) => getTypeName(el)).join(' | '); return type.array ? `(${stringTypes})[]` : stringTypes; } else if (typeof type === 'string') { return type; } return type.name; }; const getErrorMessage = (propertyName, keyType, types, each) => { const recordValueType = types.map((type) => getTypeName(type)).join(' | '); const singleRecordType = `Record<${keyType}, ${recordValueType}>`; return `Object ${propertyName} is not compliant to type ${singleRecordType}${each ? '[]' : ''}`; }; function IsRecord(allowedRecordType, validationOptions) { return (object, propertyName) => { const types = Array.isArray(allowedRecordType) ? allowedRecordType : [allowedRecordType]; const keyType = (validationOptions === null || validationOptions === void 0 ? void 0 : validationOptions.key) || 'string'; (0, class_validator_1.registerDecorator)({ name: 'isRecord', target: object.constructor, propertyName, constraints: [], options: { message: () => getErrorMessage(propertyName, keyType, types, validationOptions === null || validationOptions === void 0 ? void 0 : validationOptions.each), ...validationOptions, }, validator: { async validate(value) { if (!value) { return false; } const objectKeys = Object.keys(value); if (!areKeysValid(objectKeys, keyType)) { return false; } const valuesToCheck = (validationOptions === null || validationOptions === void 0 ? void 0 : validationOptions.each) && Array.isArray(value) ? value.flatMap((obj) => Object.values(obj)) : Object.values(value); const results = await Promise.all(valuesToCheck.map((obj) => isOneOfTypes(types, obj))); return results.reduce((acc, el) => acc && el, true); }, }, }); }; } exports.IsRecord = IsRecord; //# sourceMappingURL=is-record.decorator.js.map