ruleforge
v0.3.1
Published
Declarative rule engine to map JSON/XML payloads into canonical nested JSON.
Maintainers
Readme
ruleforge
Declarative Rule Engine & Integration Mapping Framework Transform JSON/XML payloads into canonical nested JSON using selectors, conditions, transforms, and loop bindings.
Why ruleforge?
RuleForge allows you to:
- Map complex nested payloads declaratively
- Handle JSON and XML seamlessly
- Extract deeply nested values using selector variables ($X1..$X10)
- Apply operator-based conditions
- Use preprocessors & postprocessors
- Normalize CDATA into $pre
- Support case-insensitive, regex, numeric comparisons
- Build enterprise-grade integration pipelines without hardcoding logic
Features
- JSON and XML support (XML normalized to JS object)
- Envelope / metadata support via
initializer - Payload inside string fields supported (JSON/XML strings)
- Preprocessors, PostProcessors
- Rule priority (top → bottom)
- Array selector (
X) – first match - Nested canonical output keys (dot-path targets)
- Transform functions (built-ins + custom)
- Debug metadata (
result.meta.matched,$pre, etc.)
Installation
npm install ruleforgeCore Concepts
Namespaces
RuleForge works with three namespaces:
| Namespace | Description | | --------- | ----------------------------- | | $payload | Original normalized payload | | $meta | Input metadata | | $pre | Preprocessed / derived values |
Rule Document Structure
{
"version": "1.0",
"name": "example_rules",
"initializer": { "function": "initRequest" },
"aliases": {},
"preprocessors": {},
"postProcessors": [],
"rules": {}
}
Basic Example
Input (JSON)
{
"device": {
"serialNumber": "CNB1234567"
}
}Rules
{
"version": "1.0",
"rules": {
"output.device.serialNumber": {
"mappings": ["device.serialNumber"]
}
}
}Output
{
"output": {
"device": {
"serialNumber": "CNB1234567"
}
}
}Selector Variables ($X1..$X10)
Supports nested array traversal.
Example:
{
"match.serial": {
"conditions": {
"customers.$X1.devices.$X2.id": "deviceId_10"
},
"mappings": [
"customers.$X1.devices.$X2.serialNum"
]
}
}✔ Automatically finds correct indices ✔ DFS-based selector binding ✔ Supports up to 10 nested variables
Looping Output Arrays ($X)
For output array construction:
"metrics.$X.totalSheets": {
"conditions": {
"CounterGroup.$X1.CounterName": "TotalSheets"
},
"mappings": [
"CounterGroup.$X1.Value"
]
}Each match produces:
{
"metrics": [
{ "totalSheets": 17 },
{ "totalSheets": 18 }
]
}Operator-Style Conditions
Case Insensitive
{
"$pre.clientName": { "equalsIgnoreCase": "agent_1" }
}In List (Case Insensitive)
{
"$pre.clientName": { "inIgnoreCase": ["agent_1", "agent_2"] }
}Regex
{
"$pre.clientName": { "regex": "^Agent_[0-9]+$", "flags": "i" }
}
Numeric Comparison
{
"account.balance": { "gt": 1000 }
}Exists
{
"device.serialNumber": { "exists": true }
}Type Check
{
"field": { "type": "string" }
}Combinators
{
"$pre.clientName": {
"all": [
{ "equalsIgnoreCase": "agent_1" },
{ "regex": "agent_[0-9]+", "flags": "i" }
]
}
}Preprocessors
Preprocessors allow derived values before rules execute.
{
"preprocessors": {
"clientName": { "function": "getClientName" }
}
}Implementation:
async function getClientName(ns, ctx) {
return ns.payload.source?.system;
}Accessible as:
$pre.clientNamePostProcessors
Transform final output before returning:
{
"postProcessors": ["convertOutputData"]
}Aliases
Aliases allow fallback paths across payload types.
{
"aliases": {
"Asset": [
"$pre.jsonData.device",
"UsageCollection.Asset"
]
}
}Usage:
"Asset.serialNumber"Debug Mode
Enable debug to include:
- matched rule index
- selector bindings
- resolved paths
- $pre content
new Mapper({
spec,
functions,
debug: true
})API Usage
import { Mapper } from "ruleforge";
const mapper = new Mapper({
spec: rules,
functions: {
initializer: { initRequest },
preprocessors: { getClientName },
transforms: {},
postProcessors: {}
}
});
const result = await mapper.map(input);
if (result.ok) {
console.log(result.value);
} else {
console.error(result.error);
}Guardrails
- Max 10 selector variables ($X1..$X10)
- Max candidate bindings limited
- Max array scan per level limited
- Invalid operator detection
- Invalid selector detection
- Required rule enforcement
Roadmap
- Expression engine (optional future)
- Plugin architecture (v0.3+)
- Performance optimizations
- JSON Schema validation for rule documents
License
MIT
Contributing
- PRs welcome.
- Open issues for feature discussions before major design changes.
