js-abstract-synchronizer
Version:
abstract synchronizer for backend and frontend
215 lines (185 loc) • 8.12 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _InvalidIdError = require('js-abstract-synchronizer/errors/InvalidIdError');
var _InvalidIdError2 = _interopRequireDefault(_InvalidIdError);
var _NotFoundError = require('js-abstract-synchronizer/errors/NotFoundError');
var _NotFoundError2 = _interopRequireDefault(_NotFoundError);
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _addMethods = require('js-abstract-synchronizer/objectManipulation/addMethods');
var _addMethods2 = _interopRequireDefault(_addMethods);
var _uuid = require('uuid');
var _uuid2 = _interopRequireDefault(_uuid);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var privates = Symbol('privates');
var createData = Symbol('createData');
var getDataToSerialize = Symbol('getDataToSerialize');
var addMethodsToThis = Symbol('addMethodsToThis');
var validateId = Symbol('validateId');
var createSerializedData = Symbol('createSerializedData');
exports.default = function (serializer) {
return function () {
function SerializableObject(_ref) {
var object = _ref.object,
prototypeName = _ref.prototypeName;
_classCallCheck(this, SerializableObject);
var id = _lodash2.default.isUndefined(object.id) ? _uuid2.default.v4() : object.id;
this[validateId](id);
this[privates] = {
id: id,
isBeingSaved: false,
prototypeName: prototypeName,
storedData: null
};
this[privates].currentData = this[createData](object);
this[addMethodsToThis](prototypeName);
if (this.validate) {
this.validate(object);
}
}
_createClass(SerializableObject, [{
key: validateId,
value: function value(id) {
if (typeof id !== 'string') {
throw new _InvalidIdError2.default('id must be a string');
}
if (id === '') {
throw new _InvalidIdError2.default('id cannot be empty');
}
}
}, {
key: addMethodsToThis,
value: function value(prototypeName) {
var _this = this;
var proto = serializer.getPrototype(prototypeName);
if (proto) {
(0, _addMethods2.default)({
getTargetInnerObject: function getTargetInnerObject() {
return _this[privates].currentData.data;
},
prototype: proto,
target: this
});
}
}
}, {
key: createData,
value: function value(object) {
return {
data: _lodash2.default.cloneDeep(_lodash2.default.omit(object, 'id')),
id: this[privates].id,
prototypeName: this[privates].prototypeName
};
}
}, {
key: 'saveWithoutReferences',
value: function saveWithoutReferences() {
var _this2 = this;
var data = this[getDataToSerialize]();
return (_lodash2.default.isUndefined(data.prototypeName) ? this.reload().then(function () {
return _this2[getDataToSerialize]();
}) : Promise.resolve(data)).catch(function (error) {
return error instanceof _NotFoundError2.default ? data : Promise.reject(error);
}).then(function (dataToSave) {
return serializer.save(dataToSave);
}).then(function () {
_this2[privates].storedData = _this2[createData](_this2[privates].currentData.data);
_this2[privates].isBeingSaved = false;
});
}
}, {
key: getDataToSerialize,
value: function value() {
return this[createSerializedData](this[privates].currentData);
}
}, {
key: 'save',
value: function save() {
var _this3 = this;
var objectsToSave = [];
_lodash2.default.map(this[privates].currentData.data, function (value, key) {
if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && !(value instanceof SerializableObject && value.isBeingSaved())) {
var child = value instanceof SerializableObject ? value : serializer.create(value);
child.setIsBeingSaved();
objectsToSave.push(child);
_this3[privates].currentData.data[key] = child;
}
});
return Promise.all([this.saveWithoutReferences()].concat(_toConsumableArray(objectsToSave.map(function (object) {
return object.save();
}))));
}
}, {
key: 'reload',
value: function reload() {
var _this4 = this;
return serializer.reload(this[privates].currentData.id).then(function (newObject) {
var filteredObject = _lodash2.default.pick(newObject, ['id', 'data', 'prototypeName']);
var newObjectWithReferences = Object.assign(filteredObject, {
data: _lodash2.default.mapValues(filteredObject.data, function (value, key) {
var oldValue = _this4[privates].currentData.data[key];
return oldValue instanceof SerializableObject && value.id === oldValue.getId() ? oldValue : serializer.create(value);
})
});
_this4[privates].storedData = _lodash2.default.cloneDeep(newObjectWithReferences);
_this4[privates].currentData = _lodash2.default.cloneDeep(newObjectWithReferences);
_this4[addMethodsToThis](filteredObject.prototypeName);
});
}
}, {
key: 'reset',
value: function reset() {
this[privates].currentData = _lodash2.default.cloneDeep(this[privates].storedData);
}
}, {
key: 'isDirty',
value: function isDirty() {
return !_lodash2.default.isEqual(this[privates].currentData, this[privates].storedData);
}
}, {
key: 'setIsBeingSaved',
value: function setIsBeingSaved() {
this[privates].isBeingSaved = true;
}
}, {
key: 'isBeingSaved',
value: function isBeingSaved() {
return this[privates].isBeingSaved;
}
}, {
key: 'getId',
value: function getId() {
return this[privates].id;
}
}, {
key: createSerializedData,
value: function value(data) {
if (!data || !data.data) {
return data;
}
return Object.assign({}, data, {
data: _lodash2.default.mapValues(data.data, function (value) {
return value instanceof SerializableObject ? { id: value.getId() } : value;
})
});
}
}, {
key: 'getSerializedStoredData',
value: function getSerializedStoredData() {
return JSON.stringify(this[createSerializedData](this[privates].storedData));
}
}, {
key: 'getSerializedCurrentData',
value: function getSerializedCurrentData() {
return JSON.stringify(this[createSerializedData](this[privates].currentData));
}
}]);
return SerializableObject;
}();
};