Skip to content

Commit 6c0ad2a

Browse files
committed
migrated to typescript, updated the readme and added more examples
1 parent 7d7799d commit 6c0ad2a

36 files changed

+2668
-1870
lines changed

.eslintrc.yml

Lines changed: 0 additions & 20 deletions
This file was deleted.

README.md

Lines changed: 215 additions & 227 deletions
Large diffs are not rendered by default.

eslint.config.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use strict';
2+
3+
import parser from '@typescript-eslint/parser';
4+
import plugin from '@typescript-eslint/eslint-plugin';
5+
6+
export default [
7+
{
8+
files: ['**/*.ts'],
9+
languageOptions: {
10+
parser,
11+
ecmaVersion: 'latest',
12+
sourceType: 'module',
13+
globals: {
14+
describe: 'readonly',
15+
it: 'readonly',
16+
before: 'readonly',
17+
after: 'readonly',
18+
beforeEach: 'readonly',
19+
afterEach: 'readonly'
20+
}
21+
},
22+
plugins: {
23+
'@typescript-eslint': plugin
24+
},
25+
rules: {
26+
indent: ['error', 4],
27+
'linebreak-style': ['error', 'unix'],
28+
quotes: ['error', 'single'],
29+
semi: ['error', 'always']
30+
}
31+
},
32+
{
33+
ignores: ['node_modules/', 'dist/', 'coverage/']
34+
}
35+
];
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Example 1: High-spending customer discount
3+
* Run from project root: node examples/01-high-spending-discount.mjs
4+
* (Run "npm run build" first.)
5+
*/
6+
import { Fact, Condition, Conditions, Rule, RuleEngine } from '../dist/index.js';
7+
8+
const transactionFact = new Fact('transaction');
9+
transactionFact.setFact = { amount: 600 };
10+
const customerStatusFact = new Fact('customer_status');
11+
customerStatusFact.setFact = { status: 'gold' };
12+
13+
const condition1 = new Condition();
14+
condition1.fact('transaction').operator('greaterThan').value(500).path('amount');
15+
const condition2 = new Condition();
16+
condition2.fact('customer_status').operator('equal').value('gold').path('status');
17+
18+
const conditions = new Conditions('promoEligibility');
19+
conditions.all([condition1.getCondition, condition2.getCondition]);
20+
21+
const rule = new Rule('applyDiscount');
22+
rule.conditions('promoEligibility')
23+
.event('discount', { discount: 10 })
24+
.priority(1)
25+
.onSuccess(() => console.log('Discount applied successfully'))
26+
.onFailure(() => console.log('Discount could not be applied'));
27+
28+
const ruleEngine = new RuleEngine();
29+
const results = await ruleEngine.run();
30+
console.log('Events:', results.events.length);
31+
console.log('First event type:', results.events[0]?.type);
32+
console.log('OK: High-spending discount example passed.\n');

examples/02-action-arithmetic.mjs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* Example 2: Action arithmetic and run()
3+
* Run: node examples/02-action-arithmetic.mjs
4+
*/
5+
import { Action } from '../dist/index.js';
6+
7+
const data = { price: 100, taxRate: 0.2 };
8+
const params = { action: 'multiply', value: 0.2, dataPath: 'price' };
9+
const action = new Action(data, params);
10+
11+
// Compute tax: price * taxRate via run() (uses params.action, params.value, params.dataPath)
12+
const result = await action.run();
13+
console.log('Tax (100 * 0.2):', result);
14+
console.log(result === 20 ? 'OK: Action arithmetic example passed.\n' : 'FAIL');

examples/03-date-difference.mjs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* Example 3: Date difference (numberOfDays, numberOfWeeks, numberOfMonths, numberOfYears)
3+
* Run: node examples/03-date-difference.mjs
4+
*/
5+
import { Action } from '../dist/index.js';
6+
7+
const action = new Action(
8+
{ dummy: 1 },
9+
{ action: 'numberOfDays', value: null, dataPath: 'dummy' }
10+
);
11+
12+
action.numberOfDays('2023-01-01', '2023-01-10');
13+
console.log('Days between 2023-01-01 and 2023-01-10:', action.getResult);
14+
console.log(action.getResult === 9 ? 'OK: numberOfDays passed.' : 'FAIL');
15+
16+
action.numberOfMonths('2023-01-01', '2024-01-01');
17+
console.log('Months between 2023-01-01 and 2024-01-01:', action.getResult);
18+
console.log(action.getResult === 12 ? 'OK: numberOfMonths passed.' : 'FAIL');
19+
20+
action.numberOfYears('2020-01-01', '2024-01-01');
21+
console.log('Years between 2020 and 2024:', action.getResult);
22+
console.log(action.getResult === 4 ? 'OK: Date difference example passed.\n' : 'FAIL');

