UNPKG

6.25 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _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; };
8
9var _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; }; }();
10
11var _fact = require('./fact');
12
13var _fact2 = _interopRequireDefault(_fact);
14
15var _errors = require('./errors');
16
17var _debug = require('./debug');
18
19var _debug2 = _interopRequireDefault(_debug);
20
21var _selectn = require('selectn');
22
23var _selectn2 = _interopRequireDefault(_selectn);
24
25var _lodash = require('lodash.isobjectlike');
26
27var _lodash2 = _interopRequireDefault(_lodash);
28
29function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
30
31function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
32
33/**
34 * Fact results lookup
35 * Triggers fact computations and saves the results
36 * A new almanac is used for every engine run()
37 */
38var Almanac = function () {
39 function Almanac(factMap) {
40 var runtimeFacts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
41
42 _classCallCheck(this, Almanac);
43
44 this.factMap = new Map(factMap);
45 this.factResultsCache = new Map(); // { cacheKey: Promise<factValu> }
46
47 for (var factId in runtimeFacts) {
48 var fact = void 0;
49 if (runtimeFacts[factId] instanceof _fact2.default) {
50 fact = runtimeFacts[factId];
51 } else {
52 fact = new _fact2.default(factId, runtimeFacts[factId]);
53 }
54
55 this._addConstantFact(fact);
56 (0, _debug2.default)('almanac::constructor initialized runtime fact:' + fact.id + ' with ' + fact.value + '<' + _typeof(fact.value) + '>');
57 }
58 }
59
60 /**
61 * Retrieve fact by id, raising an exception if it DNE
62 * @param {String} factId
63 * @return {Fact}
64 */
65
66
67 _createClass(Almanac, [{
68 key: '_getFact',
69 value: function _getFact(factId) {
70 return this.factMap.get(factId);
71 }
72
73 /**
74 * Registers fact with the almanac
75 * @param {[type]} fact [description]
76 */
77
78 }, {
79 key: '_addConstantFact',
80 value: function _addConstantFact(fact) {
81 this.factMap.set(fact.id, fact);
82 this._setFactValue(fact, {}, fact.value);
83 }
84
85 /**
86 * Sets the computed value of a fact
87 * @param {Fact} fact
88 * @param {Object} params - values for differentiating this fact value from others, used for cache key
89 * @param {Mixed} value - computed value
90 */
91
92 }, {
93 key: '_setFactValue',
94 value: function _setFactValue(fact, params, value) {
95 var cacheKey = fact.getCacheKey(params);
96 var factValue = Promise.resolve(value);
97 if (cacheKey) {
98 this.factResultsCache.set(cacheKey, factValue);
99 }
100 return factValue;
101 }
102
103 /**
104 * Adds a constant fact during runtime. Can be used mid-run() to add additional information
105 * @param {String} fact - fact identifier
106 * @param {Mixed} value - constant value of the fact
107 */
108
109 }, {
110 key: 'addRuntimeFact',
111 value: function addRuntimeFact(factId, value) {
112 var fact = new _fact2.default(factId, value);
113 return this._addConstantFact(fact);
114 }
115
116 /**
117 * Returns the value of a fact, based on the given parameters. Utilizes the 'almanac' maintained
118 * by the engine, which cache's fact computations based on parameters provided
119 * @param {string} factId - fact identifier
120 * @param {Object} params - parameters to feed into the fact. By default, these will also be used to compute the cache key
121 * @param {String} path - object
122 * @return {Promise} a promise which will resolve with the fact computation.
123 */
124
125 }, {
126 key: 'factValue',
127 value: function factValue(factId) {
128 var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
129 var path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
130
131 var factValuePromise = void 0;
132 var fact = this._getFact(factId);
133 if (fact === undefined) {
134 return Promise.reject(new _errors.UndefinedFactError('Undefined fact: ' + factId));
135 }
136 if (fact.isConstant()) {
137 factValuePromise = Promise.resolve(fact.calculate(params, this));
138 } else {
139 var cacheKey = fact.getCacheKey(params);
140 var cacheVal = cacheKey && this.factResultsCache.get(cacheKey);
141 if (cacheVal) {
142 factValuePromise = Promise.resolve(cacheVal);
143 (0, _debug2.default)('almanac::factValue cache hit for fact:' + factId);
144 } else {
145 (0, _debug2.default)('almanac::factValue cache miss for fact:' + factId + '; calculating');
146 factValuePromise = this._setFactValue(fact, params, fact.calculate(params, this));
147 }
148 }
149 if (path) {
150 return factValuePromise.then(function (factValue) {
151 if ((0, _lodash2.default)(factValue)) {
152 var pathValue = (0, _selectn2.default)(path)(factValue);
153 (0, _debug2.default)('condition::evaluate extracting object property ' + path + ', received: ' + pathValue);
154 return pathValue;
155 } else {
156 (0, _debug2.default)('condition::evaluate could not compute object path(' + path + ') of non-object: ' + factValue + ' <' + (typeof factValue === 'undefined' ? 'undefined' : _typeof(factValue)) + '>; continuing with ' + factValue);
157 return factValue;
158 }
159 });
160 }
161 return factValuePromise;
162 }
163 }]);
164
165 return Almanac;
166}();
167
168exports.default = Almanac;
\No newline at end of file