UNPKG

@storable/model

Version:

Base class providing typed properties, validation and serialization

194 lines (156 loc) 4.64 kB
"use strict"; exports.__esModule = true; exports.Field = void 0; var _util = require("@storable/util"); var _isEmpty = _interopRequireDefault(require("lodash/isEmpty")); var _compact = _interopRequireDefault(require("lodash/compact")); var _serialization = require("./serialization"); var _validation = require("./validation"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class Field { constructor(name, type, { default: defaultValue, validators = [], serializedName } = {}) { if (typeof name !== 'string' || !name) { throw new Error("'name' parameter is missing or invalid"); } if (typeof type !== 'string' || !type) { throw new Error("'type' parameter is missing or invalid"); } if (!Array.isArray(validators)) { throw new Error(`'validators' option must be an array (field: '${name}')`); } validators = validators.map(validator => (0, _util.mapFromOneOrMany)(validator, validator => (0, _validation.normalizeValidator)(validator, { fieldName: name }))); this.name = name; this.serializedName = serializedName || name; this.type = type; let scalarType; let scalarIsOptional; let scalarValidators; const isArray = type.endsWith('[]'); if (isArray) { if (type.includes('?')) { throw new Error(`An array type cannot be optional (field: '${name}')`); } scalarType = type.slice(0, -2); const index = validators.findIndex(validator => Array.isArray(validator)); if (index !== -1) { scalarValidators = validators[index]; validators.splice(index, 1); } else { scalarValidators = []; } } else { scalarType = type; scalarValidators = validators; validators = []; if (scalarType.endsWith('?')) { scalarIsOptional = true; scalarType = scalarType.slice(0, -1); } } this.scalar = new Scalar(scalarType, { isOptional: scalarIsOptional, validators: scalarValidators }); this.validators = validators; this.isArray = isArray; if (defaultValue !== undefined) { this.default = defaultValue; } } createValue(value, { registry, isDeserializing }) { value = (0, _serialization.normalizeValue)(value, { fieldName: this.name }); if (value === undefined) { return undefined; } if (this.isArray && !Array.isArray(value)) { throw new Error(`Type mismatch (field: '${this.name}', expected: 'Array', provided: '${typeof value}')`); } return (0, _util.mapFromOneOrMany)(value, value => this.scalar.createValue(value, { registry, fieldName: this.name, isDeserializing })); } serializeValue(value, { filter, _level }) { return (0, _util.mapFromOneOrMany)(value, value => this.scalar.serializeValue(value, { filter, _level })); } validateValue(value) { if (this.isArray) { const values = value; let failedValidators = (0, _validation.runValidators)(values, this.validators); const failedScalarValidators = values.map(value => this.scalar.validateValue(value)); if (!(0, _isEmpty.default)((0, _compact.default)(failedScalarValidators))) { if (!failedValidators) { failedValidators = []; } failedValidators.push(failedScalarValidators); } return failedValidators; } return this.scalar.validateValue(value); } } exports.Field = Field; class Scalar { constructor(type, { isOptional, validators }) { if (typeof type !== 'string' || !type) { throw new Error("'type' parameter is missing or invalid"); } this.type = type; this.isOptional = isOptional; this.validators = validators; } createValue(value, { registry, fieldName, isDeserializing }) { return (0, _serialization.createValue)(value, { expectedType: this.type, registry, fieldName, isDeserializing }); } serializeValue(value, { filter, _level }) { return (0, _serialization.serializeValue)(value, { filter, _level }); } validateValue(value) { if (value === undefined) { if (!this.isOptional) { return [_validation.REQUIRED_VALIDATOR_NAME]; } return undefined; } if (value.isOfType && value.isOfType('Model')) { return value.constructor.fieldValueIsSubmodel(value) ? value.getFailedValidators() : undefined; } return (0, _validation.runValidators)(value, this.validators); } }