Skip to content

Use Case: Business Rules Engine

neuron-js excels as a lightweight, dynamic Business Rules Engine (BRE). It allows you to decouple complex decision logic from your core application code, enabling runtime updates and non-technical management of business policies.

Scenario: Tiered Loyalty Discounts

Imagine a retail platform that needs to calculate cart discounts based on two factors:

  1. User Loyalty Tier (Bronze, Silver, Gold).
  2. Cart Total Value.

1. The Implementation (Plugins)

First, we define the "building blocks" (Actions and Conditions) that our business team will use to compose rules.

Condition: UserLoyaltyTier

typescript
import { AbstractCondition, ExecutionResult } from '@sebasoft/neuron-js';

export class LoyaltyTierCondition extends AbstractCondition {
  static TYPE = 'loyalty_tier_match';

  async execute(context: ExecutionContext): ExecutionResult<boolean> {
    const requiredTier = this.params.get('tier').getValue(context);
    const userTier = context.state.user.loyaltyTier;

    return new ExecutionResult(userTier === requiredTier, context);
  }
}

Action: ApplyDiscount

typescript
import { AbstractAction, ExecutionResult } from '@sebasoft/neuron-js';

export class ApplyDiscountAction extends AbstractAction {
  static TYPE = 'apply_discount';

  async execute(context: ExecutionContext): ExecutionResult<void> {
    const percentage = this.params.get('percentage').getValue(context);
    const currentTotal = context.state.cart.total;
    
    const discountAmount = currentTotal * (percentage / 100);
    const newTotal = currentTotal - discountAmount;

    const nextContext = {
      ...context,
      state: {
        ...context.state,
        cart: { ...context.state.cart, total: newTotal }
      }
    };

    return new ExecutionResult(true, nextContext);
  }
}

2. The Rule Script (JSON)

Now, we can define our business logic in a pure JSON format. This could be stored in a database or a configuration file.

json
{
  "id": "seasonal-discounts-2026",
  "rules": [
    {
      "id": "gold-member-special",
      "type": "simple_rule",
      "conditions": [
        { 
          "type": "loyalty_tier_match", 
          "params": [{ "name": "tier", "type": "simple_string", "value": "GOLD" }] 
        }
      ],
      "actions": [
        { 
          "type": "apply_discount", 
          "params": [{ "name": "percentage", "type": "simple_number", "value": 20 }] 
        }
      ]
    },
    {
      "id": "high-value-bronze",
      "type": "simple_rule",
      "conditions": [
        { 
          "type": "loyalty_tier_match", 
          "params": [{ "name": "tier", "type": "simple_string", "value": "BRONZE" }] 
        },
        {
          "type": "compare_two_numbers",
          "params": [
            { "name": "op1", "type": "path_value", "value": "cart.total" },
            { "name": "comp", "type": "comparator", "value": ">" },
            { "name": "op2", "type": "simple_number", "value": 1000 }
          ]
        }
      ],
      "actions": [
        { 
          "type": "apply_discount", 
          "params": [{ "name": "percentage", "type": "simple_number", "value": 5 }] 
        }
      ]
    }
  ]
}

3. Execution

The execution engine coordinates the registry and the script to produce a result.

typescript
import { Neuron, Synapse } from '@sebasoft/neuron-js';

// 1. Setup the Registry
const registry = new Neuron();
registry.registerCondition(LoyaltyTierCondition.TYPE, LoyaltyTierCondition);
registry.registerAction(ApplyDiscountAction.TYPE, ApplyDiscountAction);

// 2. Prepare the Input Context
const context = {
  state: {
    user: { loyaltyTier: 'GOLD' },
    cart: { total: 100 }
  },
  messages: []
};

// 3. Execute the Engine
const engine = new Synapse(registry);
const result = engine.execute(discountScript, context);

if (result.isSuccessful()) {
  console.log(`New Total: ${result.context.state.cart.total}`); // New Total: 80
}

Why use neuron-js for BRE?

  • Hot-Swapping Logic: Update the JSON script in your database to change pricing strategies instantly without a code deployment.
  • Audit Trails: Use Lifecycle Hooks to log exactly which rules were evaluated and which actions were triggered.
  • Testing & Simulation: Since the script is data, you can run "What If" simulations by executing production scripts against test contexts in a sandbox environment.
  • Shared Grammar: Developers define the capabilities (Actions/Conditions), while Business Analysts or Admins can define the logic (Scripts).