Lightweight rule evaluation engine for A/B testing, feature flags, and user targeting.
- Zero runtime dependencies —
@atari-engine/corehas no external dependencies for minimal bundle size and cold starts. - Edge-native — Runs on Cloudflare Workers, Node.js, and in the browser.
- Infinite nesting — AND/OR rule groups with arbitrary depth.
- Type-safe — Full TypeScript support and type definitions.
- Isomorphic — Same code and behavior across all supported environments.
- React Rule Builder — Optional UI components with dark mode and validation.
This monorepo publishes two packages:
| Package | Description |
|---|---|
| @atari-engine/core | Rule evaluation engine: evaluate(), validate(), and shared types. |
| @atari-engine/react | React Rule Builder UI for creating and editing rule groups. |
Install the core engine:
npm install @atari-engine/core
# or
pnpm add @atari-engine/core
# or
yarn add @atari-engine/coreDefine a rule, validate it, and evaluate against context:
import {
evaluate,
validate,
FIELD_TYPES,
LOGICAL_OPERATORS,
OPERATORS,
type RuleGroup,
type UserProperties,
} from "@atari-engine/core";
const rule: RuleGroup = {
logicalOperator: LOGICAL_OPERATORS.AND,
conditions: [
{
fieldName: "age",
fieldType: FIELD_TYPES.NUMBER,
operator: OPERATORS.GREATER_THAN_OR_EQUAL_TO,
value: 18,
},
{
fieldName: "country",
fieldType: FIELD_TYPES.STRING,
operator: OPERATORS.IN,
value: ["KR", "JP", "US"],
},
],
};
const validation = validate(rule);
if (!validation.valid) {
console.error(validation.errors);
process.exit(1);
}
const user: UserProperties = { age: 25, country: "KR" };
const matched = evaluate(rule, user);
console.log(matched); // trueInstall the React package and peer dependencies:
npm install @atari-engine/react @atari-engine/core react react-dom
# or
pnpm add @atari-engine/react @atari-engine/core react react-domUse the Rule Builder in your app:
import { useState } from "react";
import { RuleBuilder, createEmptyRuleGroup } from "@atari-engine/react";
import "@atari-engine/react/styles.css";
function App() {
const [value, setValue] = useState(() => createEmptyRuleGroup("AND"));
return (
<RuleBuilder
value={value}
onChange={setValue}
fields={[
{ name: "age", type: "number", label: "Age" },
{ name: "country", type: "string", label: "Country" },
]}
showValidation
/>
);
}For dark mode, set data-theme="dark" on the wrapper or rely on prefers-color-scheme: dark.
| Environment | Supported |
|---|---|
| Cloudflare Workers | Yes (primary target) |
| Node.js >= 18 | Yes |
| Browser (ES2022+) | Yes |
| Deno / Bun | Yes (ESM) |
Issues and feedback are welcome.
MIT © JammyTheDreamer