@edgerules/node

中文文档
0.2.8-alpha.202611121551发布于 2026/11/12TypeScriptES Module近 30 天下载 2400

EdgeRules decision service for Node.js.

原始使用文档
文档目录12 节
  1. Installation
  2. Production Usage
  3. Load from an EdgeRules DSL string
  4. Load from a Portable JSON model
  5. Executing a ruleset
  6. Error handling
  7. Mutable / Development Usage
  8. get kinds
  9. API Reference
  10. DecisionService
  11. MutableDecisionService (dev build)
  12. Related packages

@edgerules/node

Quality Gate Status Bugs Code Smells Coverage Duplicated Lines

EdgeRules decision service for Node.js. Ships two builds:

ExportDescription
@edgerules/nodeProduction build — execution only (DecisionService)
@edgerules/node/mutableDevelopment build — execution + CRUD (MutableDecisionService)

Installation

npm install @edgerules/node @edgerules/portable

Requires Node.js 18 or later (ESM only).


Production Usage

Load from an EdgeRules DSL string

import { DecisionService } from '@edgerules/node';

const service = new DecisionService(`{
    applicant: {
        age:    <number, required: true>
        income: <number, default: 0>
    }
    isEligible: applicant.age >= 18 and applicant.income >= 1000
}`);

// Execute the whole model — inputs are bound via a model-shaped request object
const result = service.execute('*', { applicant: { age: 25, income: 2500 } });
// { applicant: { age: 25, income: 2500 }, isEligible: true }

Load from a Portable JSON model

import { DecisionService } from '@edgerules/node';
import type { PortableContext } from '@edgerules/portable';

const model: PortableContext = {
  '@kind': 'context',
  fields: {
    taxRate: 0.21,
    calculateTax: {
      '@kind': 'method',
      parameters: { amount: 'number', rate: 'number' },
      body: { '@kind': 'context', fields: { result: 'amount * rate' } },
    },
  },
};

const service = new DecisionService(model);

// Execute a specific function — pass its arguments as request bindings
const tax = service.execute('calculateTax', { amount: 100, rate: 0.21 });
// { result: 21 }

Executing a ruleset

const service = new DecisionService(`{
    ruleset risk(age: number, income: number): {
        hitPolicy: "first-match"
        rules: [
            { when: { age: 18..25, income: < 30000 }, then: { level: "high",   limit: 1000  } }
            { when: { age: 18..25, income: >= 30000 }, then: { level: "medium", limit: 5000  } }
            { when: { age: > 25 },                     then: { level: "low",    limit: 20000 } }
        ]
        default: { level: "none", limit: 0 }
    }
    decision: risk(age: applicant.age, income: applicant.income)
}`);

const result = service.execute('decision', { applicant: { age: 23, income: 25000 } });
// { level: "high", limit: 1000 }

Error handling

Every execution or model error is a structured PortableError — never a plain string.

import { DecisionService } from '@edgerules/node';
import type { PortableError } from '@edgerules/portable';

try {
  service.execute('unknownField');
} catch (err) {
  const error = err as PortableError;
  console.error(error.type);     // "EntryNotFound"
  console.error(error.message);  // human-readable, safe to surface
  console.error(error.path);     // "unknownField"
}
error.typeMeaning
EntryNotFoundPath does not exist in the model
WrongFieldPathInvalid path, out-of-bounds array index
ParseExpression string failed to parse
LinkingType mismatch or broken reference
ExecutionRuntime error during evaluation

Mutable / Development Usage

Use the ./mutable subpath import to access MutableDecisionService, which adds CRUD operations on top of execution. This build is intended for IDEs, rule editors, and test tooling — not for production traffic.

import { MutableDecisionService } from '@edgerules/node/mutable';

const service = new MutableDecisionService(`{
    taxRate: 0.21
    tax: amount * taxRate
}`);

// Read a node enriched with linked type information
const node = service.get('taxRate');
// { "@kind": "expression", "expression": "0.21", "type": "number", "linked": true }

// Update a field at runtime — the engine relinks lazily on the next execute
service.set('taxRate', 0.25);

// Read the entire model snapshot
const model = service.get('*');

// Add a new typed input
service.set('amount', { '@kind': 'placeholder', type: 'number', required: true });

// Remove a field
service.remove('taxRate');

// Rename a field
service.rename('tax', 'vat');

// Read a node as DSL source text instead of Portable JSON
service.getCode('tax');
// 'amount * taxRate'

// Write DSL source text back — returns a PortableNode, not code text
service.setCode('tax', 'amount * taxRate * 2');

get kinds

import { Kinds } from '@edgerules/node';

// Absent kinds: every declaration, with bodies
service.get('isEligible');

// The method signature only
service.get('isEligible', ['method-interface']);

// The type only, without its facts
service.get('Customer', ['type']);

// A project-explorer view without bodies and expression text
service.get('*', [...Kinds.EXPRESSION_INTERFACES, ...Kinds.TYPES, ...Kinds.INVOCABLE_INTERFACES]);

API Reference

DecisionService

MethodDescription
new DecisionService(model)Create from DSL string or a root PortableContext
execute(method, args?)Evaluate method (field path, function, or "*") against optional request bindings

MutableDecisionService (dev build)

Inherits execute and adds:

MethodDescription
get(path, kinds?)Read a node, filtered by @kind; linked tells if the model links
set(path, value)Write an expression, placeholder, method, type, or context
getCode(path)Read a node as EdgeRules DSL source text
setCode(path, code)Write a node from EdgeRules DSL source text; returns a PortableNode, not code text
remove(path)Delete an entry
rename(oldPath, newPath)Rename an entry within its context

版本与发布记录

@edgerules/node 共发布 35 个版本,首次发布于 2026/07/04;过去 12 个月发布了 35 个版本。

版本发布日期距今
0.2.8-alpha.202611121551latest2026/11/12今天
0.2.7-alpha.2026110819152026/11/094 天前
0.2.6-alpha.2026110818092026/11/094 天前
0.2.6-alpha.2026110818082026/11/094 天前
0.2.5-alpha.2026110720262026/11/085 天前
0.2.4-alpha.2026110716572026/11/085 天前

关于 @edgerules/node 的常见问题

@edgerules/node 是什么?

EdgeRules decision service for Node.js.

如何安装 @edgerules/node?

在项目目录运行 npm install @edgerules/node,或使用 pnpm add / yarn add / bun add。

@edgerules/node 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@edgerules/node 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@edgerules/node 可以商用吗?

@edgerules/node 使用 未声明 许可。package.json 没有声明许可证。没有许可证的代码默认保留全部权利,商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括,不构成法律意见,请以许可原文为准。

@edgerules/node 的下载量有多少?

根据 npm 官方下载统计,@edgerules/node 在 2026/10/13 – 2026/11/11 这 30 天内被下载 2,400 次,日均约 80 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@edgerules/node 还在维护吗?

最新版本 0.2.8-alpha.202611121551 发布于 2026/11/12(今天);至今共发布 35 个版本,其中过去 12 个月发布了 35 个;首次发布于 2026/07/04。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。