@commodo/fields
Version:
Enables defining rich data models by decorating function instances with specified model fields. Additionally, it adds `populate` and `validate` methods, for populating model instances with data, and then validating it, respectively.
160 lines (126 loc) • 4.22 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _repropose = require("repropose");
var _fields = require("@commodo/fields");
const withFields = fields => {
return baseFn => {
let fn = (0, _repropose.withProps)(props => {
if (props.__withFields) {
return {};
}
return {
__withFields: {
fields: {},
processing: {
validation: false,
dirty: false
}
},
getFields() {
return this.__withFields.fields;
},
getField(name) {
return this.__withFields.fields[name];
},
populate(data) {
if (data && typeof data === "object") {
const values = this.getFields();
for (let valueKey in values) {
const value = values[valueKey];
if (!value || value.skipOnPopulate || !(valueKey in data)) {
continue;
}
values[valueKey].setValue(data[valueKey]);
}
}
return this;
},
async validate() {
if (this.__withFields.processing.validation) {
return;
}
this.__withFields.processing.validation = true;
const invalidFields = {};
const fields = this.getFields();
for (let name in fields) {
const field = fields[name];
try {
await field.validate();
} catch (e) {
invalidFields[name] = {
code: e.code || _fields.WithFieldsError.VALIDATION_FAILED_INVALID_FIELD,
data: e.data || null,
message: e.message
};
}
}
this.__withFields.processing.validation = false;
if (Object.keys(invalidFields).length > 0) {
throw new _fields.WithFieldsError("Validation failed.", _fields.WithFieldsError.VALIDATION_FAILED_INVALID_FIELDS, {
invalidFields
});
}
},
clean() {
const values = this.getFields();
for (let valueKey in values) {
const value = values[valueKey];
value && value.isDirty() && value.clean();
}
},
isDirty() {
if (this.__withFields.processing.dirty) {
return false;
}
this.__withFields.processing.dirty = true;
const fields = this.getFields();
for (let valueKey in fields) {
const field = fields[valueKey];
if (field && field.isDirty()) {
this.__withFields.processing.dirty = false;
return true;
}
}
this.__withFields.processing.dirty = false;
return false;
}
};
})(baseFn);
fn = (0, _repropose.withProps)(instance => {
let fieldsList = fields;
if (typeof fields === "function") {
fieldsList = fields(instance);
}
for (let newFieldName in fieldsList) {
const valueFactory = fieldsList[newFieldName];
instance.__withFields.fields[newFieldName] = new valueFactory(newFieldName, instance);
Object.defineProperty(instance, newFieldName, {
get() {
if (this.__withFields.fields[newFieldName].get) {
return this.__withFields.fields[newFieldName].get.call(this, this.__withFields.fields[newFieldName]);
}
return this.__withFields.fields[newFieldName].getValue();
},
set(value) {
if (this.__withFields.fields[newFieldName].set) {
this.__withFields.fields[newFieldName].set.call(this, this.__withFields.fields[newFieldName], value);
} else {
this.__withFields.fields[newFieldName].setValue(value);
}
}
});
}
return {};
})(fn);
fn = (0, _repropose.withStaticProps)({
__withFields: true // For satisfying hasFields helper function.
})(fn);
return fn;
};
};
var _default = withFields;
exports.default = _default;
//# sourceMappingURL=withFields.js.map