Skip to content

Commit 597daa3

Browse files
committed
Add Almanac addFact method
The addFact method is stright from the engine class. It's able to either add a fact with a name and value / implementation or add a fact as a fact subclass.
1 parent 0de797c commit 597daa3

File tree

5 files changed

+79
-3
lines changed

5 files changed

+79
-3
lines changed

Diff for: docs/almanac.md

+21
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* [Overview](#overview)
44
* [Methods](#methods)
55
* [almanac.factValue(Fact fact, Object params, String path) -> Promise](#almanacfactvaluefact-fact-object-params-string-path---promise)
6+
* [almanac.addFact(String id, Function [definitionFunc], Object [options])](#almanacaddfactstring-id-function-definitionfunc-object-options)
67
* [almanac.addRuntimeFact(String factId, Mixed value)](#almanacaddruntimefactstring-factid-mixed-value)
78
* [almanac.getEvents(String outcome) -> Events[]](#almanacgeteventsstring-outcome---events)
89
* [almanac.getResults() -> RuleResults[]](#almanacgetresults---ruleresults)
@@ -33,8 +34,28 @@ almanac
3334
.then( value => console.log(value))
3435
```
3536

37+
### almanac.addFact(String id, Function [definitionFunc], Object [options])
38+
39+
Sets a fact in the almanac. Used in conjunction with rule and engine event emissions.
40+
41+
```js
42+
// constant facts:
43+
engine.addFact('speed-of-light', 299792458)
44+
45+
// facts computed via function
46+
engine.addFact('account-type', function getAccountType(params, almanac) {
47+
// ...
48+
})
49+
50+
// facts with options:
51+
engine.addFact('account-type', function getAccountType(params, almanac) {
52+
// ...
53+
}, { cache: false, priority: 500 })
54+
```
55+
3656
### almanac.addRuntimeFact(String factId, Mixed value)
3757

58+
**Deprecated** Use `almanac.addFact` instead
3859
Sets a constant fact mid-run. Often used in conjunction with rule and engine event emissions.
3960

4061
```js

Diff for: examples/07-rule-chaining.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,16 @@ async function start () {
3939
event: { type: 'drinks-screwdrivers' },
4040
priority: 10, // IMPORTANT! Set a higher priority for the drinkRule, so it runs first
4141
onSuccess: async function (event, almanac) {
42-
almanac.addRuntimeFact('screwdriverAficionado', true)
42+
almanac.addFact('screwdriverAficionado', true)
4343

4444
// asychronous operations can be performed within callbacks
4545
// engine execution will not proceed until the returned promises is resolved
4646
const accountId = await almanac.factValue('accountId')
4747
const accountInfo = await getAccountInformation(accountId)
48-
almanac.addRuntimeFact('accountInfo', accountInfo)
48+
almanac.addFact('accountInfo', accountInfo)
4949
},
5050
onFailure: function (event, almanac) {
51-
almanac.addRuntimeFact('screwdriverAficionado', false)
51+
almanac.addFact('screwdriverAficionado', false)
5252
}
5353
}
5454
engine.addRule(drinkRule)

Diff for: src/almanac.js

+24
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,32 @@ export default class Almanac {
103103
return factValue
104104
}
105105

106+
/**
107+
* Add a fact definition to the engine. Facts are called by rules as they are evaluated.
108+
* @param {object|Fact} id - fact identifier or instance of Fact
109+
* @param {function} definitionFunc - function to be called when computing the fact value for a given rule
110+
* @param {Object} options - options to initialize the fact with. used when "id" is not a Fact instance
111+
*/
112+
addFact (id, valueOrMethod, options) {
113+
let factId = id
114+
let fact
115+
if (id instanceof Fact) {
116+
factId = id.id
117+
fact = id
118+
} else {
119+
fact = new Fact(id, valueOrMethod, options)
120+
}
121+
debug(`almanac::addFact id:${factId}`)
122+
this.factMap.set(factId, fact)
123+
if (fact.isConstant()) {
124+
this._setFactValue(fact, {}, fact.value)
125+
}
126+
return this
127+
}
128+
106129
/**
107130
* Adds a constant fact during runtime. Can be used mid-run() to add additional information
131+
* @deprecated use addFact
108132
* @param {String} fact - fact identifier
109133
* @param {Mixed} value - constant value of the fact
110134
*/

Diff for: test/almanac.test.js

+25
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,31 @@ describe('Almanac', () => {
4141
})
4242
})
4343

44+
describe('addFact', () => {
45+
it('supports runtime facts as key => values', () => {
46+
almanac = new Almanac()
47+
almanac.addFact('fact1', 3)
48+
return expect(almanac.factValue('fact1')).to.eventually.equal(3)
49+
})
50+
51+
it('supporrts runtime facts as dynamic callbacks', async () => {
52+
almanac = new Almanac()
53+
almanac.addFact('fact1', () => {
54+
factSpy()
55+
return Promise.resolve(3)
56+
})
57+
await expect(almanac.factValue('fact1')).to.eventually.equal(3)
58+
await expect(factSpy).to.have.been.calledOnce()
59+
})
60+
61+
it('supports runtime fact instances', () => {
62+
const fact = new Fact('fact1', 3)
63+
almanac = new Almanac()
64+
almanac.addFact(fact)
65+
return expect(almanac.factValue('fact1')).to.eventually.equal(fact.value)
66+
})
67+
})
68+
4469
describe('addEvent() / getEvents()', () => {
4570
const event = {};
4671
['success', 'failure'].forEach(outcome => {

Diff for: types/index.d.ts

+6
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ export class Almanac {
7171
params?: Record<string, any>,
7272
path?: string
7373
): Promise<T>;
74+
addFact<T>(fact: Fact<T>): this;
75+
addFact<T>(
76+
id: string,
77+
valueCallback: DynamicFactCallback<T> | T,
78+
options?: FactOptions
79+
): this;
7480
addRuntimeFact(factId: string, value: any): void;
7581
}
7682

0 commit comments

Comments
 (0)