examples/04-boolean-action.mjs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Example 4: Boolean actions (true() and false())
3+
* Run: node examples/04-boolean-action.mjs
4+
*/
5+
import { Action } from '../dist/index.js';
6+
7+
const action = new Action(
8+
{ x: 1 },
9+
{ action: 'true', value: null, dataPath: 'x' }
10+
);
11+
action.true();
12+
console.log('action.true() result:', action.getResult);
13+
console.log(action.getResult === true ? 'OK: true() passed.' : 'FAIL');
14+
15+
action.false();
16+
console.log('action.false() result:', action.getResult);
17+
console.log(action.getResult === false ? 'OK: Boolean action example passed.\n' : 'FAIL');

examples/05-or-conditions.mjs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Example 5: OR conditions (any) — rule fires if status is gold OR silver
3+
* Run: node examples/05-or-conditions.mjs
4+
*/
5+
import { Fact, Condition, Conditions, Rule, RuleEngine } from '../dist/index.js';
6+
7+
const fact = new Fact('customer_status');
8+
fact.setFact = { status: 'silver' }; // Not gold; silver qualifies with "any"
9+
10+
const condGold = new Condition();
11+
condGold.fact('customer_status').operator('equal').value('gold').path('status');
12+
const condSilver = new Condition();
13+
condSilver.fact('customer_status').operator('equal').value('silver').path('status');
14+
15+
const conditions = new Conditions('premiumStatus');
16+
conditions.any([condGold.getCondition, condSilver.getCondition]);
17+
18+
const rule = new Rule('premiumAccess');
19+
rule.conditions('premiumStatus')
20+
.event('grantAccess', { level: 'premium' })
21+
.priority(1)
22+
.onSuccess(() => console.log('Premium access granted (gold or silver).'))
23+
.onFailure(() => console.log('Access denied.'));
24+
25+
const ruleEngine = new RuleEngine();
26+
const results = await ruleEngine.run();
27+
console.log('Events:', results.events.length, results.events[0]?.type);
28+
console.log(results.events.length === 1 && results.events[0].type === 'grantAccess'
29+
? 'OK: OR conditions example passed.\n' : 'FAIL');

examples/06-rule-failure.mjs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Example 6: Rule that does not fire (onFailure) — amount too low
3+
* Run: node examples/06-rule-failure.mjs
4+
*/
5+
import { Fact, Condition, Conditions, Rule, RuleEngine } from '../dist/index.js';
6+
7+
const transactionFact = new Fact('transaction');
8+
transactionFact.setFact = { amount: 100 }; // Below 500
9+
10+
const condition1 = new Condition();
11+
condition1.fact('transaction').operator('greaterThan').value(500).path('amount');
12+
13+
const conditions = new Conditions('noDiscountEligibility');
14+
conditions.all([condition1.getCondition]);
15+
16+
const rule = new Rule('noDiscount');
17+
rule.conditions('noDiscountEligibility')
18+
.event('discount', { discount: 0 })
19+
.priority(1)
20+
.onSuccess(() => console.log('Discount applied'))
21+
.onFailure(() => console.log('Discount could not be applied (amount too low)'));
22+
23+
const ruleEngine = new RuleEngine();
24+
const results = await ruleEngine.run();
25+
console.log('Events fired:', results.events.length);
26+
console.log(results.events.length === 0 ? 'OK: Rule failure (onFailure) example passed.\n' : 'FAIL');

examples/07-api-request.mjs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Example 7: HTTP request (Action with a public API)
3+
* Run: node examples/07-api-request.mjs
4+
* Uses JSONPlaceholder (https://jsonplaceholder.typicode.com) - no auth required.
5+
*/
6+
import { Action } from '../dist/index.js';
7+
8+
const action = new Action(
9+
{ dummy: 1 },
10+
{ action: 'request', value: null, dataPath: 'dummy' }
11+
);
12+
13+
action.setUrl = 'https://jsonplaceholder.typicode.com/posts/1';
14+
action.setMethod = 'GET';
15+
action.setHeaders = {};
16+
17+
await action.request('post', {});
18+
19+
const result = action.getResult;
20+
const byName = action.getData.requestData?.post;
21+
22+
console.log('GET https://jsonplaceholder.typicode.com/posts/1');
23+
console.log('Response (getResult):', typeof result === 'object' && result !== null ? { ...result } : result);
24+
console.log('Response (requestData.post):', typeof byName === 'object' && byName !== null ? { ...byName } : byName);
25+
26+
const ok = result && typeof result === 'object' && 'id' in result && result.id === 1 && 'title' in result;
27+
console.log(ok ? 'OK: API request example passed.\n' : 'FAIL');

0 commit comments

Comments
 (0)