A minimal rules engine (~500 lines) that executes actions based on events. Built with TypeScript — no database, fully in-memory.
Demonstrates data modeling, abstraction, extensibility, and thinking in systems.
npm installnpm run examplenpm testnpm run typecheck| Concept | Description |
|---|---|
| Event | Something that happened: { type, properties } |
| Condition | A predicate on event properties: { field, op, value } |
| ConditionGroup | Conditions combined with AND or OR logic |
| Rule | Wires event type(s) → conditions → actions |
| Action | A side effect to run: { type, params } |
| ActionHandler | A function registered for an action type |
| Operator | Description |
|---|---|
eq |
Strict equality |
neq |
Strict inequality |
gt |
Greater than (numeric) |
gte |
Greater than or equal (numeric) |
lt |
Less than (numeric) |
lte |
Less than or equal (numeric) |
contains |
String substring or array element check |
in |
Value is member of a provided array |
exists |
Field is defined and not null |
import { WorkflowEngine, registerBuiltinActions } from './src/index.js';
const engine = new WorkflowEngine();
registerBuiltinActions(engine);
engine.addRule({
name: 'welcome-trial',
when: 'new_customer',
conditionGroup: {
logic: 'AND',
conditions: [
{ field: 'plan', op: 'eq', value: 'trial' },
],
},
actions: [
{ type: 'log', params: { message: 'New trial customer!' } },
{ type: 'send_email', params: { to: 'user@example.com', subject: 'Welcome!' } },
],
});
const results = await engine.emit({
type: 'new_customer',
properties: { plan: 'trial' },
});
// [{ ruleName: 'welcome-trial', actionType: 'log', status: 'success' }, ...]
console.log(results);engine.registerAction('slack_notify', async (params, event) => {
await fetch(params.webhookUrl as string, {
method: 'POST',
body: JSON.stringify({ text: params.message }),
});
});A single rule can match multiple event types:
engine.addRule({
name: 'premium-welcome',
when: ['new_customer', 'upgrade'], // fires on either event
conditionGroup: {
logic: 'AND',
conditions: [{ field: 'plan', op: 'eq', value: 'premium' }],
},
actions: [{ type: 'log', params: { message: 'Premium user!' } }],
});src/
types.ts Core interfaces and types
evaluator.ts Pure condition evaluation (eq, gte, contains, etc.)
engine.ts WorkflowEngine class — orchestrates rule matching and action dispatch
actions.ts Built-in action handlers (log, send_email)
index.ts Public API exports
examples/
onboarding.ts Runnable demo with 4 scenarios
tests/
engine.test.ts 30 unit tests covering all operators and engine behaviour