@storable/model
Version:
Base class providing typed properties, validation and serialization
194 lines (156 loc) • 4.64 kB
JavaScript
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);
}
}
;