UNPKG

decode-it

Version:

a simple zero-dependency type safe json decoder for typescript

94 lines 3.82 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createDecoder = exports.getFailedDecodes = void 0; const constructErrorPath_1 = require("./constructErrorPath"); const errorFormatter_1 = require("./errorFormatter"); const typeCheckers_1 = require("./typeCheckers"); const utils_1 = require("./utils"); require("./validators/ValidationResult"); require("./validators/Validator"); class DecodeError extends Error { constructor(message) { super(message); this.name = '\nDecode Error'; } } const isValidationResult = (arg) => { if (!typeCheckers_1.isObject(arg)) return false; if (arg.state !== 'failed' && arg.state !== 'passed') return false; return true; }; const concatNestedErrors = (errorsSources, currentKey) => errorsSources.map(errorSource => ({ ...errorSource, path: `${currentKey}.${errorSource.path}`, })); const getFailedDecodes = (schema, json) => { if (typeCheckers_1.isFunction(schema)) { const validate = schema; const result = validate(json); if (result.state === 'failed') return [ { actual: result.value, expectedType: result.type, expectedValue: result.literal, wrapper: result.wrapper, path: result.path, }, ]; } return Object.entries(schema).reduce((errors, [key, validate]) => { const field = json[key]; if (typeCheckers_1.isObject(validate)) { if (!typeCheckers_1.isObject(field)) return errors.concat({ actual: field, expectedType: 'object', path: key, }); const errorsSource = exports.getFailedDecodes(validate, field); const error = concatNestedErrors(errorsSource, key); return errors.concat(error); } const result = validate(field); if (!isValidationResult(result)) return errors.concat({ actual: result, expectedType: 'validator', path: key, }); if (result.state === 'failed') return errors.concat({ actual: result.value, expectedType: result.type, expectedValue: result.literal, wrapper: result.wrapper, path: constructErrorPath_1.constructNestedErrorPath(key, result.path), }); return errors; }, []); }; exports.getFailedDecodes = getFailedDecodes; const createDecoder = (schema) => { if (!typeCheckers_1.isObject(schema) && !typeCheckers_1.isFunction(schema)) throw new DecodeError(`Expected schema to be an object or an array validator but got ${errorFormatter_1.formatToJson(schema)}`); if (typeCheckers_1.isObject(schema)) { const nonFunctionField = utils_1.flatObject(schema).find(([_k, v]) => !typeCheckers_1.isFunction(v)); if (!typeCheckers_1.isUndefined(nonFunctionField)) throw new DecodeError(`Expected schema fields to be an validator or another schema but got ${nonFunctionField[1]} at ${nonFunctionField[0]}`); } return (json) => { if (!typeCheckers_1.isObject(json) && !typeCheckers_1.isArray(json)) throw new DecodeError(`Expected json to be an object but got ${json}`); const failedDecodes = exports.getFailedDecodes(schema, json); const formattedErrors = failedDecodes.map(err => errorFormatter_1.formatFailedDecode(err)); formattedErrors.forEach(msg => { throw new DecodeError(msg); }); return json; }; }; exports.createDecoder = createDecoder; //# sourceMappingURL=decode.js.map