@yamamotok/dataobject
Version:
Decorator based JSON serializer and deserializer.
78 lines • 3.71 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Factory = void 0;
const factoryValueTransform_1 = require("./transformer/factoryValueTransform");
const getDescriptor_1 = require("./utils/getDescriptor");
const inContext_1 = require("./utils/inContext");
const validate_1 = require("./validator/validate");
const DataObjectError_1 = require("./DataObjectError");
const Decorator_1 = require("./Decorator");
const ValidationError_1 = require("./ValidationError");
class Factory {
/**
* Create factory method.
* @param ctor the class
*
* Note: Avoid using `this` in this method.
*/
static createFactory(ctor) {
return (_source, _context) => {
const newObj = new ctor();
const source = (_source || {});
const properties = Decorator_1.Decorator.getPropertyMap(newObj);
if (!properties) {
throw new DataObjectError_1.DataObjectError('Implementation error, no decorated properties');
}
properties.forEach((options, _key) => {
const context = _context || Factory.DefaultContext;
const key = _key;
// Probably the property is just "getter".
const newObjDescriptor = (0, getDescriptor_1.getDescriptor)(newObj, key);
if (newObjDescriptor && !newObjDescriptor.writable && !newObjDescriptor.set) {
return;
}
// Check if the given value to factory should be processed.
// - It will be ignored if the value is `undefined`.
// - `DataObjectError` will be thrown in case no value was given for `required()` decorated property.
if (source[key] === undefined) {
if (options === null || options === void 0 ? void 0 : options.required) {
throw new DataObjectError_1.DataObjectError(`Required property "${key}" is missing`);
}
return;
}
// Skip property which is out of context
if (!(0, inContext_1.inContext)(context, options === null || options === void 0 ? void 0 : options.context)) {
return;
}
// Transform value
const transformedValue = (0, factoryValueTransform_1.factoryValueTransform)({
key,
sourceValue: source[key],
context,
options,
});
newObj[key] = transformedValue;
});
// Validation should be applied after the instance was created.
const validationErrors = [];
properties.forEach((options, _key) => {
const context = _context || Factory.DefaultContext;
const key = _key;
if (!(0, inContext_1.inContext)(context, options === null || options === void 0 ? void 0 : options.context)) {
return;
}
const validationError = (0, validate_1.validate)({ key, targetValue: newObj[key], options, context });
if (validationError) {
validationErrors.push(validationError);
}
});
if (validationErrors.length > 0) {
throw new ValidationError_1.ValidationError('Validation failed', validationErrors);
}
return newObj;
};
}
}
exports.Factory = Factory;
Factory.DefaultContext = 'factory';
//# sourceMappingURL=Factory.js.map