UNPKG

tsbase

Version:

Base class libraries for TypeScript

175 lines 7.63 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EventStore = exports.NoTransactionToRedo = exports.NoTransactionToUndo = exports.StateChangeUnnecessary = void 0; var tslib_1 = require("tslib"); var dlv_1 = tslib_1.__importDefault(require("dlv")); var dset_1 = require("dset"); var Queryable_1 = require("../../Collections/Queryable/Queryable"); var Strings_1 = require("../../System/Strings"); var Query_1 = require("../CommandQuery/Query"); var Observable_1 = require("../Observable/Observable"); exports.StateChangeUnnecessary = 'State change unnecessary - nothing changed'; exports.NoTransactionToUndo = 'No transaction to undo'; exports.NoTransactionToRedo = 'No transaction to redo'; var EventStore = /** @class */ (function () { function EventStore(state) { this.state = state; this.stateObservers = new Map(); this.ledger = new Array(); } EventStore.prototype.GetState = function (member) { if (typeof member === 'string') { return this.getStateAtPath(member); } var clone = this.cloneOf(this.state); return member ? member(clone) : clone; }; EventStore.prototype.SetState = function (memberOrState, state) { var _this = this; return new Query_1.Query(function () { var isGranularUpdate = ['function', 'string'].includes(typeof memberOrState) && state !== undefined; var getCurrentState = function () { if (isGranularUpdate && typeof memberOrState === 'function') { return memberOrState(_this.cloneOf(_this.state)); } else if (isGranularUpdate && typeof memberOrState === 'string') { return _this.getStateAtPath(memberOrState); } else { return _this.cloneOf(_this.state); } }; var newState = isGranularUpdate ? state : memberOrState; if (JSON.stringify(getCurrentState()) !== JSON.stringify(newState)) { _this.updateState(isGranularUpdate ? memberOrState : Strings_1.Strings.Empty, getCurrentState(), newState); } else { throw new Error(exports.StateChangeUnnecessary); } return getCurrentState(); }).Execute(); }; EventStore.prototype.ObservableAt = function (member) { var path = typeof member === 'string' ? member : this.getPathFromMemberFunction(member); if (!this.stateObservers.has(path)) { this.stateObservers.set(path, new Observable_1.Observable()); } ; return this.stateObservers.get(path); }; EventStore.prototype.GetLedger = function () { return this.ledger.slice(); }; EventStore.prototype.Undo = function () { var _this = this; return new Query_1.Query(function () { var queryableLedger = Queryable_1.Queryable.From(_this.ledger); var lastVoidableTransaction = queryableLedger.Last(function (t) { return !t.voided; }); if (lastVoidableTransaction) { lastVoidableTransaction.voided = true; _this.updateState(lastVoidableTransaction.path, lastVoidableTransaction.toState, lastVoidableTransaction.fromState, false); } else { throw new Error(exports.NoTransactionToUndo); } return _this.getStateAtPath(lastVoidableTransaction.path); }).Execute(); }; EventStore.prototype.Redo = function () { var _this = this; return new Query_1.Query(function () { var lastRedoableTransaction = null; for (var index = _this.ledger.length - 1; index >= 0; index--) { var element = _this.ledger[index]; if (!element.voided) { break; } else { lastRedoableTransaction = element; } } if (lastRedoableTransaction) { lastRedoableTransaction.voided = false; _this.updateState(lastRedoableTransaction.path, lastRedoableTransaction.fromState, lastRedoableTransaction.toState, false); } else { throw new Error(exports.NoTransactionToRedo); } return _this.getStateAtPath(lastRedoableTransaction.path); }).Execute(); }; EventStore.prototype.cloneOf = function (value) { return value ? JSON.parse(JSON.stringify(value)) : value; }; EventStore.prototype.getPathFromMemberFunction = function (member) { var regex = /[.][a-zA-Z0-9]*/g; var path = Strings_1.Strings.Empty; if (member) { var match = void 0; while ((match = regex.exec(member.toString())) !== null) { var matchValue = path.length ? match[0] : match[0].replace('.', Strings_1.Strings.Empty); path += matchValue; } } return path; }; EventStore.prototype.getStateAtPath = function (path) { return this.cloneOf((0, dlv_1.default)(this.state, path)); }; EventStore.prototype.updateState = function (member, previousState, value, updateLedger) { if (updateLedger === void 0) { updateLedger = true; } if (typeof member !== 'string') { member = this.getPathFromMemberFunction(member); } if (updateLedger) { this.ledger.push({ path: member, timestamp: Date.now(), toState: this.cloneOf(value), fromState: previousState, voided: false }); } var rootUpdate = Strings_1.Strings.IsEmptyOrWhiteSpace(member.toString()); if (rootUpdate) { this.state = value; } else { (0, dset_1.dset)(this.state, member.toString(), value); } this.publishToDependentObservers(member); }; EventStore.prototype.publishToDependentObservers = function (path) { var _this = this; var targetObserverKeys = this.getTargetObservers(path); targetObserverKeys.forEach(function (key) { _this.stateObservers.get(key).Publish(Strings_1.Strings.IsEmptyOrWhiteSpace(key) ? _this.GetState() : _this.cloneOf((0, dlv_1.default)(_this.state, key))); }); }; EventStore.prototype.getTargetObservers = function (path) { var _this = this; var observerKeys = Array.from(this.stateObservers.keys()); return Strings_1.Strings.IsEmptyOrWhiteSpace(path) ? observerKeys : observerKeys.filter(function (k) { return k === Strings_1.Strings.Empty || k === path || _this.childOf(k, path) || _this.parentOf(k, path); }); }; EventStore.prototype.childOf = function (parentPath, childPath) { return parentPath.startsWith("".concat(childPath, ".")) || parentPath.startsWith(".".concat(childPath)) || parentPath.indexOf(".".concat(childPath, ".")) >= 0; }; EventStore.prototype.parentOf = function (parentPath, childPath) { return childPath.startsWith("".concat(parentPath, ".")) || childPath.startsWith(".".concat(parentPath)) || childPath.indexOf(".".concat(parentPath, ".")) >= 0; }; return EventStore; }()); exports.EventStore = EventStore; //# sourceMappingURL=EventStore.js.map