Showing preview only (1,739K chars total). Download the full file or copy to clipboard to get everything.
Repository: ali-master/rule-engine
Branch: master
Commit: 711e58f9b1a4
Files: 237
Total size: 1.6 MB
Directory structure:
gitextract_v5gxdb39/
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── CODE_OF_CONDUCT.md
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── .idea/
│ ├── .gitignore
│ ├── compiler.xml
│ ├── git_toolbox_prj.xml
│ ├── inspectionProfiles/
│ │ └── Project_Default.xml
│ ├── jsLinters/
│ │ └── eslint.xml
│ ├── modules.xml
│ ├── prettier.xml
│ ├── usex.iml
│ └── vcs.xml
├── .npmignore
├── .npmrc
├── .nvmrc
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENCE
├── README.md
├── assets/
│ └── BRAND_ASSETS.md
├── docs/
│ ├── architecture.md
│ ├── comparison.md
│ └── getting-started.md
├── eslint.config.js
├── knip.json
├── package.json
├── packages/
│ ├── builder/
│ │ ├── .gitignore
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── components.json
│ │ ├── docs/
│ │ │ ├── README.md
│ │ │ ├── RuleEvaluator.md
│ │ │ ├── components.md
│ │ │ ├── examples.md
│ │ │ ├── hooks.md
│ │ │ └── integration.md
│ │ ├── index.html
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── App.tsx
│ │ │ ├── components/
│ │ │ │ ├── AdvancedFieldInput.tsx
│ │ │ │ ├── AnimatedNumber.tsx
│ │ │ │ ├── ConditionGroup.tsx
│ │ │ │ ├── ConstraintEditor.tsx
│ │ │ │ ├── DiffViewer.tsx
│ │ │ │ ├── DraggableConditionGroup.tsx
│ │ │ │ ├── DynamicFieldSelector.tsx
│ │ │ │ ├── EditableJsonViewer.tsx
│ │ │ │ ├── FieldSelector.tsx
│ │ │ │ ├── HistoryViewer.tsx
│ │ │ │ ├── ImportExport.tsx
│ │ │ │ ├── JsonViewer.tsx
│ │ │ │ ├── JsonVisualizer.tsx
│ │ │ │ ├── ModernConstraintEditor.tsx
│ │ │ │ ├── ModernRuleBuilder.tsx
│ │ │ │ ├── OperatorSelector.tsx
│ │ │ │ ├── RegexValidator.tsx
│ │ │ │ ├── ResizablePanel.tsx
│ │ │ │ ├── RuleImportModal.tsx
│ │ │ │ ├── RuleImporter.tsx
│ │ │ │ ├── RuleViewer.tsx
│ │ │ │ ├── SmartOperatorSelector.tsx
│ │ │ │ ├── ThemeToggle.tsx
│ │ │ │ ├── TreeConditionGroup.tsx
│ │ │ │ ├── TreeConstraintEditor.tsx
│ │ │ │ ├── TreeRuleBuilder.tsx
│ │ │ │ ├── UndoRedoInfo.tsx
│ │ │ │ ├── ValueInput.tsx
│ │ │ │ ├── VisualFieldSelector.tsx
│ │ │ │ ├── condition-group.tsx
│ │ │ │ ├── editable-json-viewer.tsx
│ │ │ │ ├── history-viewer.tsx
│ │ │ │ ├── inputs/
│ │ │ │ │ ├── AnimatedNumberInput.tsx
│ │ │ │ │ ├── ArrayInput.tsx
│ │ │ │ │ ├── BooleanInput.tsx
│ │ │ │ │ ├── DateInput.tsx
│ │ │ │ │ ├── NumberInput.tsx
│ │ │ │ │ └── SmartValueInput.tsx
│ │ │ │ ├── operators/
│ │ │ │ │ ├── ArrayOperatorHandler.tsx
│ │ │ │ │ ├── BooleanValidationHandler.tsx
│ │ │ │ │ ├── ComparisonOperatorHandler.tsx
│ │ │ │ │ ├── DateOperatorHandler.tsx
│ │ │ │ │ ├── ExistenceOperatorHandler.tsx
│ │ │ │ │ ├── LengthValidationHandler.tsx
│ │ │ │ │ ├── NumberValidationHandler.tsx
│ │ │ │ │ ├── SelfReferenceHandler.tsx
│ │ │ │ │ ├── StringValidationHandler.tsx
│ │ │ │ │ ├── TypeValidationHandler.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── resizable-panel.tsx
│ │ │ │ ├── rule-builder.tsx
│ │ │ │ ├── rule-editor.tsx
│ │ │ │ ├── rule-evaluator.tsx
│ │ │ │ ├── rule-import-modal.tsx
│ │ │ │ ├── rule-viewer.tsx
│ │ │ │ ├── theme-provider.tsx
│ │ │ │ ├── theme-toggle.tsx
│ │ │ │ └── ui/
│ │ │ │ ├── alert.tsx
│ │ │ │ ├── badge.tsx
│ │ │ │ ├── button.tsx
│ │ │ │ ├── calendar.tsx
│ │ │ │ ├── card.tsx
│ │ │ │ ├── collapsible.tsx
│ │ │ │ ├── command.tsx
│ │ │ │ ├── dialog.tsx
│ │ │ │ ├── dropdown-menu.tsx
│ │ │ │ ├── input.tsx
│ │ │ │ ├── label.tsx
│ │ │ │ ├── popover.tsx
│ │ │ │ ├── scroll-area.tsx
│ │ │ │ ├── select.tsx
│ │ │ │ ├── separator.tsx
│ │ │ │ ├── sheet.tsx
│ │ │ │ ├── slider.tsx
│ │ │ │ ├── sonner.tsx
│ │ │ │ ├── switch.tsx
│ │ │ │ ├── tabs.tsx
│ │ │ │ ├── textarea.tsx
│ │ │ │ ├── tooltip.tsx
│ │ │ │ └── zoom-dialog.tsx
│ │ │ ├── constants/
│ │ │ │ └── operator-help.ts
│ │ │ ├── data/
│ │ │ │ └── sample-data.ts
│ │ │ ├── debug-test.tsx
│ │ │ ├── demo.tsx
│ │ │ ├── hooks/
│ │ │ │ ├── use-field-discovery.ts
│ │ │ │ ├── use-keyboard-shortcuts.ts
│ │ │ │ └── use-theme.ts
│ │ │ ├── index.ts
│ │ │ ├── lib/
│ │ │ │ └── utils.ts
│ │ │ ├── main.tsx
│ │ │ ├── stores/
│ │ │ │ ├── enhanced-rule-store.ts
│ │ │ │ ├── rule-store.ts
│ │ │ │ └── unified-rule-store.ts
│ │ │ ├── styles/
│ │ │ │ ├── animations.css
│ │ │ │ └── globals.css
│ │ │ ├── test-demo.tsx
│ │ │ ├── test-store-debug.tsx
│ │ │ ├── types/
│ │ │ │ └── index.ts
│ │ │ ├── utils/
│ │ │ │ ├── json-path.ts
│ │ │ │ └── operators.ts
│ │ │ └── vite-env.d.ts
│ │ ├── tsconfig.app.json
│ │ ├── tsconfig.json
│ │ ├── tsconfig.node.json
│ │ ├── vercel.json
│ │ └── vite.config.ts
│ └── core/
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── benchmarks/
│ │ ├── builder.bench.ts
│ │ ├── engine.bench.ts
│ │ ├── introspector.bench.ts
│ │ ├── json-path.bench.ts
│ │ ├── mutator.bench.ts
│ │ └── validator.bench.ts
│ ├── docs/
│ │ ├── README.md
│ │ ├── api-reference-v2.md
│ │ ├── api-reference.md
│ │ ├── best-practices.md
│ │ ├── index.md
│ │ ├── migration-guide.md
│ │ ├── operators.md
│ │ ├── refactoring-summary.md
│ │ ├── typescript-guide.md
│ │ └── v2-migration-guide.md
│ ├── package.json
│ ├── src/
│ │ ├── enums/
│ │ │ ├── condition-types.enum.ts
│ │ │ ├── index.ts
│ │ │ └── operators.enum.ts
│ │ ├── examples/
│ │ │ └── custom-operator.example.ts
│ │ ├── index.ts
│ │ ├── operators/
│ │ │ ├── base.ts
│ │ │ ├── factory.ts
│ │ │ ├── implementations/
│ │ │ │ ├── array.ts
│ │ │ │ ├── boolean.ts
│ │ │ │ ├── comparison.ts
│ │ │ │ ├── date-time.ts
│ │ │ │ ├── existence.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── numeric.ts
│ │ │ │ ├── pattern.ts
│ │ │ │ ├── string.ts
│ │ │ │ └── type.ts
│ │ │ ├── index.ts
│ │ │ ├── like.md
│ │ │ └── registry.ts
│ │ ├── services/
│ │ │ ├── builder.ts
│ │ │ ├── evaluator.ts
│ │ │ ├── index.ts
│ │ │ ├── introspector.ts
│ │ │ ├── logger.ts
│ │ │ ├── mutator.ts
│ │ │ ├── object-discovery.ts
│ │ │ ├── rule-engine.ts
│ │ │ └── validator.ts
│ │ ├── types/
│ │ │ ├── index.ts
│ │ │ ├── introspection.type.ts
│ │ │ ├── rule.type.ts
│ │ │ └── validator.type.ts
│ │ └── utils/
│ │ ├── clone.util.ts
│ │ ├── date.util.ts
│ │ ├── error.util.ts
│ │ ├── extract-jsonpath-expressions.util.ts
│ │ ├── index.ts
│ │ ├── is-object.util.ts
│ │ └── time.util.ts
│ ├── test/
│ │ ├── builder.spec.ts
│ │ ├── engine.spec.ts
│ │ ├── introspector.spec.ts
│ │ ├── json-path.spec.ts
│ │ ├── mutator.spec.ts
│ │ ├── operators.spec.ts
│ │ ├── rule-engine.spec.ts
│ │ ├── rulesets/
│ │ │ ├── invalid2.json.ts
│ │ │ ├── password-rule.json.ts
│ │ │ ├── regex-rules.json.ts
│ │ │ ├── self-fields-constraints.json.ts
│ │ │ ├── valid1.json.ts
│ │ │ ├── valid10.json.ts
│ │ │ ├── valid11.json.ts
│ │ │ ├── valid12.json.ts
│ │ │ ├── valid13.json.ts
│ │ │ ├── valid2.json.ts
│ │ │ ├── valid3.json.ts
│ │ │ ├── valid4.json.ts
│ │ │ ├── valid5.json.ts
│ │ │ ├── valid6.json.ts
│ │ │ ├── valid7.json.ts
│ │ │ ├── valid8.json.ts
│ │ │ └── valid9.json.ts
│ │ ├── utils.spec.ts
│ │ └── validator.spec.ts
│ ├── tsconfig.build.json
│ ├── tsconfig.json
│ ├── tsup.config.ts
│ └── vitest.config.ts
└── pnpm-workspace.yaml
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = true
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
[*.js]
indent_style = space
indent_size = 2
[{package.json,*.yml,*.cjson}]
indent_style = space
indent_size = 2
================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto
================================================
FILE: .github/CODE_OF_CONDUCT.md
================================================
# Code of Conduct
## Our Pledge
The **@usex/rule-engine** project is committed to fostering an open, welcoming, and inclusive community. As contributors and maintainers of this JSON-based rule engine, we pledge to make participation in our project a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
We believe that a diverse community of developers, architects, and business analysts makes our rule engine better and more valuable for everyone.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
- **Inclusive Communication**: Using welcoming and inclusive language in issues, pull requests, and discussions
- **Respectful Collaboration**: Being respectful of differing technical approaches, architectural decisions, and implementation strategies
- **Constructive Feedback**: Gracefully accepting and providing constructive criticism on code, documentation, and rule engine design
- **Community Focus**: Prioritizing what benefits the broader rule engine community and user ecosystem
- **Empathy and Support**: Showing empathy towards other community members, especially when helping newcomers understand rule engine concepts
- **Knowledge Sharing**: Actively sharing knowledge about business rules, JSON schemas, and engine optimization
- **Technical Excellence**: Striving for high-quality code, comprehensive documentation, and robust testing
Examples of unacceptable behavior by participants include:
- **Harassment and Discrimination**: The use of sexualized language or imagery, trolling, insulting/derogatory comments, and personal or political attacks
- **Privacy Violations**: Publishing others' private information, such as physical or electronic addresses, without explicit permission
- **Technical Gatekeeping**: Deliberately making newcomers feel unwelcome or inferior based on their technical knowledge or experience level
- **Destructive Criticism**: Providing criticism that is not constructive or that attacks the person rather than the idea or implementation
- **Spam and Self-Promotion**: Excessive self-promotion, spam, or off-topic discussions unrelated to rule engines or the project
- **Bad Faith Participation**: Contributing with malicious intent, deliberately introducing bugs, or sabotaging the project
- **Violation of Licensing**: Misusing the project's MIT license or violating intellectual property rights
- Other conduct which could reasonably be considered inappropriate in a professional open-source environment
## Maintainer Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
The maintainers of @usex/rule-engine have the right and responsibility to:
- **Moderate Content**: Remove, edit, or reject comments, commits, code, documentation, wiki edits, issues, pull requests, and other contributions that are not aligned with this Code of Conduct
- **Ensure Quality**: Maintain high standards for code quality, testing, and documentation while being supportive of contributors learning these standards
- **Community Management**: Foster an inclusive environment where both technical experts and newcomers can contribute meaningfully to the rule engine ecosystem
- **Enforcement Actions**: Take temporary or permanent action against contributors for behaviors deemed inappropriate, threatening, offensive, or harmful to the community
- **Technical Leadership**: Guide the architectural direction of the rule engine while remaining open to community input and innovative ideas
## Scope
This Code of Conduct applies within all @usex/rule-engine project spaces, including:
- **GitHub Repository**: Issues, pull requests, discussions, code reviews, and wiki pages
- **Documentation**: README files, API documentation, tutorials, and guides
- **Communication Channels**: Official project communications via email, social media, or other platforms
- **Community Events**: When representing the project at conferences, meetups, workshops, or online events
- **Package Registries**: Comments and descriptions on npm, GitHub Packages, or other distribution platforms
This Code of Conduct also applies when community members are representing the rule engine project in public spaces. Representation may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project maintainer:
- **Primary Contact**: [Ali Torki](https://github.com/ali-master) via GitHub issues or discussions
- **Direct Email**: For sensitive matters that require privacy
All complaints will be reviewed and investigated promptly and fairly. The project team is obligated to maintain confidentiality with regard to the reporter of an incident.
### Enforcement Process
1. **Initial Review**: Reports will be acknowledged within 48 hours
2. **Investigation**: Thorough review of the incident with all relevant parties
3. **Resolution**: Appropriate action will be taken, which may include:
- Warning and education
- Temporary suspension from project spaces
- Permanent ban from the community
4. **Follow-up**: Monitoring to ensure the resolution is effective
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by the project leadership.
## Attribution
This Code of Conduct is customized for the **@usex/rule-engine** project and is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq
---
## Community Resources
- 📚 **Documentation**: [Project README](../README.md)
- 🐛 **Report Issues**: [GitHub Issues](https://github.com/ali-master/rule-engine/issues)
- 💬 **Discussions**: [GitHub Discussions](https://github.com/ali-master/rule-engine/discussions)
- 📦 **NPM Package**: [@usex/rule-engine](https://www.npmjs.com/package/@usex/rule-engine)
**Thank you for helping make the @usex/rule-engine community welcoming and inclusive for everyone!** 🚀
================================================
FILE: .github/workflows/ci.yml
================================================
name: ci
on:
pull_request:
branches:
- master
- develop
push:
branches:
- master
- develop
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm i -g --force corepack && corepack enable
- uses: actions/setup-node@v4
with:
node-version: lts/*
cache: pnpm
- name: 📦 Install dependencies
run: pnpm install
- name: 🛠 Build project
run: pnpm build
- name: 🔠 Lint project
run: pnpm lint
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm i -g --force corepack && corepack enable
- uses: actions/setup-node@v4
with:
node-version: lts/*
cache: pnpm
- name: 📦 Install dependencies
run: pnpm install
- name: 🛠 Build project
run: pnpm build
- name: 💪 Test types
run: pnpm test:types
- name: 🧪 Test project
run: pnpm test:coverage
- name: 📊 Generate test report
if: always()
run: pnpm test:junit
- name: 📈 Upload test results to Codecov
if: ${{ !cancelled() }}
uses: codecov/test-results-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
- name: 🟩 Coverage
uses: codecov/codecov-action@v5
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
================================================
FILE: .gitignore
================================================
**/dist
**/node_modules
**/coverage
.vscode
.DS_Store
.eslintcache
*.log*
**/*.env*
.husky
.claude
apps/*/.next/
================================================
FILE: .idea/.gitignore
================================================
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
================================================
FILE: .idea/compiler.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="TypeScriptCompiler">
<option name="useTypesFromServer" value="true" />
</component>
</project>
================================================
FILE: .idea/git_toolbox_prj.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitToolBoxProjectSettings">
<option name="commitMessageIssueKeyValidationOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
<option name="commitMessageValidationEnabledOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
</component>
</project>
================================================
FILE: .idea/inspectionProfiles/Project_Default.xml
================================================
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>
================================================
FILE: .idea/jsLinters/eslint.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EslintConfiguration">
<option name="fix-on-save" value="true" />
</component>
</project>
================================================
FILE: .idea/modules.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/usex.iml" filepath="$PROJECT_DIR$/.idea/usex.iml" />
</modules>
</component>
</project>
================================================
FILE: .idea/prettier.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PrettierConfiguration">
<option name="myConfigurationMode" value="AUTOMATIC" />
<option name="myRunOnSave" value="true" />
<option name="myFilesPattern" value="**/*.{js,ts,jsx,tsx,cjs,cts,mjs,mts,vue,astro,json,css}" />
</component>
</project>
================================================
FILE: .idea/usex.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
<excludeFolder url="file://$MODULE_DIR$/apps/web/.next" />
<excludeFolder url="file://$MODULE_DIR$/packages/builder/dist-demo" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
================================================
FILE: .idea/vcs.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
================================================
FILE: .npmignore
================================================
# Ignore everything by default
*
# Include the dist folder and its contents
!dist
!dist/**
# Exclude .tsbuildinfo files (not needed in published package)
dist/**/*.tsbuildinfo
# Include the assets folder and its contents
!assets
!assets/**
================================================
FILE: .npmrc
================================================
strict-peer-dependencies=false
================================================
FILE: .nvmrc
================================================
24.4.1
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our standards
Examples of behavior that contributes to creating a positive environment include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
## Our responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies within all project spaces, and it also applies when an individual is representing the project or its community in public spaces. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [ali_4286@live.com](mailto:ali_4286@live.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to @usex/rule-engine
First off, thank you for considering contributing to @usex/rule-engine! It's people like you that make this project better for everyone.
## Table of Contents
- [Code of Conduct](#code-of-conduct)
- [Getting Started](#getting-started)
- [Development Setup](#development-setup)
- [How to Contribute](#how-to-contribute)
- [Coding Standards](#coding-standards)
- [Testing](#testing)
- [Documentation](#documentation)
- [Pull Request Process](#pull-request-process)
## Code of Conduct
This project and everyone participating in it is governed by our [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code.
## Getting Started
1. Fork the repository on GitHub
2. Clone your fork locally
3. Set up the development environment
4. Create a branch for your changes
5. Make your changes
6. Submit a pull request
## Development Setup
### Prerequisites
- Node.js >= 18.12.0
- pnpm >= 10.11.0
### Installation
```bash
# Clone your fork
git clone https://github.com/YOUR_USERNAME/rule-engine.git
cd rule-engine
# Install dependencies
pnpm install
# Build all packages
pnpm build
```
### Project Structure
```
rule-engine/
├── packages/
│ ├── core/ # Core rule engine library
│ └── builder/ # Visual rule builder UI
├── apps/
│ └── web/ # Documentation website
└── docs/ # Additional documentation
```
## How to Contribute
### Reporting Bugs
Before creating bug reports, please check existing issues. When creating a bug report, include:
1. **Clear title and description**
2. **Steps to reproduce**
3. **Expected behavior**
4. **Actual behavior**
5. **Code samples** (if applicable)
6. **Environment details** (Node version, OS, etc.)
### Suggesting Features
Feature suggestions are welcome! Please:
1. **Check existing issues** first
2. **Provide clear use cases**
3. **Explain the benefits**
4. **Consider implementation details**
### Code Contributions
1. **Small changes**: Bug fixes, documentation updates
2. **Large changes**: New features, significant refactoring (discuss first in an issue)
## Coding Standards
### TypeScript
- Use TypeScript for all new code
- Enable strict mode
- Provide proper types (avoid `any`)
- Document complex types
### Code Style
```typescript
// Good
export function evaluateRule<T>(
rule: RuleType<T>,
data: unknown
): Promise<EvaluationResult<T>> {
// Implementation
}
// Bad
export function evaluateRule(rule: any, data: any): any {
// Implementation
}
```
### Naming Conventions
- **Files**: kebab-case (e.g., `rule-engine.ts`)
- **Classes**: PascalCase (e.g., `RuleEngine`)
- **Functions/Variables**: camelCase (e.g., `evaluateRule`)
- **Constants**: UPPER_SNAKE_CASE (e.g., `MAX_DEPTH`)
- **Types/Interfaces**: PascalCase (e.g., `RuleType`)
### Comments
```typescript
/**
* Evaluates a rule against the provided criteria.
*
* @param rule - The rule to evaluate
* @param criteria - The data to evaluate against
* @param trustRule - Skip validation if true
* @returns The evaluation result
*
* @example
* ```typescript
* const result = await evaluateRule(rule, { age: 25 });
* ```
*/
```
## Testing
### Running Tests
```bash
# Run all tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Run tests with coverage
pnpm test:coverage
# Run specific package tests
cd packages/core && pnpm test
```
### Writing Tests
```typescript
describe('RuleEngine', () => {
describe('evaluate', () => {
it('should evaluate simple rule correctly', async () => {
const rule = {
conditions: {
and: [
{ field: 'age', operator: 'greater-than', value: 18 }
]
}
};
const result = await RuleEngine.evaluate(rule, { age: 25 });
expect(result.isPassed).toBe(true);
expect(result.value).toBe(true);
});
});
});
```
### Test Requirements
- Write tests for all new features
- Maintain or improve code coverage
- Test edge cases
- Include integration tests for complex features
## Documentation
### Code Documentation
- Document all public APIs
- Include JSDoc comments
- Provide usage examples
- Explain complex algorithms
### README Updates
Update relevant README files when:
- Adding new features
- Changing APIs
- Adding new operators
- Fixing significant bugs
### Documentation Structure
```
packages/core/
├── README.md # Package documentation
└── docs/
├── api-reference.md
├── operators.md
└── best-practices.md
```
## Pull Request Process
### Before Submitting
1. **Update documentation** for any API changes
2. **Add tests** for new functionality
3. **Run all tests** locally
4. **Update CHANGELOG** if applicable
5. **Ensure code follows** style guidelines
### PR Guidelines
#### Title Format
```
<type>(<scope>): <subject>
Examples:
feat(core): add new date-between operator
fix(builder): resolve focus issue in field selector
docs(core): update migration guide
```
#### Types
- `feat`: New feature
- `fix`: Bug fix
- `docs`: Documentation only
- `style`: Code style changes
- `refactor`: Code refactoring
- `perf`: Performance improvements
- `test`: Test additions/changes
- `chore`: Maintenance tasks
#### Description Template
```markdown
## Description
Brief description of changes
## Motivation
Why these changes are needed
## Changes
- Change 1
- Change 2
## Testing
How the changes were tested
## Breaking Changes
List any breaking changes
## Related Issues
Fixes #123
```
### Review Process
1. **Automated checks** must pass
2. **Code review** by maintainers
3. **Address feedback** promptly
4. **Squash commits** if requested
## Questions?
Feel free to:
- Open an issue for questions
- Join discussions in existing issues
- Contact maintainers
Thank you for contributing! 🎉
================================================
FILE: LICENCE
================================================
MIT License
Copyright (c) 2022 Ali Torki
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
<div align="center">
<img src="./assets/core-logo.png" alt="Rule Engine" width="120" />
<h1>@usex/rule-engine</h1>
<p><strong>🎯 The Ultimate JSON-Based Rule Engine for Modern Applications</strong></p>
<p>
<a href="https://www.npmjs.com/package/@usex/rule-engine"><img src="https://img.shields.io/npm/v/@usex/rule-engine?style=flat-square&color=blue" alt="npm version" /></a>
<a href="https://github.com/ali-master/rule-engine/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/@usex/rule-engine?style=flat-square&color=green" alt="license" /></a>
<a href="https://codecov.io/gh/ali-master/rule-engine"><img src="https://codecov.io/gh/ali-master/rule-engine/graph/badge.svg?token=UN5opqxNsi" alt="codecov" /></a>
<a href="https://www.npmjs.com/package/@usex/rule-engine"><img src="https://img.shields.io/npm/dm/@usex/rule-engine?style=flat-square&color=orange" alt="downloads" /></a>
<a href="https://github.com/ali-master/rule-engine"><img src="https://img.shields.io/github/stars/ali-master/rule-engine?style=flat-square&color=yellow" alt="stars" /></a>
<a href="https://bundlephobia.com/package/@usex/rule-engine"><img src="https://img.shields.io/bundlephobia/minzip/@usex/rule-engine?style=flat-square&color=purple" alt="bundle size" /></a>
</p>
<p>
<a href="#-quick-start">Quick Start</a> •
<a href="#-packages">Packages</a> •
<a href="#-examples">Examples</a> •
<a href="#-documentation">Documentation</a> •
<a href="#-why-choose-this">Why This?</a>
</p>
<a href="https://www.producthunt.com/products/open-source-rule-engine?embed=true&utm_source=badge-featured&utm_medium=badge&utm_source=badge-open-source-rule-engine" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=1012148&theme=light&t=1759345778417" alt="Open Source Rule Engine - A JSON rule engine for declarative business logic. | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
</div>
---
**Transform complex business logic into elegant, maintainable JSON rules.** Stop hardcoding decisions, start building intelligent systems that adapt to your business needs.
```typescript
// From this mess...
if (user.tier === 'vip' && order.total > 100 && user.country === 'US') {
return { discount: 0.20, shipping: 'free' };
} else if (user.isNew && order.total > 50) {
return { discount: 0.10, shipping: 'standard' };
} // ... 50 more lines of spaghetti code
// To this elegance...
const result = await RuleEngine.evaluate(discountRules, { user, order });
```
## 🚀 Why Rule Engine?
### **Built for Modern Developers**
- 🎯 **Zero Dependencies** - Pure JavaScript excellence, no supply chain bloat
- 🏎️ **Lightning Fast** - 17,000+ rule evaluations per second with complex JSONPath support at 55,000+ ops/sec
- 🛡️ **TypeScript Native** - **Fully typed with generic support** for bulletproof type safety
- 🔧 **Extensible Architecture** - **Create & register custom operators** without core modifications
- 🌐 **Universal** - Node.js, browsers, edge functions, Deno, Bun everywhere
### **Powerful Yet Intuitive**
- 🔍 **JSONPath Support** - Navigate complex objects: `$.user.profile.settings.theme`
- 🔗 **Self-Referencing** - Dynamic field references: `"value": "$.maxPrice"`
- 🧩 **121+ Operators** - From basic comparisons to advanced pattern matching
- 🏗️ **Visual Builder** - Drag-and-drop UI for non-technical stakeholders
### **Enterprise Ready**
- 🔧 **Extensible Core** - **Plugin custom operators** without touching internals
- 🛡️ **Type-Safe APIs** - **Generic interfaces** ensure compile-time safety
- 📊 **Rule Introspection** - Reverse-engineer possible inputs from rule definitions
- ⚡ **Performance Optimized** - Optional validation bypass for trusted rules
- 🎭 **Data Mutations** - Preprocess data before evaluation
## 📦 Packages
This monorepo contains two powerful packages:
| Package | Description | Install |
|---------|-------------|---------|
| **[@usex/rule-engine](./packages/core)** <br/> [](https://www.npmjs.com/package/@usex/rule-engine) | **Fully typed** core engine with **generic support** & **custom operators** | `npm install @usex/rule-engine` |
| **[@usex/rule-engine-builder](./packages/builder)** <br/> [](https://www.npmjs.com/package/@usex/rule-engine-builder) | Visual rule builder for React applications | `npm install @usex/rule-engine-builder` |
## 🛡️ TypeScript Excellence & Extensibility
### **Fully Typed with Generics**
The core package is built with TypeScript-first design, providing complete type safety:
```typescript
// Type-safe rule definitions with generics
interface DiscountResult {
discount: number;
code: string;
description: string;
}
// Generic rule with full type inference
const discountRule: Rule<DiscountResult> = {
conditions: [
{
and: [
{ field: "$.user.tier", operator: "equals", value: "premium" },
{ field: "$.order.total", operator: "greater-than", value: 100 }
],
result: {
discount: 0.20, // ✅ Type-safe
code: "PREMIUM20", // ✅ Type-safe
description: "20% premium discount" // ✅ Type-safe
}
}
],
default: { discount: 0, code: "", description: "No discount" }
};
// Evaluation with full type inference
const result = await RuleEngine.evaluate<DiscountResult>(discountRule, orderData);
// result.value is automatically typed as DiscountResult ✅
```
### **Custom Operators Made Easy**
Extend the engine with your business-specific logic:
```typescript
import { OperatorRegistry, BaseOperator } from '@usex/rule-engine';
// 1. Create your custom operator
class IsWeekendOperator extends BaseOperator {
name = 'is-weekend';
category = 'datetime';
evaluate(fieldValue: Date): boolean {
const day = fieldValue.getDay();
return day === 0 || day === 6; // Sunday or Saturday
}
}
class BulkDiscountEligibleOperator extends BaseOperator {
name = 'bulk-discount-eligible';
category = 'business';
evaluate(orderData: any, threshold: number): boolean {
return orderData.quantity >= threshold || orderData.value >= threshold * 10;
}
}
// 2. Register your operators
OperatorRegistry.register(new IsWeekendOperator());
OperatorRegistry.register(new BulkDiscountEligibleOperator());
// 3. Use them in your rules immediately
const weekendRule = {
conditions: {
and: [
{ field: "$.currentDate", operator: "is-weekend", value: true },
{ field: "$.order", operator: "bulk-discount-eligible", value: 10 }
],
result: {
discount: 0.25,
reason: "Weekend bulk discount!"
}
}
};
// 4. Full TypeScript support for your custom operators
const result = await RuleEngine.evaluate(weekendRule, {
currentDate: new Date(),
order: { quantity: 15, value: 200 }
}); // ✅ Fully typed, including custom operators
```
### **Advanced Generic Usage**
```typescript
// Define complex result types
interface AccessControlResult {
allowed: boolean;
permissions: string[];
level: 'admin' | 'user' | 'guest';
expiresAt?: Date;
}
interface UserData {
role: string;
department: string;
clearanceLevel: number;
}
// Generic rule with both input and output types
const accessRule: Rule<AccessControlResult, UserData> = {
conditions: [
{
and: [
{ field: "role", operator: "equals", value: "admin" },
{ field: "clearanceLevel", operator: "greater-than", value: 5 }
],
result: {
allowed: true,
permissions: ["read", "write", "delete"],
level: "admin"
}
}
],
default: {
allowed: false,
permissions: [],
level: "guest"
}
};
// Type-safe evaluation with input validation
const userData: UserData = {
role: "admin",
department: "engineering",
clearanceLevel: 8
};
const access = await RuleEngine.evaluate<AccessControlResult, UserData>(
accessRule,
userData
);
// Both input and output are fully typed ✅
```
## 🎬 Quick Start
### Core Engine (Pure JavaScript/TypeScript)
```bash
npm install @usex/rule-engine
```
```typescript
import { RuleEngine } from '@usex/rule-engine';
// Define a discount rule
const discountRule = {
conditions: [
{
// VIP customers get 20% off orders over $100
and: [
{ field: "$.customer.tier", operator: "equals", value: "vip" },
{ field: "$.order.total", operator: "greater-than", value: 100 }
],
result: { discount: 0.20, message: "VIP discount applied! 🎉" }
},
{
// First-time buyers get 10% off orders over $50
and: [
{ field: "$.customer.orderCount", operator: "equals", value: 0 },
{ field: "$.order.total", operator: "greater-than", value: 50 }
],
result: { discount: 0.10, message: "Welcome! First order discount 🎁" }
}
],
default: { discount: 0, message: "No discount available" }
};
// Apply the rule
const orderData = {
customer: { tier: "vip", orderCount: 5 },
order: { total: 150, items: ["laptop", "mouse"] }
};
const result = await RuleEngine.evaluate(discountRule, orderData);
console.log(result);
// { value: { discount: 0.20, message: "VIP discount applied! 🎉" }, isPassed: true }
```
### Visual Builder (React Applications)
```bash
npm install @usex/rule-engine-builder @usex/rule-engine react
```
```tsx
import React, { useState } from 'react';
import { RuleBuilder } from '@usex/rule-engine-builder';
import { RuleEngine } from '@usex/rule-engine';
function App() {
const [rule, setRule] = useState(null);
const availableFields = [
{ name: '$.user.tier', type: 'string', label: 'User Tier' },
{ name: '$.user.age', type: 'number', label: 'User Age' },
{ name: '$.order.total', type: 'number', label: 'Order Total' },
{ name: '$.order.items', type: 'array', label: 'Order Items' }
];
const testData = {
user: { tier: 'premium', age: 28 },
order: { total: 150, items: ['laptop', 'mouse'] }
};
return (
<div className="app">
<h1>Build Your Business Rules Visually</h1>
<RuleBuilder
rule={rule}
onRuleChange={setRule}
availableFields={availableFields}
testData={testData}
theme="auto"
showPreview={true}
showHistory={true}
/>
{rule && (
<button onClick={async () => {
const result = await RuleEngine.evaluate(rule, testData);
console.log('Rule Result:', result);
}}>
Test Rule
</button>
)}
</div>
);
}
```
## 💡 Real-World Examples
### 🛒 E-commerce Pricing Engine
```typescript
const pricingRules = {
conditions: [
{
// Black Friday: 50% off everything
and: [
{ field: "$.event.name", operator: "equals", value: "black-friday" },
{ field: "$.event.active", operator: "equals", value: true }
],
result: { discount: 0.50, code: "BLACKFRIDAY50", expires: "2025-11-30T23:59:59Z" }
},
{
// Bulk orders: tiered discounts
or: [
{ field: "$.cart.quantity", operator: "greater-than", value: 50 },
{ field: "$.cart.value", operator: "greater-than", value: 1000 }
],
result: { discount: 0.15, code: "BULK15", shipping: "free" }
},
{
// New customer welcome
and: [
{ field: "$.customer.orderHistory.length", operator: "equals", value: 0 },
{ field: "$.cart.value", operator: "greater-than", value: 50 }
],
result: { discount: 0.10, code: "WELCOME10", message: "Welcome! Enjoy 10% off your first order 🎉" }
}
],
default: { discount: 0, message: "Regular pricing applies" }
};
```
### 🔐 Dynamic Access Control
```typescript
const accessControlRules = {
conditions: [
{
// Super admin: full access
and: [
{ field: "role", operator: "equals", value: "super-admin" },
{ field: "status", operator: "equals", value: "active" }
],
result: {
permissions: ["read", "write", "delete", "admin"],
level: "unlimited",
expires: null
}
},
{
// Department manager: departmental access during business hours
and: [
{ field: "role", operator: "equals", value: "manager" },
{ field: "department", operator: "exists", value: true },
{ field: "$.currentTime", operator: "time-between", value: ["09:00", "17:00"] }
],
result: {
permissions: ["read", "write"],
level: "department",
scope: "$.department",
expires: "$.session.loginTime + 8h"
}
}
],
default: { permissions: [], level: "none", message: "Access denied" }
};
```
### ✅ Smart Form Validation
```typescript
const registrationValidation = {
conditions: {
and: [
// Email validation
{
field: "email",
operator: "email",
value: true,
message: "Please enter a valid email address"
},
// Strong password requirements
{
and: [
{
field: "password",
operator: "min-length",
value: 8,
message: "Password must be at least 8 characters long"
},
{
field: "password",
operator: "matches",
value: ".*[A-Z].*",
message: "Password must contain at least one uppercase letter"
},
{
field: "password",
operator: "matches",
value: ".*[0-9].*",
message: "Password must contain at least one number"
}
]
},
// Age verification
{
field: "birthDate",
operator: "date-before",
value: "$.today - 18 years",
message: "You must be 18 or older to register"
}
]
}
};
```
## 🔧 Advanced Features
### 🔗 Self-Referencing Magic
Compare fields against other fields dynamically:
```typescript
const budgetRule = {
conditions: {
and: [
// Actual cost must not exceed budget
{
field: "$.project.actualCost",
operator: "less-than-or-equals",
value: "$.project.approvedBudget"
},
// Start date must be before end date
{
field: "$.project.startDate",
operator: "date-before",
value: "$.project.endDate"
}
]
}
};
```
### 🏗️ Fluent Builder Pattern
Construct complex rules programmatically:
```typescript
const complexRule = RuleEngine.builder()
.add({
and: [
{ field: "userType", operator: "equals", value: "premium" },
{ field: "subscriptionActive", operator: "equals", value: true }
],
result: { access: "premium", features: ["analytics", "api", "support"] }
})
.add({
and: [
{ field: "userType", operator: "equals", value: "basic" },
{ field: "trialExpired", operator: "equals", value: false }
],
result: { access: "basic", features: ["dashboard"] }
})
.default({ access: "none", features: [] })
.build(true); // Validate during build
```
### 📊 Rule Introspection
Understand what your rules need:
```typescript
const insights = RuleEngine.introspect(complexRule);
console.log(insights);
// {
// fields: ["userType", "subscriptionActive", "trialExpired"],
// operators: ["equals"],
// possibleResults: [
// { access: "premium", features: ["analytics", "api", "support"] },
// { access: "basic", features: ["dashboard"] },
// { access: "none", features: [] }
// ],
// complexity: "medium",
// estimatedPerformance: "fast"
// }
```
## 🏎️ Performance & Benchmarks
*Real-world performance data from actual benchmark runs (10,000 iterations each)*
### Core Rule Performance
| Operation | Hz (ops/sec) | Avg Time | Performance Grade |
|-----------|-------------|----------|-------------------|
| **Simple Rules (3-5 conditions)** | **~16,900** | **0.059ms** | **🚀 Lightning Fast** |
| Complex Rules (nested evaluation) | ~17,400 | 0.057ms | 🔥 Blazing |
| Complex Rules (priority-based) | ~8,000 | 0.126ms | ⚡ Very Fast |
| Array Operations | ~45,400 | 0.022ms | 🚀 Ultra Fast |
### Advanced Features
| Feature | Hz (ops/sec) | Avg Time | Performance Grade |
|---------|-------------|----------|-------------------|
| **JSONPath Resolution (simple)** | **~55,000** | **0.018ms** | **🔥 Blazing Fast** |
| JSONPath Deep Nested Access | ~54,000 | 0.019ms | 🔥 Blazing Fast |
| JSONPath Array Processing | ~49,500 | 0.020ms | 🚀 Ultra Fast |
| Self-Referencing (complex) | ~33,600 | 0.030ms | 🚀 Excellent |
| Data Mutations (simple) | ~16,300 | 0.061ms | 🚀 Fast |
| Data Mutations (complex) | ~34,100 | 0.029ms | 🚀 Excellent |
### Specialized Operations
| Operation | Hz (ops/sec) | Use Case | Performance |
|-----------|-------------|----------|-------------|
| **Rule Builder (simple)** | **~12,000,000** | Rule Construction | ⚡ Instant |
| Rule Builder (complex) | ~94,300 | Complex Rule Building | 🚀 Very Fast |
| Rule Validation | ~67,000 | Schema Validation | 🔥 Blazing |
| Error Handling | ~1,661,000 | Exception Processing | ⚡ Instant |
### Optimization Tips
1. **Trust Mode**: Skip validation for 20% performance boost
```typescript
const result = await RuleEngine.evaluate(rule, data, true);
```
2. **Batch Processing**: Process multiple records at once
```typescript
const results = await RuleEngine.evaluate(rule, arrayOfData);
```
3. **Operator Selection**: Prefer specific operators over general ones
```typescript
{ operator: "equals" } // ✅ Fast
{ operator: "matches" } // ⚠️ Slower for simple cases
```
## 🔧 Operator Categories
### All 121+ Operators at Your Fingertips
| Category | Count | Examples |
|----------|-------|----------|
| **Comparison** | 6 | `equals`, `greater-than`, `less-than` |
| **String** | 12 | `like`, `starts-with`, `matches` |
| **Numeric** | 11 | `between`, `divisible-by`, `even` |
| **Array** | 12 | `contains`, `contains-any`, `array-length` |
| **Date/Time** | 14 | `date-after`, `date-between`, `time-equals` |
| **Type** | 10 | `string`, `number`, `boolean` |
| **Existence** | 6 | `exists`, `empty`, `null-or-undefined` |
| **Boolean** | 4 | `truthy`, `falsy`, `boolean-string` |
| **Pattern** | 2 | `matches`, `not-matches` |
| **Length** | 8 | `min-length`, `max-length`, `length-between` |
| **Persian** | 6 | `persian-alpha`, `persian-number` |
| **Validation** | 30+ | `email`, `url`, `uuid`, `alpha-numeric` |
### Popular Operators
```typescript
// String operations
{ field: "name", operator: "equals", value: "John" }
{ field: "email", operator: "like", value: "*@gmail.com" }
{ field: "description", operator: "matches", value: "^Product.*" }
// Numeric comparisons
{ field: "age", operator: "greater-than", value: 18 }
{ field: "price", operator: "between", value: [10, 100] }
// Array operations
{ field: "roles", operator: "contains", value: "admin" }
{ field: "tags", operator: "contains-all", value: ["urgent", "review"] }
// Date/time
{ field: "expiryDate", operator: "date-before-now", value: true }
{ field: "openTime", operator: "time-after", value: "09:00" }
// Validation
{ field: "email", operator: "email", value: true }
{ field: "password", operator: "min-length", value: 8 }
```
## 🎓 Complete TypeScript Excellence
### **Built-in Generic Support**
The core package is **100% TypeScript** with comprehensive generic interfaces:
```typescript
// 🛡️ Full generic support for input and output types
interface UserPermissions {
canRead: boolean;
canWrite: boolean;
canDelete: boolean;
level: 'admin' | 'user' | 'guest';
}
interface UserContext {
role: string;
department: string;
active: boolean;
}
// ✅ Type-safe rule with both input/output generics
const accessRule: Rule<UserPermissions, UserContext> = {
conditions: [
{
and: [
{ field: "role", operator: "equals", value: "admin" },
{ field: "active", operator: "equals", value: true }
],
result: {
canRead: true,
canWrite: true,
canDelete: true,
level: "admin" // ✅ Autocomplete & validation
}
}
],
default: {
canRead: false,
canWrite: false,
canDelete: false,
level: "guest" // ✅ Type-safe default
}
};
// ✅ Fully typed evaluation with IntelliSense
const result = await RuleEngine.evaluate<UserPermissions, UserContext>(
accessRule,
{ role: "admin", department: "IT", active: true }
);
// result.value is automatically typed as UserPermissions with full IDE support ✅
```
### **Type-Safe Custom Operators**
Custom operators inherit full TypeScript support:
```typescript
// ✅ Typed custom operator interface
interface CustomOperator<T = any, V = any> {
name: string;
category: string;
evaluate(fieldValue: T, operatorValue: V): boolean;
}
// ✅ Type-safe custom operator implementation
class DateRangeOperator implements CustomOperator<Date, [Date, Date]> {
name = 'date-within-range';
category = 'datetime';
evaluate(fieldValue: Date, [start, end]: [Date, Date]): boolean {
return fieldValue >= start && fieldValue <= end;
}
}
// ✅ Generic operator registration with type safety
OperatorRegistry.register<Date, [Date, Date]>(new DateRangeOperator());
```
## 📚 Documentation
### Core Package
- 📖 **[Core README](./packages/core/README.md)** - Complete API reference and examples
- 🎯 **[Operators Guide](./packages/core/docs/operators.md)** - All 121+ operators with examples
- 💡 **[Best Practices](./packages/core/docs/best-practices.md)** - Production patterns and tips
- 🚀 **[Migration Guide](./packages/core/docs/migration-guide.md)** - Upgrading from other engines
### Builder Package
- 🏗️ **[Builder README](./packages/builder/README.md)** - React components and integration
- 🎨 **[Component Reference](./packages/builder/docs/components.md)** - All UI components
- ⌨️ **[Keyboard Shortcuts](./packages/builder/docs/shortcuts.md)** - Professional navigation
- 🎯 **[Integration Examples](./packages/builder/docs/integration.md)** - Framework guides
### Architecture & Development
- 🏛️ **[Architecture Guide](./docs/architecture.md)** - System design and patterns
- 🛠️ **[Development Setup](./docs/getting-started.md)** - Contributing and development
- 📊 **[Comparison Guide](./docs/comparison.md)** - vs other rule engines
## 🛠️ Development
### Prerequisites
- Node.js >= 18.12.0
- pnpm >= 10.11.0
### Setup
```bash
# Clone the repository
git clone https://github.com/ali-master/rule-engine.git
cd rule-engine
# Install dependencies
pnpm install
# Build all packages
pnpm build
# Run tests
pnpm test
# Run linter
pnpm lint
```
### Package Scripts
| Script | Description |
|--------|-------------|
| `pnpm build` | Build all packages |
| `pnpm test` | Run all tests |
| `pnpm lint` | Lint all packages |
| `pnpm test:types` | Type checking |
| `pnpm test:bench` | Performance benchmarks |
## 🆚 Why Choose This Rule Engine?
| Feature | @usex/rule-engine | json-rules-engine | node-rules |
|---------|-------------------|-------------------|------------|
| Zero Dependencies | ✅ | ❌ | ❌ |
| **TypeScript Native** | **✅ 100% + Generics** | ⚠️ Partial | ❌ |
| **Custom Operators** | **✅ Full Support** | ⚠️ Limited | ❌ |
| JSONPath Support | ✅ | ❌ | ❌ |
| Self-Referencing | ✅ | ❌ | ❌ |
| Visual Builder | ✅ | ❌ | ❌ |
| Generic Support | **✅ Input/Output** | ❌ | ❌ |
| Performance (ops/sec) | 17k+ (55k+ JSONPath) | 45k | 30k |
| Bundle Size | 12KB | 45KB | 38KB |
| Browser Support | ✅ | ✅ | ❌ |
| Rule Introspection | ✅ | ❌ | ❌ |
| Fluent Builder | ✅ | ❌ | ❌ |
## 🤝 Contributing
We love contributions! Whether it's:
- 🐛 Bug reports and fixes
- ✨ New operators or features
- 📖 Documentation improvements
- 🎨 Examples and tutorials
- 🏗️ UI components for the builder
See our [Contributing Guide](./CONTRIBUTING.md) for details.
### How to Contribute
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## 🗺️ Roadmap
### Version 1.0 (Current)
- ✅ Core rule engine with 121+ operators
- ✅ **Full TypeScript support with generics**
- ✅ **Custom operator registration system**
- ✅ Visual rule builder for React
- ✅ Comprehensive documentation
- ✅ Performance optimizations
### Version 1.1 (Q2 2025)
- 🔄 **Enhanced TypeScript utilities** (type guards, validators)
- 🔄 **Operator marketplace** with community operators
- 🔄 Rule templates and marketplace
- 🔄 GraphQL integration
- 🔄 More operator types (geo, financial)
- 🔄 Advanced debugging tools
### Version 2.0 (Q4 2025)
- 🔮 AI-powered rule suggestions
- 🔮 Visual rule debugger
- 🔮 Collaborative editing
- 🔮 Mobile app support
- 🔮 Multi-language operators
## 📄 License
This project is licensed under the MIT License - see the [LICENSE](./LICENCE) file for details.
## 🙏 Acknowledgments
- Thanks to all contributors who have helped shape this project
- Inspired by json-rules-engine and other rule engines
- Built with modern web technologies and best practices
## 💬 Support & Community
- 📖 **[Documentation](./packages/core/docs)** - Complete guides and references
- 🐛 **[Issue Tracker](https://github.com/ali-master/rule-engine/issues)** - Bug reports and feature requests
- 💭 **[Discussions](https://github.com/ali-master/rule-engine/discussions)** - Community Q&A and ideas
- 📧 **[Email](mailto:ali_4286@live.com)** - Direct contact
## Star History
<a href="https://www.star-history.com/#ali-master/rule-engine&Date&LogScale">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=ali-master/rule-engine&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=ali-master/rule-engine&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=ali-master/rule-engine&type=Date" />
</picture>
</a>
---
<div align="center">
**Built with ❤️ by [Ali Torki](https://github.com/ali-master) for the developer community**
[⭐ Star us on GitHub](https://github.com/ali-master/rule-engine) • [📦 View on npm](https://www.npmjs.com/package/@usex/rule-engine) • [📖 Read the Docs](./packages/core/README.md)
**Making complex business logic simple, one rule at a time.**
</div>
================================================
FILE: assets/BRAND_ASSETS.md
================================================
# @usex/rule-engine Brand Assets
> **Official brand assets and usage guidelines for the @usex/rule-engine project**
## 📦 Available Assets
### Package Logos
#### @packages/core
- **Purpose**: Rule evaluation and processing engine
- **Design Concept**: IF-THEN-ELSE decision flow diagram
- **Files**:
- `core-logo.svg` (vector, recommended)
- `core-logo.png` (raster, 200×200px)
#### @packages/builder
- **Purpose**: Visual rule construction interface
- **Design Concept**: Drag & drop interface with component palette
- **Files**:
- `builder-logo.svg` (vector, recommended)
- `builder-logo.png` (raster, 200×200px)
### Social Media Preview
- **Purpose**: Social sharing, GitHub repository preview
- **Dimensions**: 1280×640px (optimized for social platforms)
- **Files**:
- `social-preview.svg` (vector, recommended)
- `social-preview.png` (raster, 1280×640px)
## 🎨 Design System
### Color Palette
#### Core Package Colors
```css
/* Primary Gradient: Electric Blue to Purple */
--core-primary: linear-gradient(135deg, #3b82f6 0%, #6366f1 50%, #8b5cf6 100%);
/* Success Path: Green */
--core-success: linear-gradient(135deg, #10b981 0%, #059669 100%);
/* Error Path: Orange to Red */
--core-error: linear-gradient(135deg, #f59e0b 0%, #ef4444 100%);
```
#### Builder Package Colors
```css
/* Primary Gradient: Orange to Pink */
--builder-primary: linear-gradient(135deg, #f97316 0%, #ec4899 50%, #8b5cf6 100%);
/* Creation Accent: Emerald to Cyan */
--builder-accent: linear-gradient(135deg, #10b981 0%, #06b6d4 100%);
/* Active Element: Golden */
--builder-active: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);
```
### Typography
- **Primary**: `system-ui, -apple-system, sans-serif`
- **Monospace**: `monospace` (for code elements)
- **Weights**: 400 (regular), 500 (medium), 600 (semibold), 700 (bold), 900 (black)
### Visual Effects
- **Glow**: `filter: drop-shadow(0 0 8px rgba(color, 0.4))`
- **Shadow**: `filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.25))`
- **Border Radius**: `8px` (small), `12px` (medium), `16px` (large)
## 📐 Logo Specifications
### Core Logo Elements
- **Central Diamond**: IF decision node with white "IF" text
- **Input Box**: Data input with `{data}` placeholder text
- **Flow Paths**: TRUE (green) and FALSE (orange/red) branches
- **Output Circles**: Success (✓) and error (✗) indicators
- **Animated Flow**: Data processing visualization
### Builder Logo Elements
- **Canvas Area**: Workspace with dotted border
- **Draggable Components**: AND, >, $.user.age blocks with trails
- **Drop Zones**: Dashed outline target areas
- **Component Palette**: Available building blocks
- **Hand Cursor**: Interaction indicator with motion trail
### Sizing Guidelines
| Usage | Minimum Size | Recommended Size | Maximum Size |
|-------|-------------|------------------|-------------|
| Favicon | 16×16px | 32×32px | 64×64px |
| Navigation | 24×24px | 32×32px | 48×48px |
| Cards/Lists | 48×48px | 64×64px | 96×96px |
| Headers | 96×96px | 120×120px | 200×200px |
| Hero Sections | 120×120px | 200×200px | 400×400px |
## ✅ Usage Guidelines
### ✅ DO
- Use the SVG versions for all digital applications
- Maintain the original aspect ratio (1:1 square)
- Ensure adequate clear space around logos (minimum 20% of logo width)
- Use logos on contrasting backgrounds for optimal visibility
- Respect the functional design concept when explaining the packages
### ❌ DON'T
- Stretch, skew, or distort the logos
- Change the colors or gradients
- Add additional elements or text to the logos
- Use low-resolution PNG files when SVG is available
- Place logos on busy backgrounds without sufficient contrast
- Remove or modify the animated elements in digital contexts
## 📱 Platform-Specific Usage
### GitHub Repository
- **README Header**: Use `core-logo.svg` at 120×120px
- **Social Preview**: Use `social-preview.svg` (1280×640px)
- **Issue Templates**: Small logo usage at 32×32px
### NPM Package
- **Package Icon**: Use `core-logo.png` (200×200px)
- **Documentation**: Use `core-logo.svg` with flexible sizing
### Social Media
- **Twitter/X Cards**: Use `social-preview.svg`
- **LinkedIn Posts**: Use `social-preview.svg`
- **Avatar/Profile**: Use individual package logos at 400×400px
### Documentation Sites
- **Header Logo**: 120×120px recommended
- **Navigation**: 32×32px recommended
- **Footer**: 48×48px recommended
## 🔗 Logo Meaning & Messaging
### Core Package
**Visual Message**: "I process your data through decision logic"
- The diamond shape represents decision points (standard flowchart symbol)
- The branching paths show TRUE/FALSE evaluation
- The animated flow demonstrates active processing
- Colors indicate different outcomes (green=success, red=error)
### Builder Package
**Visual Message**: "I help you build rules visually"
- The canvas represents the workspace
- Draggable blocks show the construction process
- Drop zones indicate where components can be placed
- The hand cursor shows user interaction
## 📄 File Formats & Technical Specs
### SVG Files (Recommended)
- **Viewbox**: 200×200 (logos), 1280×640 (social preview)
- **Optimization**: Minified and compressed
- **Animations**: CSS animations for web compatibility
- **Compatibility**: All modern browsers, design tools
### PNG Files (Fallback)
- **Resolution**: 200×200px (logos), 1280×640px (social preview)
- **Format**: PNG-24 with transparency
- **Compression**: Optimized for web delivery
- **Background**: Transparent
## 📞 Brand Contact
For questions about brand usage, asset requests, or licensing:
- **Repository**: [github.com/ali-master/rule-engine](https://github.com/ali-master/rule-engine)
- **Issues**: [Brand Asset Issues](https://github.com/ali-master/rule-engine/issues/new?labels=brand,assets)
- **Maintainer**: [@ali-master](https://github.com/ali-master)
---
**Last Updated**: June 02, 2025
**Version**: 2.1.0
**License**: MIT License (same as project)
**Made with ❤️ by [Ali Torki](https://github.com/ali-master)**
================================================
FILE: docs/architecture.md
================================================
# Architecture Overview
This document provides a comprehensive overview of the Rule Engine architecture, design decisions, and implementation details.
## Table of Contents
- [System Architecture](#system-architecture)
- [Package Structure](#package-structure)
- [Core Components](#core-components)
- [Design Patterns](#design-patterns)
- [Data Flow](#data-flow)
- [Performance Architecture](#performance-architecture)
- [Security Architecture](#security-architecture)
## System Architecture
### High-Level Architecture
```
┌─────────────────────────────────────────────────────────────────┐
│ Application Layer │
│ ┌─────────────────┐ ┌──────────────────┐ ┌───────────────┐ │
│ │ React Apps │ │ Node.js Apps │ │ API Services │ │
│ └────────┬────────┘ └────────┬─────────┘ └───────┬───────┘ │
└───────────┼────────────────────┼─────────────────────┼─────────┘
│ │ │
┌───────────┼────────────────────┼─────────────────────┼─────────┐
│ │ Rule Engine SDK Layer │ │
│ ┌────────▼────────┐ ┌────────▼─────────┐ ┌──────▼───────┐ │
│ │ UI Builder │ │ Rule Engine │ │ Validators │ │
│ │ (@usex/builder)│ │ (@usex/core) │ │ & Utils │ │
│ └─────────────────┘ └──────────────────┘ └──────────────┘ │
└────────────────────────────────────────────────────────────────┘
```
### Component Architecture
```
Rule Engine Core
├── Services
│ ├── RuleEngine # Main evaluation engine
│ ├── Evaluator # Rule evaluation logic
│ ├── Validator # Rule validation
│ ├── Introspector # Rule analysis
│ ├── Builder # Programmatic rule construction
│ └── ObjectDiscovery # JSONPath utilities
│
├── Operators
│ ├── Comparison # Basic comparisons
│ ├── String # String operations
│ ├── Numeric # Number operations
│ ├── Array # Array/collection operations
│ ├── Date/Time # Temporal operations
│ ├── Type # Type validation
│ └── Custom # User-defined operators
│
└── Types & Utils
├── Rule Types # Core type definitions
├── JSONPath Utils # Path resolution
├── Date Utils # Date handling
└── Error Utils # Error management
```
## Package Structure
### Monorepo Organization
| Directory | Purpose | Key Contents |
|-----------|---------|--------------|
| `/packages/core` | Core rule engine | Engine, operators, types |
| `/packages/builder` | React UI components | Visual builder, inputs |
| `/apps/web` | Documentation site | Docs, examples, guides |
| `/docs` | Project documentation | Architecture, guides |
| `/scripts` | Build scripts | Automation, tooling |
### Package Dependencies
```mermaid
graph TD
A[@usex/rule-engine-builder] --> B[@usex/rule-engine]
C[React Apps] --> A
D[Node.js Apps] --> B
E[API Services] --> B
```
### Module Structure
```typescript
// Core Package Exports
export {
// Main Classes
RuleEngine,
ObjectDiscovery,
// Types
RuleType,
Condition,
Constraint,
EvaluationResult,
// Enums
OperatorsType,
ConditionType,
// Utilities
validateRule,
introspectRule,
buildRule
} from '@usex/rule-engine';
// Builder Package Exports
export {
// Components
TreeRuleBuilder,
ModernRuleBuilder,
RuleEvaluator,
HistoryViewer,
// Hooks
useEnhancedRuleStore,
useFieldDiscovery,
useKeyboardShortcuts,
// Types
FieldConfig,
ThemeConfig
} from '@usex/rule-engine-builder';
```
## Core Components
### RuleEngine Service
The main service responsible for rule evaluation:
```typescript
class RuleEngine {
// Singleton instance
private static instance: RuleEngine;
// Mutation system for data preprocessing
private mutations: Map<string, MutationFunction>;
// Cache for performance
private cache: Map<string, any>;
// Core methods
async evaluate<T>(rule: RuleType<T>, criteria: any): Promise<EvaluationResult<T>>;
validate(rule: RuleType<any>): ValidationResult;
introspect(rule: RuleType<any>): IntrospectionResult;
// Static API
static evaluate<T>(...args): Promise<EvaluationResult<T>>;
static validate(...args): ValidationResult;
static builder(): RuleBuilder;
}
```
### Evaluator Pipeline
```
Input Data → Mutations → Validation → Evaluation → Result
↓ ↓ ↓ ↓ ↓
Criteria Transform Type Check Apply Rules Output
```
### Operator System
| Layer | Description | Example |
|-------|-------------|---------|
| **Registration** | Operator definition | `{ name: 'equals', evaluate: (a, b) => a === b }` |
| **Categorization** | Logical grouping | Comparison, String, Numeric, etc. |
| **Type Safety** | Input/output types | `<T>(field: T, value: T) => boolean` |
| **Validation** | Pre-evaluation checks | Value type, range, format |
| **Evaluation** | Actual comparison | Field value vs constraint value |
## Design Patterns
### 1. Strategy Pattern
Used for operator evaluation:
```typescript
interface OperatorStrategy {
evaluate(fieldValue: any, constraintValue: any): boolean;
}
class EqualsOperator implements OperatorStrategy {
evaluate(fieldValue: any, constraintValue: any): boolean {
return fieldValue === constraintValue;
}
}
class OperatorFactory {
private strategies: Map<string, OperatorStrategy>;
getOperator(type: string): OperatorStrategy {
return this.strategies.get(type);
}
}
```
### 2. Builder Pattern
For programmatic rule construction:
```typescript
const rule = RuleEngine.builder()
.add({
and: [
{ field: 'age', operator: 'greater-than', value: 18 },
{ field: 'country', operator: 'equals', value: 'US' }
],
result: { allowed: true }
})
.default({ allowed: false })
.build();
```
### 3. Observer Pattern
Used in the UI for state management:
```typescript
class RuleStore {
private listeners: Set<() => void> = new Set();
private state: RuleState;
subscribe(listener: () => void) {
this.listeners.add(listener);
return () => this.listeners.delete(listener);
}
notify() {
this.listeners.forEach(listener => listener());
}
}
```
### 4. Command Pattern
For undo/redo functionality:
```typescript
interface Command {
execute(): void;
undo(): void;
}
class UpdateRuleCommand implements Command {
constructor(
private store: RuleStore,
private oldRule: Rule,
private newRule: Rule
) {}
execute() {
this.store.setRule(this.newRule);
}
undo() {
this.store.setRule(this.oldRule);
}
}
```
## Data Flow
### Rule Evaluation Flow
```
1. Input Reception
└── Receive rule and criteria
2. Mutation Phase
├── Apply registered mutations
└── Transform criteria data
3. Validation Phase
├── Validate rule structure
├── Check operator validity
└── Verify field paths
4. Resolution Phase
├── Resolve JSONPath expressions
├── Extract field values
└── Handle nested objects
5. Evaluation Phase
├── Apply constraints
├── Evaluate conditions
└── Aggregate results
6. Result Composition
└── Return evaluation result
```
### State Management Flow
```
User Action → Component → Hook → Store → State Update → UI Update
↓ ↓ ↓ ↓ ↓ ↓
Change Handler Action Reducer New State Re-render
```
## Performance Architecture
### Optimization Strategies
| Strategy | Implementation | Impact |
|----------|----------------|--------|
| **Caching** | Memoize evaluation results | 40% faster for repeated rules |
| **Lazy Evaluation** | Stop on first failure | 60% faster for failing rules |
| **Path Optimization** | Pre-compile JSONPath | 30% faster path resolution |
| **Batch Processing** | Evaluate multiple items | 50% throughput increase |
| **Trust Mode** | Skip validation | 20% faster for trusted rules |
### Memory Management
```typescript
class CacheManager {
private cache: LRUCache<string, any>;
private maxSize: number = 1000;
set(key: string, value: any) {
if (this.cache.size >= this.maxSize) {
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
this.cache.set(key, value);
}
}
```
### Concurrency Model
```typescript
class BatchEvaluator {
async evaluateBatch<T>(
rule: RuleType<T>,
items: any[],
concurrency: number = 10
): Promise<EvaluationResult<T>[]> {
const chunks = chunk(items, concurrency);
const results = [];
for (const chunk of chunks) {
const chunkResults = await Promise.all(
chunk.map(item => this.evaluate(rule, item))
);
results.push(...chunkResults);
}
return results;
}
}
```
## Security Architecture
### Input Validation
| Layer | Protection | Implementation |
|-------|------------|----------------|
| **Schema Validation** | Rule structure | JSON Schema validation |
| **Type Checking** | Data types | TypeScript + runtime checks |
| **Path Validation** | JSONPath safety | Whitelist allowed paths |
| **Operator Validation** | Valid operators | Operator registry check |
| **Value Sanitization** | Input cleaning | XSS prevention, type coercion |
### Security Patterns
```typescript
class SecurityValidator {
// Prevent prototype pollution
validatePath(path: string): boolean {
const dangerous = ['__proto__', 'constructor', 'prototype'];
return !dangerous.some(d => path.includes(d));
}
// Limit complexity
validateComplexity(rule: RuleType): boolean {
const depth = this.calculateDepth(rule);
const conditions = this.countConditions(rule);
return depth <= MAX_DEPTH && conditions <= MAX_CONDITIONS;
}
// Sanitize regex patterns
validateRegex(pattern: string): boolean {
try {
new RegExp(pattern);
return !pattern.includes('(?<') && // No lookbehind
!pattern.includes('{1000,}'); // No large repetitions
} catch {
return false;
}
}
}
```
### Access Control Integration
```typescript
interface RuleAccessControl {
canCreate: (user: User) => boolean;
canRead: (user: User, rule: Rule) => boolean;
canUpdate: (user: User, rule: Rule) => boolean;
canDelete: (user: User, rule: Rule) => boolean;
canEvaluate: (user: User, rule: Rule) => boolean;
}
class RuleEngineWithACL extends RuleEngine {
constructor(private acl: RuleAccessControl) {
super();
}
async evaluate(rule: RuleType, criteria: any, user: User) {
if (!this.acl.canEvaluate(user, rule)) {
throw new Error('Access denied');
}
return super.evaluate(rule, criteria);
}
}
```
## Extension Architecture
### Plugin System
```typescript
interface RuleEnginePlugin {
name: string;
version: string;
// Lifecycle hooks
onInit?(engine: RuleEngine): void;
beforeEvaluate?(rule: RuleType, criteria: any): void;
afterEvaluate?(result: EvaluationResult): void;
// Extension points
operators?: Record<string, OperatorDefinition>;
mutations?: Record<string, MutationFunction>;
validators?: Record<string, ValidatorFunction>;
}
class PluginManager {
private plugins: Map<string, RuleEnginePlugin> = new Map();
register(plugin: RuleEnginePlugin) {
this.plugins.set(plugin.name, plugin);
plugin.onInit?.(this.engine);
}
}
```
### Custom Operator Architecture
```typescript
interface CustomOperator {
name: string;
category: string;
description: string;
// Type constraints
acceptedFieldTypes: FieldType[];
acceptedValueTypes: ValueType[];
// Validation
validate(value: any): ValidationResult;
// Evaluation
evaluate(fieldValue: any, constraintValue: any): boolean;
// UI hints
ui?: {
icon?: string;
color?: string;
inputComponent?: React.ComponentType;
};
}
```
## Future Architecture Considerations
### Scalability
- **Distributed Evaluation**: Rule evaluation across multiple workers
- **Rule Compilation**: Compile rules to optimized JavaScript
- **Streaming Support**: Process data streams with rules
- **Edge Computing**: Run rules at the edge for low latency
### Extensibility
- **Plugin Marketplace**: Community-contributed operators and plugins
- **Rule Templates**: Reusable rule patterns
- **AI Integration**: ML-powered rule suggestions
- **Visual Debugging**: Step-through rule evaluation
---
For more technical details, see the [API Reference](../packages/core/docs/api-reference.md).
================================================
FILE: docs/comparison.md
================================================
# Rule Engine Comparison
This document compares @usex/rule-engine with other popular rule engines to help you make an informed decision.
## Table of Contents
- [Feature Comparison](#feature-comparison)
- [Performance Comparison](#performance-comparison)
- [API Comparison](#api-comparison)
- [Use Case Comparison](#use-case-comparison)
- [Migration Guides](#migration-guides)
## Feature Comparison
### Overall Feature Matrix
| Feature | @usex/rule-engine | json-rules-engine | node-rules | nools | drools |
|---------|-------------------|-------------------|------------|-------|--------|
| **Language** | TypeScript/JS | JavaScript | JavaScript | JavaScript | Java |
| **JSON-based DSL** | ✅ Yes | ✅ Yes | ❌ Code-based | ⚠️ Partial | ⚠️ DRL |
| **Visual Builder** | ✅ Built-in | ❌ No | ❌ No | ❌ No | ⚠️ External |
| **TypeScript Support** | ✅ Native | ⚠️ @types | ❌ No | ❌ No | N/A |
| **Browser Support** | ✅ Yes | ✅ Yes | ✅ Yes | ❌ No | ❌ No |
| **JSONPath** | ✅ Yes | ❌ No | ❌ No | ❌ No | ❌ No |
| **Operators Count** | 121+ | ~20 | ~15 | ~10 | 50+ |
| **Async Support** | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
| **History/Undo** | ✅ Built-in | ❌ No | ❌ No | ❌ No | ❌ No |
| **Real-time Testing** | ✅ Built-in | ❌ No | ❌ No | ❌ No | ⚠️ External |
| **Dependencies** | 0 (core) | 0 | 2 | 3 | Many |
| **Bundle Size** | 42KB | 38KB | 45KB | 120KB | N/A |
| **License** | MIT | MIT | MIT | MIT | Apache 2.0 |
### Detailed Feature Breakdown
#### Rule Definition
| Feature | @usex/rule-engine | json-rules-engine | node-rules |
|---------|-------------------|-------------------|------------|
| **JSON Rules** | ✅ Native JSON | ✅ Native JSON | ❌ JavaScript functions |
| **Visual Builder** | ✅ React component | ❌ Manual JSON | ❌ Code only |
| **Rule Validation** | ✅ Built-in | ⚠️ Basic | ❌ Runtime only |
| **Type Safety** | ✅ Full generics | ⚠️ Basic types | ❌ No types |
| **Self-referencing** | ✅ JSONPath refs | ❌ No | ❌ No |
| **Nested Conditions** | ✅ Unlimited | ✅ Limited | ✅ Yes |
#### Operators & Evaluation
| Feature | @usex/rule-engine | json-rules-engine | node-rules |
|---------|-------------------|-------------------|------------|
| **Built-in Operators** | 121+ | ~20 | ~15 |
| **Custom Operators** | ✅ Yes | ✅ Yes | ✅ Yes |
| **Date/Time Ops** | ✅ 14 operators | ⚠️ Basic | ❌ Manual |
| **Array Operations** | ✅ 12 operators | ⚠️ Basic | ❌ Manual |
| **String Operations** | ✅ 12 operators | ⚠️ Basic | ⚠️ Basic |
| **Type Validation** | ✅ 10 operators | ❌ No | ❌ No |
| **Regex Support** | ✅ Native | ⚠️ Custom | ⚠️ Custom |
#### Developer Experience
| Feature | @usex/rule-engine | json-rules-engine | node-rules |
|---------|-------------------|-------------------|------------|
| **Documentation** | ✅ Comprehensive | ✅ Good | ⚠️ Basic |
| **Examples** | ✅ 15+ examples | ✅ 5+ examples | ⚠️ Few |
| **TypeScript** | ✅ Native | ⚠️ @types | ❌ No |
| **IDE Support** | ✅ Full IntelliSense | ⚠️ Partial | ❌ Limited |
| **Testing Utils** | ✅ Built-in | ❌ Manual | ❌ Manual |
| **Debug Mode** | ✅ Yes | ✅ Yes | ⚠️ Basic |
## Performance Comparison
### Benchmark Results
Test setup: 10,000 evaluations, average of 10 runs
| Engine | Simple Rule (5 conditions) | Complex Rule (20 conditions) | Nested Rule (3 levels) |
|--------|---------------------------|------------------------------|------------------------|
| **@usex/rule-engine** | 85ms (~117K/sec) | 250ms (~40K/sec) | 180ms (~55K/sec) |
| **json-rules-engine** | 92ms (~108K/sec) | 310ms (~32K/sec) | 220ms (~45K/sec) |
| **node-rules** | 78ms (~128K/sec) | 280ms (~35K/sec) | 195ms (~51K/sec) |
| **nools** | 125ms (~80K/sec) | 420ms (~23K/sec) | 350ms (~28K/sec) |
### Memory Usage
| Engine | Idle | 1K Rules | 10K Rules | 100K Rules |
|--------|------|----------|-----------|------------|
| **@usex/rule-engine** | 12MB | 25MB | 120MB | 980MB |
| **json-rules-engine** | 10MB | 28MB | 150MB | 1.2GB |
| **node-rules** | 15MB | 35MB | 180MB | 1.5GB |
| **nools** | 25MB | 60MB | 350MB | 3GB |
### Optimization Features
| Feature | @usex/rule-engine | json-rules-engine | node-rules |
|---------|-------------------|-------------------|------------|
| **Lazy Evaluation** | ✅ Yes | ✅ Yes | ⚠️ Partial |
| **Result Caching** | ✅ Built-in | ❌ Manual | ❌ Manual |
| **Batch Processing** | ✅ Native | ❌ Manual | ❌ Manual |
| **Trust Mode** | ✅ Skip validation | ❌ No | ❌ No |
| **Parallel Eval** | ✅ Promise.all | ✅ Promise.all | ⚠️ Limited |
## API Comparison
### Rule Definition Syntax
#### @usex/rule-engine
```javascript
{
conditions: {
and: [
{ field: "age", operator: "greater-than", value: 18 },
{ field: "status", operator: "equals", value: "active" }
]
},
default: { value: false }
}
```
#### json-rules-engine
```javascript
{
conditions: {
all: [{
fact: 'age',
operator: 'greaterThanInclusive',
value: 18
}, {
fact: 'status',
operator: 'equal',
value: 'active'
}]
},
event: {
type: 'allow-access',
params: { message: 'Access granted' }
}
}
```
#### node-rules
```javascript
{
name: "access-rule",
condition: function(R) {
R.when(this.age >= 18 && this.status === 'active');
},
consequence: function(R) {
this.result = true;
R.stop();
}
}
```
### Evaluation API
| Method | @usex/rule-engine | json-rules-engine | node-rules |
|--------|-------------------|-------------------|------------|
| **Basic Eval** | `RuleEngine.evaluate(rule, data)` | `engine.run(facts)` | `R.execute(fact)` |
| **Boolean Check** | `RuleEngine.checkIsPassed(rule, data)` | Manual check | Manual check |
| **Result Only** | `RuleEngine.getEvaluateResult(rule, data)` | Manual extract | Manual extract |
| **Batch Eval** | `RuleEngine.evaluate(rule, dataArray)` | Loop manually | Loop manually |
| **Validation** | `RuleEngine.validate(rule)` | No built-in | No built-in |
## Use Case Comparison
### Best For
| Use Case | Best Choice | Reason |
|----------|-------------|--------|
| **Complex Business Rules** | @usex/rule-engine | Most operators, visual builder |
| **Simple Boolean Logic** | node-rules | Lightweight, fast |
| **Event-driven Systems** | json-rules-engine | Event-based design |
| **Enterprise Java** | drools | Java ecosystem |
| **Visual Rule Building** | @usex/rule-engine | Built-in React components |
| **Browser Applications** | @usex/rule-engine | Zero deps, small bundle |
| **Microservices** | @usex/rule-engine or json-rules-engine | JSON portability |
### Feature Requirements
| Need | Recommended | Why |
|------|-------------|---------------------------|
| **Visual Builder UI** | @usex/rule-engine | Only one with built-in UI |
| **JSONPath Support** | @usex/rule-engine | Native JSONPath support |
| **TypeScript** | @usex/rule-engine | Native TypeScript |
| **Many Operators** | @usex/rule-engine | 121+ built-in operators |
| **Simple Rules** | node-rules or json-rules-engine | Simpler API |
| **Java Integration** | drools | JVM-based |
## Migration Guides
### From json-rules-engine
Key differences:
- `fact` → `field`
- `all/any` → `and/or`
- `event` → `result` in conditions or `default`
```javascript
// json-rules-engine
{
conditions: {
all: [{
fact: 'temperature',
operator: 'greaterThan',
value: 100
}]
},
event: { type: 'hot-alert' }
}
// @usex/rule-engine
{
conditions: {
and: [{
field: 'temperature',
operator: 'greater-than',
value: 100
}],
result: { alert: 'hot-alert' }
}
}
```
### From node-rules
Key differences:
- Function-based → JSON-based
- `this` context → explicit field paths
- Consequences → results
```javascript
// node-rules
{
condition: function(R) {
R.when(this.price > 100 && this.category === 'electronics');
},
consequence: function(R) {
this.discount = 0.10;
R.stop();
}
}
// @usex/rule-engine
{
conditions: {
and: [
{ field: 'price', operator: 'greater-than', value: 100 },
{ field: 'category', operator: 'equals', value: 'electronics' }
],
result: { discount: 0.10 }
}
}
```
### From nools
Key differences:
- Flow-based → Condition-based
- Session management → Stateless evaluation
- Facts → Direct data objects
```javascript
// nools
flow.rule("Discount", [
Customer, "c", "c.type == 'premium'",
Order, "o", "o.total > 100"
], function(facts) {
facts.o.discount = 0.20;
});
// @usex/rule-engine
{
conditions: {
and: [
{ field: 'customer.type', operator: 'equals', value: 'premium' },
{ field: 'order.total', operator: 'greater-than', value: 100 }
],
result: { discount: 0.20 }
}
}
```
## Decision Matrix
### Quick Decision Guide
Choose **@usex/rule-engine** if you need:
- ✅ Visual rule builder UI
- ✅ Comprehensive operator set (121+)
- ✅ JSONPath support
- ✅ TypeScript-first design
- ✅ Browser compatibility
- ✅ History/undo functionality
Choose **json-rules-engine** if you need:
- ✅ Event-driven architecture
- ✅ Proven production stability
- ✅ Simple fact-based rules
- ❌ Don't need UI components
Choose **node-rules** if you need:
- ✅ Maximum performance
- ✅ Simple boolean logic
- ✅ Programmatic rule definition
- ❌ Don't need complex operators
Choose **drools** if you need:
- ✅ Java/JVM environment
- ✅ Enterprise features
- ✅ BRMS capabilities
- ❌ Not using JavaScript
## Summary
@usex/rule-engine offers the most comprehensive feature set for JavaScript/TypeScript applications, especially when visual rule building and extensive operator support are required. While other engines may excel in specific areas (performance, simplicity, or ecosystem), @usex/rule-engine provides the best overall developer experience and flexibility for modern web applications.
---
For detailed migration instructions, see the [Migration Guide](../packages/core/docs/migration-guide.md).
================================================
FILE: docs/getting-started.md
================================================
# Getting Started Guide
Welcome to the Rule Engine! This guide will help you get up and running quickly with both the core engine and the visual builder.
## Table of Contents
- [Installation](#installation)
- [Your First Rule](#your-first-rule)
- [Understanding Rules](#understanding-rules)
- [Using the Visual Builder](#using-the-visual-builder)
- [Common Patterns](#common-patterns)
- [Next Steps](#next-steps)
## Installation
### Core Engine Only
If you only need the rule evaluation engine:
```bash
npm install @usex/rule-engine
```
### With Visual Builder
For the complete experience with UI components:
```bash
npm install @usex/rule-engine @usex/rule-engine-builder
```
### Peer Dependencies
The builder requires React 18 or 19:
```json
{
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0"
}
}
```
## Your First Rule
### Basic Example
Let's create a simple rule to check if a user is eligible for a discount:
```typescript
import { RuleEngine } from '@usex/rule-engine';
// Define the rule
const discountRule = {
conditions: {
and: [
{ field: "age", operator: "greater-than", value: 18 },
{ field: "membershipLevel", operator: "equals", value: "gold" }
]
},
default: { value: false }
};
// Test data
const customer = {
age: 25,
membershipLevel: "gold",
totalPurchases: 1500
};
// Evaluate the rule
const result = await RuleEngine.evaluate(discountRule, customer);
console.log(result);
// { value: true, isPassed: true }
```
### Understanding the Result
The evaluation returns an object with:
| Property | Type | Description |
|----------|------|-------------|
| `value` | `any` | The result value (from condition or default) |
| `isPassed` | `boolean` | Whether any condition matched |
| `message` | `string?` | Optional message from constraints |
## Understanding Rules
### Rule Structure
Every rule has two main parts:
```typescript
interface Rule {
conditions: Condition | Condition[]; // What to evaluate
default?: any; // Fallback if no match
}
```
### Conditions
Conditions group constraints using logical operators:
```typescript
// AND - All must match
{
and: [
{ field: "age", operator: "greater-than", value: 21 },
{ field: "country", operator: "equals", value: "US" }
]
}
// OR - Any must match
{
or: [
{ field: "role", operator: "equals", value: "admin" },
{ field: "role", operator: "equals", value: "moderator" }
]
}
// NONE - None must match
{
none: [
{ field: "status", operator: "equals", value: "banned" },
{ field: "status", operator: "equals", value: "suspended" }
]
}
```
### Constraints
The basic building blocks:
```typescript
interface Constraint {
field: string; // What to check
operator: string; // How to check
value?: any; // What to compare against
message?: string; // Optional validation message
}
```
## Using the Visual Builder
### Basic Setup
```tsx
import { TreeRuleBuilder } from '@usex/rule-engine-builder';
import '@usex/rule-engine-builder/styles';
function App() {
const [rule, setRule] = useState(null);
const handleRuleChange = (newRule) => {
setRule(newRule);
console.log('Rule updated:', newRule);
};
return (
<div className="app">
<TreeRuleBuilder
onChange={handleRuleChange}
showJsonViewer={true}
showToolbar={true}
/>
{rule && (
<div className="result">
<h3>Generated Rule:</h3>
<pre>{JSON.stringify(rule, null, 2)}</pre>
</div>
)}
</div>
);
}
```
### With Custom Fields
Define your business fields:
```tsx
const fields = [
{
name: 'customer.tier',
label: 'Customer Tier',
type: 'string',
group: 'Customer',
values: [
{ value: 'bronze', label: 'Bronze' },
{ value: 'silver', label: 'Silver' },
{ value: 'gold', label: 'Gold' }
]
},
{
name: 'order.total',
label: 'Order Total',
type: 'number',
group: 'Order'
},
{
name: 'order.items.length',
label: 'Item Count',
type: 'number',
group: 'Order'
}
];
<TreeRuleBuilder
fields={fields}
onChange={handleRuleChange}
/>
```
### With Sample Data
Provide sample data for testing:
```tsx
const sampleData = {
customer: {
tier: 'gold',
joinDate: '2023-01-15',
totalSpent: 2500
},
order: {
total: 150,
items: ['item1', 'item2', 'item3']
}
};
<TreeRuleBuilder
fields={fields}
sampleData={sampleData}
onChange={handleRuleChange}
showJsonViewer={true}
/>
```
## Common Patterns
### 1. Discount Rules
```typescript
const discountRule = {
conditions: [
// VIP customers get 20% off
{
and: [
{ field: "customer.tier", operator: "equals", value: "vip" },
{ field: "order.total", operator: "greater-than", value: 100 }
],
result: { discount: 0.20, message: "VIP discount applied!" }
},
// New customers get 10% off
{
and: [
{ field: "customer.isNew", operator: "equals", value: true },
{ field: "order.total", operator: "greater-than", value: 50 }
],
result: { discount: 0.10, message: "Welcome discount!" }
}
],
default: { discount: 0, message: "No discount available" }
};
```
### 2. Access Control
```typescript
const accessRule = {
conditions: {
or: [
// Admins have full access
{ field: "user.role", operator: "equals", value: "admin" },
// Owners can access their own resources
{
and: [
{ field: "user.id", operator: "equals", value: "$.resource.ownerId" },
{ field: "resource.public", operator: "equals", value: false }
]
},
// Anyone can access public resources
{ field: "resource.public", operator: "equals", value: true }
]
},
default: { value: false }
};
```
### 3. Form Validation
```typescript
const validationRule = {
conditions: {
and: [
// Email validation
{
field: "email",
operator: "matches",
value: "^[^@]+@[^@]+\\.[^@]+$",
message: "Invalid email format"
},
// Age restriction
{
field: "age",
operator: "between",
value: [18, 100],
message: "Age must be between 18 and 100"
},
// Password strength
{
field: "password",
operator: "matches",
value: "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).{8,}$",
message: "Password must contain uppercase, lowercase, and number"
}
]
}
};
```
### 4. Dynamic Pricing
```typescript
const pricingRule = {
conditions: [
// Bulk discount
{
and: [
{ field: "quantity", operator: "greater-than", value: 100 }
],
result: { multiplier: 0.8, reason: "Bulk discount" }
},
// Premium customer discount
{
and: [
{ field: "customer.tier", operator: "in", value: ["gold", "platinum"] },
{ field: "quantity", operator: "greater-than", value: 10 }
],
result: { multiplier: 0.85, reason: "Premium customer discount" }
}
],
default: { multiplier: 1, reason: "Standard pricing" }
};
```
## Advanced Features
### JSONPath Support
Access nested data with JSONPath:
```typescript
const rule = {
conditions: {
and: [
// Access nested object
{ field: "$.user.profile.age", operator: "greater-than", value: 18 },
// Access array element
{ field: "$.orders[0].total", operator: "greater-than", value: 100 },
// Filter arrays
{ field: "$.items[?(@.price > 50)]", operator: "not-empty", value: true }
]
}
};
```
### Self-referencing
Reference other fields in values:
```typescript
const rule = {
conditions: {
and: [
// Compare two fields
{ field: "$.currentPrice", operator: "less-than", value: "$.maxPrice" },
// Percentage of another field
{ field: "$.discount", operator: "less-than-or-equals", value: "$.maxDiscount" }
]
}
};
```
### Complex Nested Rules
```typescript
const complexRule = {
conditions: {
or: [
// Premium path
{
and: [
{ field: "tier", operator: "equals", value: "premium" },
{
or: [
{ field: "purchases", operator: "greater-than", value: 10 },
{ field: "totalSpent", operator: "greater-than", value: 1000 }
]
}
]
},
// VIP override
{ field: "isVIP", operator: "equals", value: true }
]
}
};
```
## Testing Your Rules
### Simple Test
```typescript
// Quick boolean check
const isPassed = await RuleEngine.checkIsPassed(rule, data);
console.log('Rule passed:', isPassed); // true or false
// Get just the result value
const value = await RuleEngine.getEvaluateResult(rule, data);
console.log('Result:', value); // The actual result value
```
### Batch Testing
```typescript
const testCases = [
{ name: "John", age: 25, tier: "gold" },
{ name: "Jane", age: 17, tier: "silver" },
{ name: "Bob", age: 30, tier: "bronze" }
];
const results = await RuleEngine.evaluate(rule, testCases);
results.forEach((result, index) => {
console.log(`${testCases[index].name}: ${result.isPassed}`);
});
```
### Validation
Always validate rules before using them:
```typescript
const validation = RuleEngine.validate(rule);
if (!validation.isValid) {
console.error('Invalid rule:', validation.error.message);
} else {
// Safe to use the rule
const result = await RuleEngine.evaluate(rule, data);
}
```
## Next Steps
Now that you understand the basics:
1. **Explore Operators**: Check the [Operators Guide](../packages/core/docs/operators.md) for all 126+ operators
2. **Learn Best Practices**: Read the [Best Practices Guide](../packages/core/docs/best-practices.md)
3. **Try Examples**: See real-world [Examples](../packages/builder/docs/examples.md)
4. **Build Complex Rules**: Use the [Visual Builder](../packages/builder/README.md)
5. **Integrate**: Follow the [Integration Guide](../packages/builder/docs/integration.md)
## Quick Reference
### Common Operators
| Operator | Description | Example |
|----------|-------------|---------|
| `equals` | Exact match | `{ operator: "equals", value: "active" }` |
| `greater-than` | Greater than | `{ operator: "greater-than", value: 18 }` |
| `contains` | Array/string contains | `{ operator: "contains", value: "admin" }` |
| `between` | Range check | `{ operator: "between", value: [10, 20] }` |
| `matches` | Regex match | `{ operator: "matches", value: "^[A-Z]" }` |
| `exists` | Field exists | `{ operator: "exists", value: true }` |
| `empty` | Is empty | `{ operator: "empty", value: true }` |
### Keyboard Shortcuts (Builder)
| Shortcut | Action |
|----------|--------|
| `Ctrl/Cmd + Z` | Undo |
| `Ctrl/Cmd + Y` | Redo |
| `Ctrl/Cmd + S` | Save |
| `Ctrl/Cmd + E` | Toggle evaluation |
| `?` | Show help |
---
Ready to build more complex rules? Check out our [Examples](../packages/builder/docs/examples.md) or dive into the [API Reference](../packages/core/docs/api-reference.md)!
================================================
FILE: eslint.config.js
================================================
import antfu from "@antfu/eslint-config";
export default antfu({
formatters: {
prettierOptions: {
printWidth: 100,
trailingComma: "all",
singleQuote: false,
semi: true,
tabWidth: 2,
quoteProps: "as-needed",
jsxSingleQuote: false,
arrowParens: "always",
},
},
stylistic: false,
typescript: true,
name: "rule-engine",
react: true,
gitignore: true,
pnpm: false,
jsonc: false,
}).append({
ignores: [
"README.md",
"packages/*/README.md",
"packages/*/CHANGELOG.md",
"packages/*/dist",
"packages/*/dist-demo",
"packages/*/node_modules",
"packages/*/coverage",
"**/*.json",
],
files: ["./packages/**/*.ts", "./packages/**/*.tsx"],
rules: {
eqeqeq: "off",
"prefer-regex-literals": "off",
"unicorn/number-literal-case": "off",
"regexp/no-dupe-characters-character-class": "off",
"no-misleading-character-class": "off",
"regexp/no-misleading-unicode-character": "off",
"regexp/no-obscure-range": "off",
"react-refresh/only-export-components": "off",
"no-labels": "off",
"no-cond-assign": "off",
"no-async-promise-executor": "off",
"no-new": "off",
"no-console": "off",
"antfu/top-level-function": "off",
"ts/no-unsafe-function-type": "off",
"perfectionist/sort-imports": "off",
"ts/explicit-function-return-type": "off",
"regexp/no-unused-capturing-group": "off",
"node/prefer-global/buffer": "off",
"node/prefer-global/process": "off",
"no-throw-literal": "off",
"ts/ban-ts-comment": "off",
"ts/method-signature-style": "off",
"ts/no-non-null-asserted-optional-chain": "off",
"react-hooks-extra/no-direct-set-state-in-use-effect": "off",
"react/no-array-index-key": "off",
"perfectionist/sort-named-imports": ["error", { order: "desc" }],
},
});
================================================
FILE: knip.json
================================================
{
"$schema": "https://unpkg.com/knip@5/schema.json",
"project": ["./packages/*/src/**/*.ts"]
}
================================================
FILE: package.json
================================================
{
"name": "rule-engine-monorepo",
"preview": true,
"type": "module",
"packageManager": "pnpm@10.17.1",
"description": "A monorepo of Rule Engine implementation for NodeJS and Browser. It includes a core rule engine and various plugins.",
"author": {
"name": "Ali Torki",
"email": "ali_4286@live.com",
"url": "https://github.com/ali-master"
},
"license": "MIT",
"scripts": {
"build": "pnpm -r build",
"build:demo": "pnpm -r build:demo",
"lint": "pnpm -r lint",
"lint:fix": "pnpm -r lint:fix",
"format:check": "pnpm -r format:check",
"format": "pnpm -r format",
"test:junit": "pnpm -r test:junit",
"test:unit": "pnpm -r test:unit",
"test:types": "pnpm -r test:types",
"test:knip": "pnpm -r test:knip",
"test:coverage": "pnpm -r test:coverage",
"release": "pnpm -r release",
"release:beta": "pnpm -r release:beta",
"postinstall": "simple-git-hooks install"
},
"devDependencies": {
"@antfu/eslint-config": "5.4.1",
"@eslint-react/eslint-plugin": "^1.53.1",
"@types/node": "24.5.2",
"@typescript/native-preview": "7.0.0-dev.20250922.1",
"@vitest/coverage-v8": "^3.2.4",
"@vitest/ui": "^3.2.4",
"changelogithub": "13.16.0",
"cross-env": "^10.0.0",
"eslint": "9.36.0",
"eslint-plugin-format": "^1.0.2",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.21",
"installed-check": "9.3.0",
"knip": "5.64.0",
"lint-staged": "16.2.0",
"prettier": "^3.6.2",
"simple-git-hooks": "2.13.1",
"standard-version": "^9.5.0",
"unbuild": "^3.6.1",
"vitest": "3.2.4"
},
"resolutions": {
"@usex/builder": "workspace:*",
"@usex/rule-engine": "workspace:*"
},
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged"
},
"lint-staged": {
"*.{js,ts,mjs,cjs,json,.*rc}": [
"pnpm lint:fix"
]
}
}
================================================
FILE: packages/builder/.gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-demo
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
================================================
FILE: packages/builder/CHANGELOG.md
================================================
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### 0.0.3 (2025-06-10)
### Features
* **AdvancedFieldInput:** refactor code for improved readability and maintainability ([8e3e1ff](https://github.com/ali-master/rule-engine/commit/8e3e1ff74c3c1dc60128850eb87b57c1cb2ade23))
* **App, TreeRuleBuilder, UndoRedoInfo:** integrate enhanced rule store with undo/redo functionality and keyboard shortcuts ([e85e89b](https://github.com/ali-master/rule-engine/commit/e85e89bebe0fec64d04f370dcf6342aadcd74067))
* **App:** implement rule evaluation feature with UI enhancements ([be42689](https://github.com/ali-master/rule-engine/commit/be42689773b385ac4bb8504920e53483e9977766))
* **builder:** add shadcn ([216c8a7](https://github.com/ali-master/rule-engine/commit/216c8a7ac425e64e3344b9aa441f35bfd64df6d2))
* **Builder:** added the smart builder ui ([eeb9468](https://github.com/ali-master/rule-engine/commit/eeb94685a16863288d6f51d4b4a136e03a41790e))
* **Calendar, DateInput, TreeConstraintEditor:** enhance calendar functionality and add animations ([94404e4](https://github.com/ali-master/rule-engine/commit/94404e49bd607e791721dcc6ba30d7a85d849efb))
* **DateInput, TreeConstraintEditor:** enhance date parsing and add visual field selector ([b9dd735](https://github.com/ali-master/rule-engine/commit/b9dd735a038703c559a9d1f32ba7f0ddbf71a522))
* **Dialog:** refactor dialog components for improved readability and structure ([c530113](https://github.com/ali-master/rule-engine/commit/c530113d58b01f9f3c1ebf916652dff10580d70f))
* **DiffViewer:** add DiffStats component for enhanced property change visualization ([f8f74c5](https://github.com/ali-master/rule-engine/commit/f8f74c57f486c6b426dceae17cbeb059991b9594))
* **EditableJsonViewer:** add keyboard shortcuts for live evaluation and enhance tooltip information ([6cfb41f](https://github.com/ali-master/rule-engine/commit/6cfb41f268b751e50c998ae47741d12585f11d40))
* **EditableJsonViewer:** add live evaluation feature and improve diff visualization ([fc4caee](https://github.com/ali-master/rule-engine/commit/fc4caeeba4d8d63657bf637d5bac1828670e8042))
* **HistoryViewer:** implement history viewer with search, filter, and version comparison features ([77c52c0](https://github.com/ali-master/rule-engine/commit/77c52c0d51aa7628a4e1180f19125c87dbe47e8a))
* **HistoryViewer:** integrate ResizablePanel for improved layout flexibility ([bc7b918](https://github.com/ali-master/rule-engine/commit/bc7b9185f9c3db1a4a91a16201a634b37f3d0de0))
* **HistoryViewer:** replace select element with custom Select component for action filtering ([ffc7b07](https://github.com/ali-master/rule-engine/commit/ffc7b0799e72816e5da692d47e8393cd668075c6))
* **JsonViewer:** add highlight for logical operators and improve scrollbar handling ([9f159bc](https://github.com/ali-master/rule-engine/commit/9f159bc9f6a33d2f479e27be225c48961074d826))
* **JsonViewer:** integrate JsonViewer component for improved JSON display and editing experience ([8ead760](https://github.com/ali-master/rule-engine/commit/8ead7605c7257c1a493d6273af682dc632041e8c))
* **OperatorSelector:** add search functionality and improve operator grouping ([10dd6c4](https://github.com/ali-master/rule-engine/commit/10dd6c484d176c0ed49ac0d7c69b36d8ce82e05f))
* **TreeConditionGroup:** enhance condition type styling with improved colors and animations ([aa5bb4a](https://github.com/ali-master/rule-engine/commit/aa5bb4ae10afcb9e78f006f5cd974d5858fc8d57))
* **TreeConstraintEditor:** add advanced field selector mode and integrate SmartOperatorSelector ([03d40ec](https://github.com/ali-master/rule-engine/commit/03d40ec93341580f3e375c0f4450c39cdc75c5a4))
* **TreeConstraintEditor:** enhance operator selection with tooltips and improved layout ([cd7a728](https://github.com/ali-master/rule-engine/commit/cd7a728326da6f26077146f3ce1df2cbbb178f4a))
* **TreeRuleBuilder, VisualFieldSelector:** enhance UI with regex helper and improved tab functionality ([cacef1a](https://github.com/ali-master/rule-engine/commit/cacef1a27bf932753df20319cd43b7a4f1da19b4))
* **VisualFieldSelector:** enhance value preview layout and improve JsonViewer integration ([59d962a](https://github.com/ali-master/rule-engine/commit/59d962ae12b3127a666eab8b105feadc45cfa77c))
* **VisualFieldSelector:** integrate JsonViewer for enhanced JSON value preview ([52bb37c](https://github.com/ali-master/rule-engine/commit/52bb37c1112e6d857d28cb430c58692c6c579d3a))
### Bug Fixes
* **HistoryViewer:** layout and overflow ([7f357a4](https://github.com/ali-master/rule-engine/commit/7f357a49bf7b9904e6bc964ff40ed85779d52eec))
### [0.0.1](https://github.com/ali-master/rule-engine/compare/v0.0.2...v0.0.1) (2025-06-10)
================================================
FILE: packages/builder/README.md
================================================
<div align="center">
<img src="../../assets/builder-logo.svg" alt="Rule Engine Builder Logo" width="120" />
<h1>@usex/rule-engine-builder</h1>
<p><strong>🎨 Visual Rule Constructor for React Applications</strong></p>
<p>
<a href="https://www.npmjs.com/package/@usex/rule-engine-builder"><img src="https://img.shields.io/npm/v/@usex/rule-engine-builder?style=flat-square" alt="npm version" /></a>
<a href="https://github.com/ali-master/rule-engine/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/@usex/rule-engine-builder?style=flat-square" alt="license" /></a>
<a href="https://codecov.io/gh/ali-master/rule-engine"><img src="https://codecov.io/gh/ali-master/rule-engine/graph/badge.svg?token=UN5opqxNsi" alt="codecov" /></a>
<a href="https://www.npmjs.com/package/@usex/rule-engine-builder"><img src="https://img.shields.io/npm/dm/@usex/rule-engine-builder?style=flat-square" alt="downloads" /></a>
<a href="https://github.com/ali-master/rule-engine"><img src="https://img.shields.io/github/stars/ali-master/rule-engine?style=flat-square" alt="stars" /></a>
</p>
<p>
<a href="#-quick-start">Quick Start</a> •
<a href="./docs/components.md">Components</a> •
<a href="./docs/examples.md">Examples</a> •
<a href="#-why-visual-builder">Why Visual Builder?</a>
</p>
</div>
---
Create complex business rules with an intuitive drag-and-drop interface. No more JSON wrestling - build rules visually and export to your rule engine.
```typescript
// Instead of writing complex JSON...
const rule = {
conditions: [
{
and: [
{ field: "$.user.tier", operator: "equals", value: "premium" },
{ field: "$.order.total", operator: "greater-than", value: 100 }
],
result: { discount: 0.15, shipping: "free" }
}
]
};
// Just drag, drop, and configure visually! 🎨
<RuleBuilder
onRuleChange={setRule}
availableFields={fields}
theme="dark"
/>
```
## 🚀 Why Visual Builder?
**Intuitive Visual Interface**
- 🎨 **Drag & Drop** - Build rules by dragging components onto a canvas
- 🌲 **Tree Structure** - Visual representation of complex nested logic
- 📦 **Component Palette** - Pre-built operators, fields, and logic blocks
- 🎯 **Drop Zones** - Smart targeting for precise rule construction
**Developer-Friendly Experience**
- ⚡ **Real-time Preview** - See JSON output as you build
- 🔄 **Live Evaluation** - Test rules instantly with sample data
- 📈 **History Management** - Undo/redo with 100-entry history
- ⌨️ **Keyboard Shortcuts** - Professional keyboard navigation
**Production-Ready Features**
- 🛡️ **TypeScript Native** - Full type safety and IntelliSense support
- 🎨 **Theme System** - Light/dark modes with full customization
- ♿ **Accessible** - WCAG compliant with screen reader support
- 📱 **Responsive** - Works on desktop, tablet, and mobile devices
**Extensible & Customizable**
- 🔧 **Custom Operators** - Add your own business-specific operators
- 🎛️ **Field Discovery** - Auto-suggest fields from your data schema
- 🌈 **Custom Themes** - Match your application's design system
- 📊 **Export Options** - JSON, TypeScript, or custom formats
## 🎬 Quick Start
```bash
npm install @usex/rule-engine-builder @usex/rule-engine react
```
### Basic Usage
```tsx
import React, { useState } from 'react';
import { RuleBuilder } from '@usex/rule-engine-builder';
import { RuleEngine } from '@usex/rule-engine';
function App() {
const [rule, setRule] = useState(null);
// Define available fields for your users
const availableFields = [
{ name: '$.user.tier', type: 'string', label: 'User Tier' },
{ name: '$.user.age', type: 'number', label: 'User Age' },
{ name: '$.order.total', type: 'number', label: 'Order Total' },
{ name: '$.order.items', type: 'array', label: 'Order Items' }
];
// Test data for live evaluation
const testData = {
user: { tier: 'premium', age: 28 },
order: { total: 150, items: ['laptop', 'mouse'] }
};
return (
<div className="app">
<h1>Build Your Business Rules</h1>
<RuleBuilder
rule={rule}
onRuleChange={setRule}
availableFields={availableFields}
testData={testData}
theme="auto"
showPreview={true}
showHistory={true}
/>
{rule && (
<div className="rule-output">
<h3>Generated Rule:</h3>
<pre>{JSON.stringify(rule, null, 2)}</pre>
<button onClick={() => testRule()}>
Test Rule
</button>
</div>
)}
</div>
);
async function testRule() {
if (!rule) return;
const result = await RuleEngine.evaluate(rule, testData);
console.log('Rule Result:', result);
}
}
```
## 🏗️ Core Components
### RuleBuilder (Main Component)
The primary visual rule construction interface.
```tsx
<RuleBuilder
rule={rule} // Current rule state
onRuleChange={setRule} // Callback when rule changes
availableFields={fields} // Available fields for selection
testData={testData} // Sample data for live testing
theme="dark" // Theme: 'light' | 'dark' | 'auto'
showPreview={true} // Show JSON preview panel
showHistory={true} // Enable undo/redo functionality
customOperators={operators} // Custom business operators
onValidationError={onError} // Validation error callback
className="my-rule-builder" // Custom CSS classes
/>
```
### RuleEvaluator
Real-time rule evaluation with visual feedback.
```tsx
<RuleEvaluator
rule={rule}
testData={testData}
engine={RuleEngine}
onResult={handleResult}
showSteps={true} // Show evaluation steps
highlightActive={true} // Highlight active rule paths
/>
```
### ModernConstraintEditor
Advanced constraint editing with intelligent suggestions.
```tsx
<ModernConstraintEditor
constraint={constraint}
onConstraintChange={setConstraint}
availableFields={fields}
operators={operators}
showFieldSuggestions={true}
allowCustomFields={true}
/>
```
## 🔧 Component Showcase
### Building Blocks
The visual builder provides intuitive components for every rule element:
#### Logic Operators
- **AND** - All conditions must be true
- **OR** - Any condition must be true
- **NONE** - No conditions must be true
#### Comparison Operators
- **Equals (=)** - Exact value matching
- **Greater Than (>)** - Numeric comparison
- **Contains** - Array/string inclusion
- **Matches** - Regular expression patterns
#### Field Selectors
- **JSONPath Fields** - `$.user.profile.name`
- **Nested Properties** - Deep object navigation
- **Array Elements** - `$.items[0].price`
- **Custom Fields** - User-defined properties
#### Value Inputs
- **Static Values** - Fixed strings, numbers, booleans
- **Dynamic References** - `$.other.field`
- **Arrays** - Multiple value selection
- **Date/Time** - Calendar and time pickers
## 🎯 Real-World Examples
### E-commerce Discount Builder
```tsx
function DiscountRuleBuilder() {
const [discountRule, setDiscountRule] = useState(null);
const ecommerceFields = [
{ name: '$.customer.tier', type: 'string', label: 'Customer Tier',
options: ['bronze', 'silver', 'gold', 'platinum'] },
{ name: '$.cart.total', type: 'number', label: 'Cart Total' },
{ name: '$.cart.itemCount', type: 'number', label: 'Number of Items' },
{ name: '$.customer.isFirstOrder', type: 'boolean', label: 'First Order' },
{ name: '$.promotions.active', type: 'array', label: 'Active Promotions' }
];
const customOperators = [
{
name: 'is-weekend',
label: 'Is Weekend',
category: 'datetime',
description: 'Check if current date is weekend'
},
{
name: 'bulk-discount-eligible',
label: 'Bulk Discount Eligible',
category: 'business',
description: 'Check if order qualifies for bulk pricing'
}
];
return (
<div className="discount-builder">
<h2>Discount Rule Builder</h2>
<RuleBuilder
rule={discountRule}
onRuleChange={setDiscountRule}
availableFields={ecommerceFields}
customOperators={customOperators}
theme="light"
resultTemplate={{
discount: 0,
code: '',
message: '',
expires: null
}}
/>
</div>
);
}
```
### User Access Control Builder
```tsx
function AccessControlBuilder() {
const [accessRule, setAccessRule] = useState(null);
const accessFields = [
{ name: '$.user.role', type: 'string', label: 'User Role' },
{ name: '$.user.department', type: 'string', label: 'Department' },
{ name: '$.user.clearanceLevel', type: 'number', label: 'Clearance Level' },
{ name: '$.resource.sensitivity', type: 'string', label: 'Resource Sensitivity' },
{ name: '$.session.duration', type: 'number', label: 'Session Duration' },
{ name: '$.time.currentHour', type: 'number', label: 'Current Hour' }
];
return (
<div className="access-builder">
<h2>Access Control Rules</h2>
<RuleBuilder
rule={accessRule}
onRuleChange={setAccessRule}
availableFields={accessFields}
theme="dark"
showHistory={true}
resultTemplate={{
allowed: false,
permissions: [],
expires: null,
reason: ''
}}
/>
<RuleEvaluator
rule={accessRule}
testData={sampleUserSession}
showSteps={true}
onResult={(result) => {
console.log('Access Decision:', result);
}}
/>
</div>
);
}
```
### Form Validation Builder
```tsx
function ValidationBuilder() {
const [validationRules, setValidationRules] = useState([]);
const formFields = [
{ name: 'email', type: 'string', label: 'Email Address' },
{ name: 'password', type: 'string', label: 'Password' },
{ name: 'confirmPassword', type: 'string', label: 'Confirm Password' },
{ name: 'age', type: 'number', label: 'Age' },
{ name: 'country', type: 'string', label: 'Country' },
{ name: 'acceptTerms', type: 'boolean', label: 'Accept Terms' }
];
return (
<div className="validation-builder">
<h2>Form Validation Rules</h2>
{validationRules.map((rule, index) => (
<div key={index} className="validation-rule">
<h3>Rule {index + 1}</h3>
<RuleBuilder
rule={rule}
onRuleChange={(newRule) => {
const updated = [...validationRules];
updated[index] = newRule;
setValidationRules(updated);
}}
availableFields={formFields}
mode="validation"
showPreview={false}
/>
</div>
))}
<button onClick={() => addValidationRule()}>
Add Validation Rule
</button>
</div>
);
}
```
## 🎨 Advanced Features
### Custom Themes
```tsx
const customTheme = {
colors: {
primary: '#6366f1',
secondary: '#10b981',
background: '#f8fafc',
surface: '#ffffff',
text: '#1f2937',
border: '#e5e7eb'
},
spacing: {
sm: '0.5rem',
md: '1rem',
lg: '1.5rem'
},
borderRadius: '0.75rem',
shadows: {
sm: '0 1px 2px rgba(0, 0, 0, 0.05)',
md: '0 4px 6px rgba(0, 0, 0, 0.1)'
}
};
<RuleBuilder
rule={rule}
onRuleChange={setRule}
theme={customTheme}
availableFields={fields}
/>
```
### Field Discovery
```tsx
// Auto-discover fields from your data schema
const fields = useFieldDiscovery(sampleData, {
maxDepth: 3,
includeArrays: true,
typeInference: true
});
<RuleBuilder
rule={rule}
onRuleChange={setRule}
availableFields={fields}
allowFieldDiscovery={true}
onFieldDiscovered={(field) => {
console.log('New field discovered:', field);
}}
/>
```
### History Management
```tsx
function RuleBuilderWithHistory() {
const [rule, setRule] = useState(null);
const { history, undo, redo, canUndo, canRedo } = useRuleHistory();
return (
<div>
<div className="history-controls">
<button
onClick={undo}
disabled={!canUndo}
title="Undo (Ctrl+Z)"
>
↶ Undo
</button>
<button
onClick={redo}
disabled={!canRedo}
title="Redo (Ctrl+Y)"
>
↷ Redo
</button>
<span className="history-count">
Step {history.currentIndex + 1} of {history.entries.length}
</span>
</div>
<RuleBuilder
rule={rule}
onRuleChange={setRule}
showHistory={true}
maxHistoryEntries={100}
/>
</div>
);
}
```
### Keyboard Shortcuts
The builder supports professional keyboard navigation:
| Shortcut | Action |
|----------|--------|
| `Ctrl+Z` | Undo last change |
| `Ctrl+Y` | Redo last undone change |
| `Ctrl+D` | Duplicate selected component |
| `Delete` | Remove selected component |
| `Tab` | Navigate between components |
| `Enter` | Edit selected component |
| `Escape` | Cancel current operation |
| `Ctrl+S` | Export rule (custom handler) |
## 🏎️ Performance & Optimization
### Virtual Scrolling
For large rule sets, the builder uses virtual scrolling:
```tsx
<RuleBuilder
rule={complexRule}
onRuleChange={setRule}
virtualScrolling={true}
itemHeight={60}
maxVisibleItems={50}
/>
```
### Lazy Loading
Components are loaded on-demand for better performance:
```tsx
const LazyRuleBuilder = lazy(() => import('@usex/rule-engine-builder'));
function App() {
return (
<Suspense fallback={<div>Loading rule builder...</div>}>
<LazyRuleBuilder />
</Suspense>
);
}
```
### Optimized Rendering
```tsx
// Use memo for expensive field calculations
const availableFields = useMemo(() =>
generateFieldsFromSchema(schema), [schema]
);
// Debounce rule changes to reduce re-renders
const debouncedOnChange = useMemo(
() => debounce(setRule, 300),
[]
);
<RuleBuilder
rule={rule}
onRuleChange={debouncedOnChange}
availableFields={availableFields}
optimizeRendering={true}
/>
```
## 🎓 TypeScript Support
Full type safety for all components and props:
```tsx
interface CustomField {
name: string;
type: 'string' | 'number' | 'boolean' | 'array' | 'object';
label: string;
description?: string;
options?: string[];
validation?: {
required?: boolean;
min?: number;
max?: number;
pattern?: string;
};
}
interface CustomRule<T = any> {
id: string;
conditions: Condition<T>[];
result?: T;
metadata?: {
name: string;
description: string;
created: Date;
modified: Date;
};
}
// Type-safe rule builder
const Builder = () => {
const [rule, setRule] = useState<CustomRule<DiscountResult>>(null);
return (
<RuleBuilder<DiscountResult>
rule={rule}
onRuleChange={setRule}
availableFields={typedFields}
resultType="discount"
/>
);
};
```
## 🧪 Testing Components
```tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { RuleBuilder } from '@usex/rule-engine-builder';
describe('RuleBuilder', () => {
const mockFields = [
{ name: 'age', type: 'number', label: 'Age' },
{ name: 'country', type: 'string', label: 'Country' }
];
it('should render field palette', () => {
render(
<RuleBuilder
availableFields={mockFields}
onRuleChange={jest.fn()}
/>
);
expect(screen.getByText('Age')).toBeInTheDocument();
expect(screen.getByText('Country')).toBeInTheDocument();
});
it('should handle drag and drop', () => {
const onChange = jest.fn();
render(
<RuleBuilder
availableFields={mockFields}
onRuleChange={onChange}
/>
);
const ageField = screen.getByText('Age');
const dropZone = screen.getByTestId('drop-zone');
fireEvent.dragStart(ageField);
fireEvent.drop(dropZone);
expect(onChange).toHaveBeenCalledWith(
expect.objectContaining({
conditions: expect.arrayContaining([
expect.objectContaining({
field: 'age'
})
])
})
);
});
});
```
## 📚 Documentation & Resources
- 🏗️ **[Component Guide](./docs/components.md)** - Detailed component documentation
- 🎨 **[Theming Guide](./docs/theming.md)** - Customization and styling
- ⌨️ **[Keyboard Shortcuts](./docs/shortcuts.md)** - Complete keyboard reference
- 🔧 **[Integration Examples](./docs/integration.md)** - Framework-specific examples
- 🎯 **[Best Practices](./docs/best-practices.md)** - Performance and UX guidelines
- 📋 **[Changelog](./CHANGELOG.md)** - Version history and updates
## 🤝 Contributing
We welcome contributions! Whether it's:
- 🐛 Bug reports and fixes
- ✨ New components or features
- 📖 Documentation improvements
- 🎨 Theme contributions
See our [Contributing Guide](../../CONTRIBUTING.md) for details.
### Development Setup
```bash
# Clone the repository
git clone https://github.com/ali-master/rule-engine.git
cd rule-engine/packages/builder
# Install dependencies
pnpm install
# Start development server
pnpm dev
# Run tests
pnpm test
# Build for production
pnpm build
```
## 🆚 Why Choose This Builder?
| Feature | @usex/rule-engine-builder | React QueryBuilder | React Awesome Query Builder |
|---------|---------------------------|--------------------|-----------------------------|
| TypeScript Native | ✅ | ⚠️ Partial | ⚠️ Partial |
| Drag & Drop | ✅ | ❌ | ✅ |
| Real-time Evaluation | ✅ | ❌ | ❌ |
| History/Undo | ✅ | ❌ | ❌ |
| Custom Themes | ✅ | ⚠️ Limited | ✅ |
| Mobile Responsive | ✅ | ⚠️ Partial | ❌ |
| JSONPath Support | ✅ | ❌ | ❌ |
| Bundle Size | 45KB | 120KB | 180KB |
| Tree Visualization | ✅ | ❌ | ✅ |
| Keyboard Shortcuts | ✅ | ❌ | ❌ |
## 📄 License
MIT © [Ali Torki](https://github.com/ali-master)
---
<div align="center">
**Built with ❤️ for modern React applications**
[⭐ Star us on GitHub](https://github.com/ali-master/rule-engine) • [🐛 Report Issues](https://github.com/ali-master/rule-engine/issues) • [💬 Discussions](https://github.com/ali-master/rule-engine/discussions)
</div>
================================================
FILE: packages/builder/components.json
================================================
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/main.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}
================================================
FILE: packages/builder/docs/README.md
================================================
# @usex/rule-engine-builder Documentation
Welcome to the comprehensive documentation for @usex/rule-engine-builder - a complete React component library for building visual rule engine interfaces.
## 📚 Documentation Overview
### Getting Started
- [**README**](../README.md) - Installation, quick start, and overview
- [**Integration Guide**](./integration.md) - Framework and backend integration
- [**Examples**](./examples.md) - Real-world use cases and implementations
### Component Documentation
- [**Component Reference**](./components.md) - Complete component API documentation
- [**Hooks Reference**](./hooks.md) - State management and utility hooks
- [**UI Components**](./components.md#ui-components) - Available UI component library
### Advanced Guides
- [**Custom Operators**](../README.md#custom-operators) - Creating custom business logic
- [**Theme Customization**](../README.md#theme-customization) - Styling and branding
- [**Performance Optimization**](./integration.md#performance-optimization) - Best practices
## 🚀 Quick Navigation
| Topic | Documentation |
|-------|---------------|
| **Installation** | [README](../README.md#installation) |
| **Basic Usage** | [README](../README.md#quick-start) |
| **TreeRuleBuilder** | [Components](./components.md#treerulebuilder) |
| **State Management** | [Hooks](./hooks.md#state-management-hooks) |
| **Field Discovery** | [Hooks](./hooks.md#usefielddiscovery) |
| **Keyboard Shortcuts** | [Hooks](./hooks.md#usekeyboardshortcuts) |
| **React Integration** | [Integration](./integration.md#react-integration) |
| **Next.js Setup** | [Integration](./integration.md#nextjs-integration) |
| **E-commerce Examples** | [Examples](./examples.md#e-commerce-examples) |
| **Access Control** | [Examples](./examples.md#access-control-examples) |
| **Form Validation** | [Examples](./examples.md#form-validation-examples) |
## 🎯 Component Categories
### Primary Components
| Component | Purpose | Documentation |
|-----------|---------|---------------|
| `TreeRuleBuilder` | Main rule builder interface | [Components](./components.md#treerulebuilder) |
| `ModernRuleBuilder` | Enhanced with animations | [Components](./components.md#modernrulebuilder) |
| `RuleEvaluator` | Real-time rule testing | [Components](./components.md#ruleevaluator) |
| `HistoryViewer` | Version control | [Components](./components.md#historyviewer) |
### Editor Components
| Component | Purpose | Use Case |
|-----------|---------|----------|
| `TreeConditionGroup` | Nested logic groups | AND/OR/NONE conditions |
| `TreeConstraintEditor` | Individual constraints | Field-operator-value editing |
| `FieldSelector` | Field selection | Grouped field picker |
| `OperatorSelector` | Operator selection | Categorized operators |
### Input Components
| Component | Type | Features |
|-----------|------|----------|
| `SmartValueInput` | Universal | Type-aware, validation |
| `ArrayInput` | Array | Drag-and-drop reordering |
| `DateInput` | Date/Time | Calendar, time zones |
| `NumberInput` | Number | Animated, formatting |
## 🔧 Integration Patterns
### Framework Support
| Framework | Status | Documentation |
|-----------|--------|---------------|
| **React** | ✅ Full Support | [Integration Guide](./integration.md#react-integration) |
| **Next.js** | ✅ App & Pages Router | [Integration Guide](./integration.md#nextjs-integration) |
| **Vite** | ✅ Optimized | [Integration Guide](./integration.md#vite-integration) |
| **Create React App** | ✅ Supported | [README](../README.md#quick-start) |
### State Management
| Library | Status | Documentation |
|---------|--------|---------------|
| **Zustand** | ✅ Built-in | [Hooks](./hooks.md#useenhancedrulestore) |
| **Redux Toolkit** | ✅ Supported | [Integration](./integration.md#redux-toolkit-integration) |
| **TanStack Query** | ✅ Supported | [Integration](./integration.md#tanstack-query-integration) |
| **Context API** | ✅ Supported | [Integration](./integration.md#with-context-providers) |
### Backend Integration
| Backend | Status | Documentation |
|---------|--------|---------------|
| **REST APIs** | ✅ Full Support | [Integration](./integration.md#expressjs-api) |
| **GraphQL** | ✅ Full Support | [Integration](./integration.md#graphql-integration) |
| **tRPC** | ✅ Compatible | [Integration](./integration.md#backend-integration) |
| **Firebase** | ✅ Compatible | [Examples](./examples.md#integration-examples) |
## 📖 Use Case Documentation
### Business Applications
| Use Case | Example | Documentation |
|----------|---------|---------------|
| **E-commerce** | Dynamic pricing, shipping | [Examples](./examples.md#e-commerce-examples) |
| **Access Control** | RBAC, permissions | [Examples](./examples.md#access-control-examples) |
| **Form Validation** | Registration, surveys | [Examples](./examples.md#form-validation-examples) |
| **Business Logic** | Lead scoring, workflows | [Examples](./examples.md#business-logic-examples) |
### Technical Implementations
| Pattern | Description | Documentation |
|---------|-------------|---------------|
| **Multi-tenant SaaS** | Tenant-specific rules | [Examples](./examples.md#multi-tenant-saas-platform) |
| **Real-time Evaluation** | Live rule testing | [Components](./components.md#ruleevaluator) |
| **Version Control** | Rule history management | [Components](./components.md#historyviewer) |
| **Custom Operators** | Domain-specific logic | [README](../README.md#custom-operators) |
## 🎨 Customization Guide
### Theming
| Aspect | Customization | Documentation |
|--------|---------------|---------------|
| **Colors** | CSS variables, props | [README](../README.md#theme-customization) |
| **Typography** | Font families, sizes | [Integration](./integration.md#styling-integration) |
| **Layout** | Spacing, borders | [Integration](./integration.md#tailwind-css-integration) |
| **Components** | Custom UI components | [Components](./components.md#ui-components) |
### Behavior
| Feature | Customization | Documentation |
|---------|---------------|---------------|
| **Keyboard Shortcuts** | Custom key bindings | [Hooks](./hooks.md#usekeyboardshortcuts) |
| **Field Discovery** | Custom algorithms | [Hooks](./hooks.md#usefielddiscovery) |
| **Validation** | Custom rules | [README](../README.md#form-validation-rules) |
| **Operators** | Business logic | [README](../README.md#custom-operators) |
## 🧪 Testing Documentation
### Testing Strategies
| Type | Tools | Documentation |
|------|-------|---------------|
| **Unit Tests** | Jest, Testing Library | [Integration](./integration.md#jest-testing) |
| **Integration Tests** | MSW, Mock APIs | [Integration](./integration.md#testing-with-mock-service-worker) |
| **E2E Tests** | Playwright, Cypress | [Integration](./integration.md#e2e-testing-with-playwright) |
| **Visual Tests** | Storybook, Chromatic | [Integration](./integration.md#testing-integration) |
## 📊 Performance Guide
### Optimization Techniques
| Technique | Implementation | Documentation |
|-----------|----------------|---------------|
| **Code Splitting** | Dynamic imports | [Integration](./integration.md#code-splitting) |
| **Memoization** | React.memo, useMemo | [Integration](./integration.md#memoization) |
| **Virtual Scrolling** | Large datasets | [Integration](./integration.md#virtual-scrolling) |
| **Bundle Analysis** | Webpack analyzer | [Integration](./integration.md#bundle-analysis) |
## 🔍 Troubleshooting
### Common Issues
| Issue | Solution | Documentation |
|-------|----------|---------------|
| **Styling conflicts** | CSS isolation | [Integration](./integration.md#styling-integration) |
| **SSR hydration** | Dynamic imports | [Integration](./integration.md#nextjs-integration) |
| **Performance** | Optimization patterns | [Integration](./integration.md#performance-optimization) |
| **Type errors** | TypeScript setup | [README](../README.md#typescript-support) |
## 🚀 Getting Started Checklist
### Setup Steps
- [ ] Install packages: `@usex/rule-engine-builder` and `@usex/rule-engine`
- [ ] Import styles: `import '@usex/rule-engine-builder/styles'`
- [ ] Add basic component: `<TreeRuleBuilder />`
- [ ] Configure fields and sample data
- [ ] Set up onChange handler
- [ ] Add keyboard shortcuts (optional)
- [ ] Customize theme (optional)
- [ ] Set up backend integration (optional)
### Quick Links
- 📦 [Installation Guide](../README.md#installation)
- 🚀 [Quick Start Tutorial](../README.md#quick-start)
- 🎯 [Live Examples](./examples.md)
- 🔧 [Integration Patterns](./integration.md)
- 📚 [API Reference](./components.md)
## 🤝 Contributing
Want to improve the documentation?
1. Check existing [issues](https://github.com/ali-master/rule-engine/issues)
2. Read the [Contributing Guide](../../../CONTRIBUTING.md)
3. Submit documentation improvements
4. Help others in discussions
## 📞 Support
- **GitHub Issues**: [Report bugs or request features](https://github.com/ali-master/rule-engine/issues)
- **Discussions**: [Community Q&A](https://github.com/ali-master/rule-engine/discussions)
- **Documentation**: You're reading it! 📖
---
<div align="center">
<p>
<strong>Made with ❤️ by the @usex/rule-engine community</strong>
</p>
<p>
<a href="https://github.com/ali-master/rule-engine">GitHub</a> •
<a href="https://www.npmjs.com/package/@usex/rule-engine-builder">npm</a> •
<a href="../README.md">Documentation</a>
</p>
</div>
================================================
FILE: packages/builder/docs/RuleEvaluator.md
================================================
# RuleEvaluator Component
The `RuleEvaluator` component provides a comprehensive interface for testing and evaluating rules in real-time against sample data. It features both live evaluation mode and manual evaluation, with detailed result visualization.
## Features
### Core Features
- **Live Rule Evaluation**: Automatically evaluates rules as they change
- **Manual Evaluation**: Evaluate rules on-demand with a single click
- **Pass/Fail Indicators**: Clear visual feedback with red/green indicators
- **Silent Mode**: Minimal UI showing just the pass/fail status
- **Detailed Mode**: Comprehensive view showing which conditions passed or failed
- **Smooth Animations**: Beautiful transitions powered by Framer Motion
### Keyboard Shortcuts
- `Ctrl/Cmd + E`: Toggle live evaluation mode
- `Ctrl/Cmd + Shift + E`: Run evaluation once
### UI Components
- **Result Tab**: Shows overall evaluation result with pass/fail status
- **Details Tab**: Hierarchical view of condition evaluation with drill-down capability
- **Test Data Tab**: Editable JSON viewer for modifying test data on the fly
## Usage
```tsx
import { RuleEvaluator } from '@usex/rule-engine-builder';
function MyApp() {
const handleEvaluationChange = (result) => {
console.log('Evaluation result:', result);
};
return (
<RuleEvaluator
defaultSampleData={mySampleData}
onEvaluationChange={handleEvaluationChange}
className="my-custom-class"
/>
);
}
```
## Props
| Prop | Type | Description | Default |
|------|------|-------------|---------|
| `className` | `string` | Additional CSS classes for styling | - |
| `defaultSampleData` | `any` | Initial sample data for evaluation | `sampleEcommerceData` |
| `onEvaluationChange` | `(result: EvaluationResult \| null) => void` | Callback when evaluation result changes | - |
## How It Works
### Evaluation Process
1. The component uses the `@usex/rule-engine` package to evaluate rules
2. It subscribes to the enhanced rule store for rule updates
3. In live mode, it automatically re-evaluates when rules change
4. Results are displayed with detailed condition breakdowns
### Visual Feedback
- **Green indicators**: Rule or condition passed
- **Red indicators**: Rule or condition failed
- **Animated transitions**: Smooth UI updates for better UX
- **Hierarchical display**: Nested conditions are indented and collapsible
### Test Data Management
- Edit test data directly in the component
- Reset to default data with one click
- JSON syntax validation
- Real-time updates when data changes
## Integration with Rule Builder
The `RuleEvaluator` component is designed to work seamlessly with the `TreeRuleBuilder`:
```tsx
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2">
<TreeRuleBuilder sampleData={sampleData} />
</div>
<div className="lg:col-span-1">
<RuleEvaluator defaultSampleData={sampleData} />
</div>
</div>
```
## Advanced Features
### Condition Details
The component evaluates each condition recursively and shows:
- Condition type (AND, OR, NONE)
- Number of sub-conditions
- Individual constraint evaluation results
- Actual vs. expected values
- Custom error messages
### Performance
- Debounced evaluation in live mode
- Efficient re-rendering with React hooks
- Minimal state updates
- Optimized for large rule trees
## Styling
The component uses Tailwind CSS and follows the design system of the rule builder. It supports:
- Light and dark themes
- Responsive design
- Custom color schemes via CSS variables
- Smooth animations and transitions
## Error Handling
The component gracefully handles:
- Invalid rule structures
- Malformed test data
- Evaluation errors
- Network timeouts (if using async evaluation)
Errors are displayed with clear messages and don't crash the UI.
================================================
FILE: packages/builder/docs/components.md
================================================
# Component Reference
Comprehensive reference for all components in @usex/rule-engine-builder.
## Table of Contents
- [Primary Components](#primary-components)
- [Editor Components](#editor-components)
- [Input Components](#input-components)
- [Utility Components](#utility-components)
- [Hook Components](#hook-components)
- [UI Components](#ui-components)
## Primary Components
### TreeRuleBuilder
Main rule builder component with tree-based interface.
```typescript
interface TreeRuleBuilderProps {
fields?: FieldConfig[];
sampleData?: Record<string, any>;
onChange?: (rule: any) => void;
onSave?: (rule: any) => void | Promise<void>;
onExport?: (rule: any, format: "json" | "yaml") => void;
onImport?: (data: string, format: "json" | "yaml") => void;
readOnly?: boolean;
className?: string;
showJsonViewer?: boolean;
showToolbar?: boolean;
maxNestingDepth?: number;
customOperators?: Record<string, any>;
theme?: "light" | "dark" | "system";
labels?: LabelConfig;
colors?: ColorConfig;
keyboardShortcuts?: KeyboardShortcuts;
}
```
**Features:**
- Tree-based rule construction
- Drag-and-drop reordering
- Keyboard shortcuts
- History management
- Real-time evaluation
- Import/export functionality
**Example:**
```tsx
<TreeRuleBuilder
fields={fields}
sampleData={data}
onChange={handleRuleChange}
onSave={handleSave}
showJsonViewer={true}
maxNestingDepth={5}
/>
```
### ModernRuleBuilder
Enhanced rule builder with modern UI and animations.
```typescript
interface ModernRuleBuilderProps extends TreeRuleBuilderProps {
animations?: boolean;
dragAndDrop?: boolean;
virtualScrolling?: boolean;
}
```
**Features:**
- Framer Motion animations
- Enhanced drag-and-drop
- Virtual scrolling for large datasets
- Modern design patterns
### RuleEvaluator
Real-time rule evaluation component.
```typescript
interface RuleEvaluatorProps {
rule?: RuleType;
data?: Record<string, any>;
onDataChange?: (data: Record<string, any>) => void;
showKeyboardShortcuts?: boolean;
className?: string;
}
```
**Features:**
- Live rule evaluation
- Sample data editing
- Pass/fail indicators
- Performance metrics
- Keyboard shortcuts (Ctrl+E, Ctrl+Shift+E)
**Example:**
```tsx
<RuleEvaluator
rule={currentRule}
data={testData}
onDataChange={setTestData}
showKeyboardShortcuts={true}
/>
```
### HistoryViewer
Rule change history with version comparison.
```typescript
interface HistoryViewerProps {
className?: string;
}
```
**Features:**
- 100-entry history
- Version comparison
- Diff visualization
- Checkout previous versions
- Search and filter
**Example:**
```tsx
<HistoryViewer className="mt-4" />
```
## Editor Components
### TreeConditionGroup
Nested condition group management.
```typescript
interface TreeConditionGroupProps {
condition: Condition;
path: number[];
depth: number;
fields: FieldConfig[];
sampleData?: Record<string, any>;
customOperators?: Record<string, any>;
maxNestingDepth?: number;
onUpdate: (condition: Condition) => void;
onRemove: () => void;
onDuplicate: () => void;
readOnly?: boolean;
labels?: LabelConfig;
colors?: ColorConfig;
}
```
**Features:**
- AND/OR/NONE logic groups
- Nested conditions
- Drag-and-drop reordering
- Visual depth indicators
- Expand/collapse state
### TreeConstraintEditor
Individual constraint editing interface.
```typescript
interface TreeConstraintEditorProps {
constraint: Constraint;
path: number[];
fields: FieldConfig[];
sampleData?: Record<string, any>;
customOperators?: Record<string, any>;
onUpdate: (constraint: Constraint) => void;
onRemove: () => void;
onDuplicate: () => void;
readOnly?: boolean;
}
```
**Features:**
- Field selection with groups
- Operator categorization
- Smart value inputs
- Validation messages
- Copy/paste support
### FieldSelector
Advanced field selection interface.
```typescript
interface FieldSelectorProps {
fields: FieldConfig[];
value?: string;
onChange: (field: string) => void;
placeholder?: string;
className?: string;
showGroups?: boolean;
allowCustom?: boolean;
jsonPathSupport?: boolean;
}
```
**Features:**
- Grouped field display
- Search and filtering
- JSONPath support
- Custom field creation
- Type indicators
**Example:**
```tsx
<FieldSelector
fields={fields}
value={selectedField}
onChange={setSelectedField}
showGroups={true}
allowCustom={true}
jsonPathSupport={true}
/>
```
### OperatorSelector
Categorized operator selection.
```typescript
interface OperatorSelectorProps {
operators: OperatorConfig[];
value?: string;
onChange: (operator: string) => void;
fieldType?: string;
className?: string;
showCategories?: boolean;
searchable?: boolean;
}
```
**Features:**
- Category-based grouping
- Search functionality
- Field type filtering
- Help text and examples
- Icon indicators
## Input Components
### SmartValueInput
Universal value input with type awareness.
```typescript
interface SmartValueInputProps {
value: any;
onChange: (value: any) => void;
operator: string;
fieldType?: string;
field?: FieldConfig;
placeholder?: string;
className?: string;
validation?: ValidationConfig;
}
```
**Features:**
- Type-aware rendering
- Operator-specific inputs
- Validation feedback
- Suggestions and autocomplete
- Multi-value support
**Example:**
```tsx
<SmartValueInput
value={constraintValue}
onChange={setValue}
operator="contains-any"
fieldType="array"
field={selectedField}
/>
```
### ArrayInput
Array value management with drag-and-drop.
```typescript
interface ArrayInputProps {
value: any[];
onChange: (value: any[]) => void;
itemType?: string;
placeholder?: string;
maxItems?: number;
allowDuplicates?: boolean;
sortable?: boolean;
className?: string;
}
```
**Features:**
- Add/remove items
- Drag-and-drop reordering
- Type-specific item inputs
- Duplicate detection
- Validation per item
### DateInput
Advanced date/time picker.
```typescript
interface DateInputProps {
value: Date | string;
onChange: (value: Date | string) => void;
format?: string;
showTime?: boolean;
timeZone?: string;
minDate?: Date;
maxDate?: Date;
className?: string;
}
```
**Features:**
- Calendar popup
- Time selection
- Time zone support
- Format customization
- Range validation
### NumberInput
Animated number input with validation.
```typescript
interface NumberInputProps {
value: number;
onChange: (value: number) => void;
min?: number;
max?: number;
step?: number;
precision?: number;
animated?: boolean;
format?: Intl.NumberFormatOptions;
className?: string;
}
```
**Features:**
- Smooth animations
- Range validation
- Step controls
- Number formatting
- Precision handling
## Utility Components
### JsonViewer / RuleViewer
JSON visualization with syntax highlighting.
```typescript
interface JsonViewerProps {
data: any;
rootName?: string;
defaultExpanded?: boolean;
className?: string;
highlightLogicalOperators?: boolean;
collapsible?: boolean;
searchable?: boolean;
}
```
**Features:**
- Syntax highlighting
- Collapsible nodes
- Search functionality
- Logical operator highlighting
- Copy to clipboard
**Example:**
```tsx
<JsonViewer
data={rule}
rootName="rule"
defaultExpanded={true}
highlightLogicalOperators={true}
searchable={true}
/>
```
### DiffViewer
Rule comparison and diff visualization.
```typescript
interface DiffViewerProps {
oldValue: any;
newValue: any;
className?: string;
title?: string;
oldTitle?: string;
newTitle?: string;
viewMode?: "split" | "unified";
showStats?: boolean;
}
```
**Features:**
- Side-by-side comparison
- Unified diff view
- Change statistics
- Syntax highlighting
- Property-level analysis
**Example:**
```tsx
<DiffViewer
oldValue={previousRule}
newValue={currentRule}
title="Rule Changes"
viewMode="split"
showStats={true}
/>
```
### ImportExport
Rule import/export functionality.
```typescript
interface ImportExportProps {
onImport: (data: any, format: string) => void;
onExport: (format: string) => any;
supportedFormats?: string[];
className?: string;
}
```
**Features:**
- JSON/YAML support
- File upload/download
- Validation on import
- Format conversion
- Error handling
### ThemeToggle
Light/dark theme switching.
```typescript
interface ThemeToggleProps {
className?: string;
size?: "sm" | "md" | "lg";
showLabel?: boolean;
}
```
**Features:**
- System theme detection
- Smooth transitions
- Customizable appearance
- Accessibility support
## Hook Components
### Enhanced Rule Store
Advanced state management with history.
```typescript
const useEnhancedRuleStore = () => ({
// State
rule: RuleType;
history: HistoryEntry[];
historyIndex: number;
expandedGroups: Set<string>;
// Actions
updateRule: (rule: RuleType, action?: string, description?: string) => void;
updateConditions: (conditions: Condition[]) => void;
setRule: (rule: RuleType, action?: string, description?: string) => void;
// History
undo: () => void;
redo: () => void;
canUndo: () => boolean;
canRedo: () => boolean;
getUndoInfo: () => HistoryInfo;
getRedoInfo: () => HistoryInfo;
// UI State
expandAll: () => void;
collapseAll: () => void;
toggleGroup: (groupId: string) => void;
isGroupExpanded: (groupId: string) => boolean;
});
```
### Field Discovery
Automatic field discovery from sample data.
```typescript
const useFieldDiscovery = (data: any, options?: DiscoveryOptions) => ({
fields: FieldConfig[];
isLoading: boolean;
error: Error | null;
discover: () => void;
addCustomField: (field: FieldConfig) => void;
removeField: (fieldName: string) => void;
updateField: (fieldName: string, updates: Partial<FieldConfig>) => void;
});
interface DiscoveryOptions {
maxDepth?: number;
includeArrayIndices?: boolean;
generateLabels?: boolean;
excludePaths?: string[];
fieldTypes?: Record<string, string>;
}
```
### Keyboard Shortcuts
Configurable keyboard shortcut management.
```typescript
interface ShortcutConfig {
key: string;
ctrl?: boolean;
cmd?: boolean;
shift?: boolean;
alt?: boolean;
handler: () => void;
description: string;
disabled?: boolean;
}
const useKeyboardShortcuts = (shortcuts: ShortcutConfig[]) => {
// Registers global keyboard event listeners
// Handles platform-specific modifiers (Cmd on Mac, Ctrl on others)
// Provides conflict detection and resolution
};
```
## UI Components
### Core UI Components
Built on Radix UI primitives with full accessibility support:
| Component | Purpose | Features |
|-----------|---------|----------|
| `Button` | Actions and triggers | Variants, sizes, loading states |
| `Input` | Text input | Validation, prefixes, suffixes |
| `Select` | Dropdown selection | Search, grouping, custom options |
| `Dialog` | Modal dialogs | Zoom animations, scroll management |
| `Popover` | Floating content | Auto-positioning, close triggers |
| `Tooltip` | Help text | Delays, positioning, rich content |
| `Tabs` | Content organization | Keyboard navigation, indicators |
| `Card` | Content containers | Headers, footers, actions |
| `Badge` | Status indicators | Variants, sizes, icons |
| `Alert` | Notifications | Types, dismissible, actions |
### Advanced UI Components
| Component | Purpose | Features |
|-----------|---------|----------|
| `ZoomDialog` | Full-screen editing | Smooth zoom animations |
| `ScrollArea` | Custom scrollbars | Virtual scrolling, smooth scroll |
| `Collapsible` | Expandable content | Animations, nested support |
| `Command` | Command palette | Search, keyboard navigation |
| `Calendar` | Date selection | Range selection, disabled dates |
| `Slider` | Range input | Multiple handles, step values |
| `Switch` | Boolean toggle | Animated, labeled |
| `Separator` | Visual dividers | Orientation, spacing |
### Layout Components
| Component | Purpose | Features |
|-----------|---------|----------|
| `ResizablePanel` | Resizable layouts | Horizontal/vertical, constraints |
| `Sheet` | Side panels | Slide animations, overlay |
| `DropdownMenu` | Contextual menus | Submenus, separators, icons |
| `HoverCard` | Rich tooltips | Delays, rich content, positioning |
## Component Composition Examples
### Custom Rule Builder
```tsx
import {
RuleBuilderProvider,
TreeConditionGroup,
FieldSelector,
JsonViewer,
useEnhancedRuleStore
} from '@usex/rule-engine-builder';
function CustomRuleBuilder() {
const { rule, updateRule } = useEnhancedRuleStore();
return (
<RuleBuilderProvider>
<div className="grid grid-cols-3 gap-4">
<div className="col-span-2">
<TreeConditionGroup
condition={rule.conditions}
path={[]}
depth={0}
fields={fields}
onUpdate={updateRule}
/>
</div>
<div>
<JsonViewer
data={rule}
highlightLogicalOperators={true}
/>
</div>
</div>
</RuleBuilderProvider>
);
}
```
### Evaluation Dashboard
```tsx
import {
TreeRuleBuilder,
RuleEvaluator,
HistoryViewer,
DiffViewer
} from '@usex/rule-engine-builder';
function EvaluationDashboard() {
const [rule, setRule] = useState(null);
const [testData, setTestData] = useState({});
const [selectedVersions, setSelectedVersions] = useState([]);
return (
<div className="space-y-6">
<div className="grid grid-cols-2 gap-6">
<TreeRuleBuilder
onChange={setRule}
sampleData={testData}
/>
<RuleEvaluator
rule={rule}
data={testData}
onDataChange={setTestData}
/>
</div>
<div className="grid grid-cols-2 gap-6">
<HistoryViewer />
{selectedVersions.length === 2 && (
<DiffViewer
oldValue={selectedVersions[0]}
newValue={selectedVersions[1]}
title="Version Comparison"
/>
)}
</div>
</div>
);
}
```
---
For more information, see the [main documentation](../README.md).
================================================
FILE: packages/builder/docs/examples.md
================================================
# Examples and Use Cases
Comprehensive collection of real-world examples using @usex/rule-engine-builder.
## Table of Contents
- [E-commerce Examples](#e-commerce-examples)
- [Access Control Examples](#access-control-examples)
- [Form Validation Examples](#form-validation-examples)
- [Business Logic Examples](#business-logic-examples)
- [Data Processing Examples](#data-processing-examples)
- [Integration Examples](#integration-examples)
## E-commerce Examples
### Dynamic Pricing Rules
```tsx
import { TreeRuleBuilder, FieldConfig } from '@usex/rule-engine-builder';
const pricingFields: FieldConfig[] = [
{
name: 'product.category',
label: 'Product Category',
type: 'string',
group: 'Product',
values: [
{ value: 'electronics', label: 'Electronics' },
{ value: 'clothing', label: 'Clothing' },
{ value: 'books', label: 'Books' },
{ value: 'home', label: 'Home & Garden' }
]
},
{
name: 'product.price',
label: 'Base Price',
type: 'number',
group: 'Product'
},
{
name: 'customer.tier',
label: 'Customer Tier',
type: 'string',
group: 'Customer',
values: [
{ value: 'bronze', label: 'Bronze' },
{ value: 'silver', label: 'Silver' },
{ value: 'gold', label: 'Gold' },
{ value: 'platinum', label: 'Platinum' }
]
},
{
name: 'order.quantity',
label: 'Order Quantity',
type: 'number',
group: 'Order'
},
{
name: 'order.total',
label: 'Order Total',
type: 'number',
group: 'Order'
},
{
name: 'customer.isFirstTime',
label: 'First Time Customer',
type: 'boolean',
group: 'Customer'
},
{
name: 'season.current',
label: 'Current Season',
type: 'string',
group: 'Context',
values: [
{ value: 'spring', label: 'Spring' },
{ value: 'summer', label: 'Summer' },
{ value: 'fall', label: 'Fall' },
{ value: 'winter', label: 'Winter' }
]
}
];
function DynamicPricingBuilder() {
const [pricingRule, setPricingRule] = useState(null);
const sampleData = {
product: {
category: 'electronics',
price: 299.99,
name: 'Wireless Headphones'
},
customer: {
tier: 'gold',
isFirstTime: false,
totalSpent: 1500
},
order: {
quantity: 2,
total: 599.98
},
season: {
current: 'winter'
}
};
const handlePricingRuleChange = (rule) => {
setPricingRule(rule);
console.log('Pricing rule updated:', rule);
};
return (
<div className="space-y-6">
<div className="bg-white p-6 rounded-lg shadow">
<h2 className="text-2xl font-bold mb-4">Dynamic Pricing Rules</h2>
<p className="text-gray-600 mb-6">
Create rules to automatically adjust pricing based on customer, product, and context factors.
</p>
<TreeRuleBuilder
fields={pricingFields}
sampleData={sampleData}
onChange={handlePricingRuleChange}
labels={{
addGroup: 'Add Pricing Condition',
noRules: 'No pricing rules defined. Add conditions to create dynamic pricing.'
}}
colors={{
and: 'border-green-500/30 bg-green-500/5',
or: 'border-blue-500/30 bg-blue-500/5',
none: 'border-red-500/30 bg-red-500/5'
}}
/>
</div>
{/* Example rule preview */}
<div className="bg-gray-50 p-4 rounded-lg">
<h3 className="font-semibold mb-2">Example Pricing Rules:</h3>
<ul className="text-sm space-y-1">
<li>• Gold/Platinum customers get 15% off electronics over $200</li>
<li>• First-time customers get 10% off their first order</li>
<li>• Bulk orders (5+ items) get 20% off</li>
<li>• Winter season: 25% off clothing items</li>
</ul>
</div>
</div>
);
}
```
### Shipping Rate Calculator
```tsx
const shippingFields: FieldConfig[] = [
{
name: 'order.weight',
label: 'Package Weight (lbs)',
type: 'number',
group: 'Package'
},
{
name: 'order.dimensions',
label: 'Package Dimensions',
type: 'object',
group: 'Package'
},
{
name: 'destination.country',
label: 'Destination Country',
type: 'string',
group: 'Destination',
values: [
{ value: 'US', label: 'United States' },
{ value: 'CA', label: 'Canada' },
{ value: 'MX', label: 'Mexico' },
{ value: 'UK', label: 'United Kingdom' },
{ value: 'DE', label: 'Germany' }
]
},
{
name: 'destination.state',
label: 'Destination State',
type: 'string',
group: 'Destination'
},
{
name: 'destination.isRemote',
label: 'Remote Location',
type: 'boolean',
group: 'Destination'
},
{
name: 'shipping.method',
label: 'Shipping Method',
type: 'string',
group: 'Shipping',
values: [
{ value: 'standard', label: 'Standard (5-7 days)' },
{ value: 'expedited', label: 'Expedited (2-3 days)' },
{ value: 'overnight', label: 'Overnight' }
]
},
{
name: 'customer.isPremium',
label: 'Premium Customer',
type: 'boolean',
group: 'Customer'
}
];
function ShippingCalculatorBuilder() {
const sampleData = {
order: {
weight: 2.5,
dimensions: { length: 12, width: 8, height: 6 },
value: 199.99
},
destination: {
country: 'US',
state: 'CA',
zipCode: '90210',
isRemote: false
},
shipping: {
method: 'standard'
},
customer: {
isPremium: true
}
};
return (
<div className="space-y-6">
<div className="bg-white p-6 rounded-lg shadow">
<h2 className="text-2xl font-bold mb-4">Shipping Rate Rules</h2>
<TreeRuleBuilder
fields={shippingFields}
sampleData={sampleData}
onChange={(rule) => console.log('Shipping rule:', rule)}
labels={{
addGroup: 'Add Shipping Condition',
noRules: 'No shipping rules defined. Create rules to calculate shipping rates.'
}}
/>
</div>
{/* Rate examples */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="bg-blue-50 p-4 rounded">
<h4 className="font-semibold">Standard Shipping</h4>
<p className="text-sm">$5.99 base + $0.50/lb</p>
</div>
<div className="bg-yellow-50 p-4 rounded">
<h4 className="font-semibold">Expedited Shipping</h4>
<p className="text-sm">$12.99 base + $1.00/lb</p>
</div>
<div className="bg-red-50 p-4 rounded">
<h4 className="font-semibold">Overnight Shipping</h4>
<p className="text-sm">$24.99 base + $2.00/lb</p>
</div>
</div>
</div>
);
}
```
### Promotional Campaign Rules
```tsx
const promotionFields: FieldConfig[] = [
{
name: 'campaign.code',
label: 'Promotion Code',
type: 'string',
group: 'Campaign'
},
{
name: 'campaign.startDate',
label: 'Campaign Start Date',
type: 'date',
group: 'Campaign'
},
{
name: 'campaign.endDate',
label: 'Campaign End Date',
type: 'date',
group: 'Campaign'
},
{
name: 'customer.email',
label: 'Customer Email',
type: 'string',
group: 'Customer'
},
{
name: 'customer.previousOrders',
label: 'Previous Orders Count',
type: 'number',
group: 'Customer'
},
{
name: 'order.items',
label: 'Order Items',
type: 'array',
group: 'Order'
},
{
name: 'order.categories',
label: 'Product Categories',
type: 'array',
group: 'Order'
}
];
function PromotionalCampaignBuilder() {
const sampleData = {
campaign: {
code: 'SAVE20',
startDate: '2025-01-01',
endDate: '2025-01-31'
},
customer: {
email: 'customer@example.com',
previousOrders: 3,
registrationDate: '2023-06-15'
},
order: {
items: ['item1', 'item2', 'item3'],
categories: ['electronics', 'accessories'],
total: 299.99
}
};
return (
<div className="space-y-6">
<div className="bg-white p-6 rounded-lg shadow">
<h2 className="text-2xl font-bold mb-4">Promotional Campaign Rules</h2>
<p className="text-gray-600 mb-6">
Define complex promotional rules with multiple conditions and customer targeting.
</p>
<TreeRuleBuilder
fields={promotionFields}
sampleData={sampleData}
onChange={(rule) => console.log('Promotion rule:', rule)}
labels={{
addGroup: 'Add Promotion Condition',
or: 'ANY of these conditions',
and: 'ALL of these conditions',
none: 'NONE of these conditions'
}}
/>
</div>
{/* Campaign examples */}
<div className="bg-gradient-to-r from-purple-100 to-pink-100 p-6 rounded-lg">
<h3 className="font-semibold mb-4">Example Campaign Rules:</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="bg-white p-4 rounded">
<h4 className="font-semibold text-purple-700">New Customer Welcome</h4>
<ul className="text-sm mt-2 space-y-1">
<li>• First-time customers only</li>
<li>• 20% off first order</li>
<li>• Minimum $50 purchase</li>
</ul>
</div>
<div className="bg-white p-4 rounded">
<h4 className="font-semibold text-pink-700">Loyalty Rewards</h4>
<ul className="text-sm mt-2 space-y-1">
<li>• 5+ previous orders</li>
<li>• 15% off electronics</li>
<li>• Free shipping included</li>
</ul>
</div>
</div>
</div>
</div>
);
}
```
## Access Control Examples
### Role-Based Access Control (RBAC)
```tsx
const rbacFields: FieldConfig[] = [
{
name: 'user.role',
label: 'User Role',
type: 'string',
group: 'User',
values: [
{ value: 'admin', label: 'Administrator' },
{ value: 'manager', label: 'Manager' },
{ value: 'employee', label: 'Employee' },
{ value: 'contractor', label: 'Contractor' },
{ value: 'guest', label: 'Guest' }
]
},
{
name: 'user.department',
label: 'Department',
type: 'string',
group: 'User',
values: [
{ value: 'engineering', label: 'Engineering' },
{ value: 'sales', label: 'Sales' },
{ value: 'marketing', label: 'Marketing' },
{ value: 'hr', label: 'Human Resources' },
{ value: 'finance', label: 'Finance' }
]
},
{
name: 'user.permissions',
label: 'User Permissions',
type: 'array',
group: 'User'
},
{
name: 'resource.type',
label: 'Resource Type',
type: 'string',
group: 'Resource',
values: [
{ value: 'document', label: 'Document' },
{ value: 'project', label: 'Project' },
{ value: 'user-profile', label: 'User Profile' },
{ value: 'financial-data', label: 'Financial Data' },
{ value: 'system-config', label: 'System Configuration' }
]
},
{
name: 'resource.owner',
label: 'Resource Owner',
type: 'string',
group: 'Resource'
},
{
name: 'resource.confidentiality',
label: 'Confidentiality Level',
type: 'string',
group: 'Resource',
values: [
{ value: 'public', label: 'Public' },
{ value: 'internal', label: 'Internal' },
{ value: 'confidential', label: 'Confidential' },
{ value: 'restricted', label: 'Restricted' }
]
},
{
name: 'action.type',
label: 'Action Type',
type: 'string',
group: 'Action',
values: [
{ value: 'read', label: 'Read' },
{ value: 'write', label: 'Write' },
{ value: 'delete', label: 'Delete' },
{ value: 'share', label: 'Share' },
{ value: 'export', label: 'Export' }
]
},
{
name: 'context.time',
label: 'Access Time',
type: 'string',
group: 'Context'
},
{
name: 'context.location',
label: 'Access Location',
type: 'string',
group: 'Context'
}
];
function RBACBuilder() {
const sampleData = {
user: {
id: 'user123',
role: 'manager',
department: 'engineering',
permissions: ['read', 'write', 'manage-team'],
clearanceLevel: 3
},
resource: {
id: 'doc456',
type: 'document',
owner: 'user789',
confidentiality: 'internal',
department: 'engineering'
},
action: {
type: 'read'
},
context: {
time: '14:30',
location: 'office',
ipAddress: '192.168.1.100'
}
};
return (
<div className="space-y-6">
<div className="bg-white p-6 rounded-lg shadow">
<h2 className="text-2xl font-bold mb-4">Access Control Rules</h2>
<p className="text-gray-600 mb-6">
Define role-based access control rules with fine-grained permissions.
</p>
<TreeRuleBuilder
fields={rbacFields}
sampleData={sampleData}
onChange={(rule) => console.log('Access rule:', rule)}
labels={{
addGroup: 'Add Access Condition',
noRules: 'No access rules defined. Create rules to control resource access.'
}}
colors={{
and: 'border-green-500/30 bg-green-500/5',
or: 'border-orange-500/30 bg-orange-500/5',
none: 'border-red-500/30 bg-red-500/5'
}}
/>
</div>
{/* Access examples */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="bg-green-50 p-4 rounded border border-green-200">
<h4 className="font-semibold text-green-800">Admin Access</h4>
<ul className="text-sm mt-2 space-y-1 text-green-700">
<li>• Full system access</li>
<li>• All resource types</li>
<li>• All actions allowed</li>
</ul>
</div>
<div className="bg-blue-50 p-4 rounded border border-blue-200">
<h4 className="font-semibold text-blue-800">Manager Access</h4>
<ul className="text-sm mt-2 space-y-1 text-blue-700">
<li>• Department resources</li>
<li>• Team management</li>
<li>• Read/Write permissions</li>
</ul>
</div>
<div className="bg-gray-50 p-4 rounded border border-gray-200">
<h4 className="font-semibold text-gray-800">Employee Access</h4>
<ul className="text-sm mt-2 space-y-1 text-gray-700">
<li>• Own resources only</li>
<li>• Public documents</li>
<li>• Limited actions</li>
</ul>
</div>
</div>
</div>
);
}
```
### Multi-Factor Authentication Rules
```tsx
const mfaFields: FieldConfig[] = [
{
name: 'user.riskScore',
label: 'User Risk Score',
type: 'number',
group: 'User',
description: 'Calculated risk score from 0-100'
},
{
name: 'device.trusted',
label: 'Trusted Device',
type: 'boolean',
group: 'Device'
},
{
name: 'location.knownLocation',
label: 'Known Location',
type: 'boolean',
group: 'Location'
},
{
name: 'location.country',
label: 'Country',
type: 'string',
group: 'Location'
},
{
name: 'session.lastLogin',
label: 'Last Login',
type: 'date',
group: 'Session'
},
{
name: 'action.sensitivity',
label: 'Action Sensitivity',
type: 'string',
group: 'Action',
values: [
{ value: 'low', label: 'Low' },
{ value: 'medium', label: 'Medium' },
{ value: 'high', label: 'High' },
{ value: 'critical', label: 'Critical' }
]
}
];
function MFABuilder() {
const sampleData = {
user: {
id: 'user123',
riskScore: 25,
hasActiveMFA: true
},
device: {
id: 'device456',
trusted: true,
type: 'mobile'
},
location: {
knownLocation: false,
country: 'US',
ipAddress: '203.0.113.1'
},
session: {
lastLogin: '2025-01-15T10:30:00Z',
duration: 30
},
action: {
type: 'transfer-funds',
sensitivity: 'critical'
}
};
return (
<div className="space-y-6">
<div className="bg-white p-6 rounded-lg shadow">
<h2 className="text-2xl font-bold mb-4">Multi-Factor Authentication Rules</h2>
<p className="text-gray-600 mb-6">
Create intelligent MFA rules based on risk assessment and context.
</p>
<TreeRuleBuilder
fields={mfaFields}
sampleData={sampleData}
onChange={(rule) => console.log('MFA rule:', rule)}
labels={{
addGroup: 'Add MFA Condition'
}}
/>
</div>
{/* MFA scenarios */}
<div className="bg-yellow-50 p-6 rounded-lg border border-yellow-200">
<h3 className="font-semibold mb-4 text-yellow-800">MFA Trigger Scenarios:</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<h4 className="font-medium">High Risk Scenarios:</h4>
<ul className="text-sm space-y-1">
<li>• Unknown device or location</li>
<li>• High-sensitivity actions</li>
<li>• Elevated risk score (> 50)</li>
<li>• International access</li>
</ul>
</div>
<div className="space-y-2">
<h4 className="font-medium">Low Risk Scenarios:</h4>
<ul className="text-sm space-y-1">
<li>• Trusted device + known location</li>
<li>• Low-sensitivity actions</li>
<li>• Recent successful authentication</li>
<li>• Low risk score (< 20)</li>
</ul>
</div>
</div>
</div>
</div>
);
}
```
## Form Validation Examples
### User Registration Validation
```tsx
const registrationFields: FieldConfig[] = [
{
name: 'email',
label: 'Email Address',
type: 'string',
group: 'Contact'
},
{
name: 'password',
label: 'Password',
type: 'string',
group: 'Security'
},
{
name: 'confirmPassword',
label: 'Confirm Password',
type: 'string',
group: 'Security'
},
{
name: 'firstName',
label: 'First Name',
type: 'string',
group: 'Personal'
},
{
name: 'lastName',
label: 'Last Name',
type: 'string',
group: 'Personal'
},
{
name: 'age',
label: 'Age',
type: 'number',
group: 'Personal'
},
{
name: 'phoneNumber',
label: 'Phone Number',
type: 'string',
group: 'Contact'
},
{
name: 'acceptTerms',
label: 'Accept Terms',
type: 'boolean',
group: 'Legal'
},
{
name: 'marketingConsent',
label: 'Marketing Consent',
type: 'boolean',
group: 'Legal'
}
];
function RegistrationValidationBuilder() {
const [validationRule, setValidationRule] = useState(null);
const [formData, setFormData] = useState({
email: 'user@example.com',
password: 'securePass123!',
confirmPassword: 'securePass123!',
firstName: 'John',
lastName: 'Doe',
age: 25,
phoneNumber: '+1-555-0123',
acceptTerms: true,
marketingConsent: false
});
const validateForm = async (data) => {
if (!validationRule) return { isValid: true, errors: [] };
try {
const result = await RuleEngine.evaluate(validationRule, data);
return {
isValid: result.isPassed,
errors: result.isPassed ? [] : ['Validation failed']
};
} catch (error) {
return {
isValid: false,
errors: [error.message]
};
}
};
return (
<div className="space-y-6">
<div className="bg-white p-6 rounded-lg shadow">
<h2 className="text-2xl font-bold mb-4">Registration Validation Rules</h2>
<p className="text-gray-600 mb-6">
Create comprehensive validation rules for user registration forms.
</p>
<TreeRuleBuilder
fields={registrationFields}
sampleData={formData}
onChange={setValidationRule}
labels={{
addGroup: 'Add Validation Rule',
noRules: 'No validation rules defined. Add rules to validate form fields.'
}}
/>
</div>
{/* Form testing */}
<div className="bg-gray-50 p-6 rounded-lg">
<h3 className="font-semibold mb-4">Test Validation</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<h4 className="font-medium mb-2">Sample Form Data:</h4>
<pre className="text-xs bg-white p-3 rounded border overflow-auto">
{JSON.stringify(formData, null, 2)}
</pre>
</div>
<div>
<h4 className="font-medium mb-2">Validation Rules:</h4>
<ul className="text-sm space-y-1">
<li>• Email must be valid format</li>
<li>• Password minimum 8 characters</li>
<li>• Password must contain uppercase, lowercase, number, symbol</li>
<li>• Passwords must match</li>
<li>• Age must be 18 or older</li>
<li>• Terms must be accepted</li>
</ul>
</div>
</div>
<button
onClick={() => validateForm(formData)}
className="mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
>
Validate Form
</button>
</div>
</div>
);
}
```
### Dynamic Form Validation
```tsx
const dynamicValidationFields: FieldConfig[] = [
{
name: 'field.name',
label: 'Field Name',
type: 'string',
group: 'Field'
},
{
name: 'field.type',
label: 'Field Type',
type: 'string',
group: 'Field',
values: [
{ value: 'text', label: 'Text' },
{ value: 'email', label: 'Email' },
{ value: 'number', label: 'Number' },
{ value: 'date', label: 'Date' },
{ value: 'select', label: 'Select' },
{ value: 'checkbox', label: 'Checkbox' }
]
},
{
name: 'field.required',
label: 'Required Field',
type: 'boolean',
group: 'Field'
},
{
name: 'field.value',
label: 'Field Value',
type: 'string',
group: 'Field'
},
{
name: 'form.step',
label: 'Form Step',
type: 'number',
group: 'Form'
},
{
name: 'user.role',
label: 'User Role',
type: 'string',
group: 'Context',
values: [
{ value: 'admin', label: 'Administrator' },
{ value: 'user', label: 'Regular User' },
{ value: 'guest', label: 'Guest' }
]
}
];
function DynamicValidationBuilder() {
const sampleData = {
field: {
name: 'businessLicense',
type: 'text',
required: true,
value: 'BL123456789'
},
form: {
step: 2,
totalSteps: 4,
category: 'business-registration'
},
user: {
role: 'user',
accountType: 'business'
}
};
return (
<div className="space-y-6">
<div className="bg-white p-6 rounded-lg shadow">
<h2 className="text-2xl font-bold mb-4">Dynamic Form Validation</h2>
<p className="text-gray-600 mb-6">
Create conditional validation rules that adapt based on form context and user role.
</p>
<TreeRuleBuilder
fields={dynamicValidationFields}
sampleData={sampleData}
onChange={(rule) => console.log('Dynamic validation rule:', rule)}
labels={{
addGroup: 'Add Conditional Validation'
}}
/>
</div>
{/* Validation scenarios */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="bg-blue-50 p-4 rounded border border-blue-200">
<h4 className="font-semibold text-blue-800 mb-2">Step-Based Validation</h4>
<ul className="text-sm space-y-1 text-blue-700">
<li>• Step 1: Basic info required</li>
<li>• Step 2: Business details (if business account)</li>
<li>• Step 3: Payment info (if paid plan)</li>
<li>• Step 4: Final verification</li>
</ul>
</div>
<div className="bg-green-50 p-4 rounded border border-green-200">
<h4 className="font-semibold text-green-800 mb-2">Role-Based Validation</h4>
<ul className="text-sm space-y-1 text-green-700">
<li>• Admin: All fields optional</li>
<li>• Business: Additional docs required</li>
<li>• Individual: Simplified validation</li>
<li>• Guest: Limited access</li>
</ul>
</div>
</div>
</div>
);
}
```
## Business Logic Examples
### Lead Scoring System
```tsx
const leadScoringFields: FieldConfig[] = [
{
name: 'company.size',
label: 'Company Size',
type: 'string',
group: 'Company',
values: [
{ value: 'startup', label: 'Startup (1-10 employees)' },
{ value: 'small', label: 'Small (11-50 employees)' },
{ value: 'medium', label: 'Medium (51-200 employees)' },
{ value: 'large', label: 'Large (201-1000 employees)' },
{ value: 'enterprise', label: 'Enterprise (1000+ employees)' }
]
},
{
name: 'company.industry',
label: 'Industry',
type: 'string',
group: 'Company',
values: [
{ value: 'technology', label: 'Technology' },
{ value: 'finance', label: 'Finance' },
{ value: 'healthcare', label: 'Healthcare' },
{ value: 'retail', label: 'Retail' },
{ value: 'manufacturing', label: 'Manufacturing' }
]
},
{
name: 'company.revenue',
label: 'Annual Revenue',
type: 'number',
group: 'Company'
},
{
name: 'contact.title',
label: 'Job Title',
type: 'string',
group: 'Contact',
values: [
{ value: 'ceo', label: 'CEO' },
{ value: 'cto', label: 'CTO' },
{ value: 'vp', label: 'VP' },
{ value: 'director', label: 'Director' },
{ value: 'manager', label: 'Manager' },
{ value: 'individual', label: 'Individual Contributor' }
]
},
{
name: 'engagement.emailOpens',
label: 'Email Opens (30 days)',
type: 'number',
group: 'Engagement'
},
{
name: 'engagement.websiteVisits',
label: 'Website Visits (30 days)',
type: 'number',
group: 'Engagement'
},
{
name: 'engagement.contentDownloads',
label: 'Content Downloads',
type: 'number',
group: 'Engagement'
},
{
name: 'behavior.demoRequested',
label: 'Demo Requested',
type: 'boolean',
group: 'Behavior'
},
{
name: 'behavior.pricingPageViews',
label: 'Pricing Page Views',
type: 'number',
group: 'Behavior'
}
];
function LeadScoringBuilder() {
const sampleData = {
company: {
size: 'medium',
industry: 'technology',
revenue: 5000000,
location: 'US'
},
contact: {
title: 'cto',
email: 'cto@example.com',
firstName: 'Jane',
lastName: 'Smith'
},
engagement: {
emailOpens: 8,
websiteVisits: 15,
contentDownloads: 3
},
behavior: {
demoRequested: true,
pricingPageViews: 5,
trialStarted: false
}
};
return (
<div className="space-y-6">
<div className="bg-white p-6 rounded-lg shadow">
<h2 className="text-2xl font-bold mb-4">Lead Scoring Rules</h2>
<p className="text-gray-600 mb-6">
Create intelligent lead scoring based on company fit and engagement metrics.
</p>
<TreeRuleBuilder
fields={leadScoringFields}
sampleData={sampleData}
onChange={(rule) => console.log('Lead scoring rule:', rule)}
labels={{
addGroup: 'Add Scoring Condition'
}}
/>
</div>
{/* Scoring matrix */}
<div className="bg-gradient-to-r from-blue-50 to-indigo-50 p-6 rounded-lg">
<h3 className="font-semibold mb-4">Lead Scoring Matrix</h3>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div className="bg-white p-4 rounded shadow">
<h4 className="font-semibold text-red-600">Cold Lead (0-25)</h4>
<ul className="text-sm mt-2 space-y-1">
<li>• Small company</li>
<li>• Low engagement</li>
<li>• No demo interest</li>
</ul>
</div>
<div className="bg-white p-4 rounded shadow">
<h4 className="font-semibold text-yellow-600">Warm Lead (26-50)</h4>
<ul className="text-sm mt-2 space-y-1">
<li>• Medium company</li>
<li>• Some engagement</li>
<li>• Content downloads</li>
</ul>
</div>
<div className="bg-white p-4 rounded shadow">
<h4 className="font-semibold text-orange-600">Hot Lead (51-75)</h4>
<ul className="text-sm mt-2 space-y-1">
<li>• Large company</li>
<li>• High engagement</li>
<li>• Pricing interest</li>
</ul>
</div>
<div className="bg-white p-4 rounded shadow">
<h4 className="font-semibold text-green-600">Qualified Lead (76-100)</h4>
<ul className="text-sm mt-2 space-y-1">
<li>• Enterprise company</li>
<li>• Decision maker</li>
<li>• Demo requested</li>
</ul>
</div>
</div>
</div>
</div>
);
}
```
### Inventory Management Rules
```tsx
const inventoryFields: FieldConfig[] = [
{
name: 'product.sku',
label: 'Product SKU',
type: 'string',
group: 'Product'
},
{
name: 'product.category',
label: 'Product Category',
type: 'string',
group: 'Product'
},
{
name: 'inventory.currentStock',
label: 'Current Stock',
type: 'number',
group: 'Inventory'
},
{
name: 'inventory.minimumStock',
label: 'Minimum Stock Level',
type: 'number',
group: 'Inventory'
},
{
name: 'inventory.maximumStock',
label: 'Maximum Stock Level',
type: 'number',
group: 'Inventory'
},
{
name: 'sales.velocity',
label: 'Sales Velocity (units/day)',
type: 'number',
group: 'Sales'
},
{
name: 'sales.trend',
label: 'Sales Trend',
type: 'string',
group: 'Sales',
values: [
{ value: 'increasing', label: 'Increasing' },
{ value: 'stable', label: 'Stable' },
{ value: 'decreasing', label: 'Decreasing' }
]
},
{
name: 'supplier.leadTime',
label: 'Supplier Lead Time (days)',
type: 'number',
group: 'Supplier'
},
{
name: 'season.current',
label: 'Current Season',
type: 'string',
group: 'Context'
}
];
function InventoryManagementBuilder() {
const sampleData = {
product: {
sku: 'WH-001',
category: 'electronics',
name: 'Wireless Headphones'
},
inventory: {
currentStock: 15,
minimumStock: 10,
maximumStock: 100,
warehouseLocation: 'A1-B2'
},
sales: {
velocity: 2.5,
trend: 'increasing',
lastWeekSales: 18
},
supplier: {
leadTime: 7,
reliability: 0.95,
cost: 45.00
},
season: {
current: 'holiday'
}
};
return (
<div className="space-y-6">
<div className="bg-white p-6 rounded-lg shadow">
<h2 className="text-2xl font-bold mb-4">Inventory Management Rules</h2>
<p className="text-gray-600 mb-6">
Automate inventory decisions with intelligent reordering and stock level management.
</p>
<TreeRuleBuilder
fields={inventoryFields}
sampleData={sampleData}
onChange={(rule) => console.log('Inventory rule:', rule)}
labels={{
addGroup: 'Add Inventory Condition'
}}
/>
</div>
{/* Inventory actions */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="bg-red-50 p-4 rounded border border-red-200">
<h4 className="font-semibold text-red-800">Reorder Alert</h4>
<ul className="text-sm mt-2 space-y-1 text-red-700">
<li>• Stock below minimum</li>
<li>• High sales velocity</li>
<li>• Long supplier lead time</li>
</ul>
</div>
<div className="bg-yellow-50 p-4 rounded border border-yellow-200">
<h4 className="font-semibold text-yellow-800">Overstock Warning</h4>
<ul className="text-sm mt-2 space-y-1 text-yellow-700">
<li>• Stock above maximum</li>
<li>• Decreasing sales trend</li>
<li>• Season ending</li>
</ul>
</div>
<div className="bg-green-50 p-4 rounded border border-green-200">
<h4 className="font-semibold text-green-800">Optimal Stock</h4>
<ul className="text-sm mt-2 space-y-1 text-green-700">
<li>• Between min/max levels</li>
<li>• Stable sales trend</li>
<li>• Adequate supply buffer</li>
</ul>
</div>
</div>
</div>
);
}
```
## Integration Examples
### Complete E-commerce Platform
```tsx
function EcommercePlatformDemo() {
const [activeTab, setActiveTab] = useState('pricing');
return (
<div className="min-h-screen bg-gray-50">
<div className="container mx-auto py-8">
<h1 className="text-3xl font-bold text-center mb-8">
E-commerce Rule Engine Platform
</h1>
<div className="bg-white rounded-lg shadow-lg">
<div className="border-b border-gray-200">
<nav className="flex space-x-8 px-6">
{[
{ id: 'pricing', label: 'Dynamic Pricing' },
{ id: 'shipping', label: 'Shipping Rules' },
{ id: 'promotions', label: 'Promotions' },
{ id: 'inventory', label: 'Inventory' }
].map((tab) => (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
className={`py-4 px-1 border-b-2 font-medium text-sm ${
activeTab === tab.id
? 'border-blue-500 text-blue-600'
: 'border-transparent text-gray-500 hover:text-gray-700'
}`}
>
{tab.label}
</button>
))}
</nav>
</div>
<div className="p-6">
{activeTab === 'pricing' && <DynamicPricingBuilder />}
{activeTab === 'shipping' && <ShippingCalculatorBuilder />}
{activeTab === 'promotions' && <PromotionalCampaignBuilder />}
{activeTab === 'inventory' && <InventoryManagementBuilder />}
</div>
</div>
</div>
</div>
);
}
```
### Multi-tenant SaaS Platform
```tsx
function SaaSRulePlatform() {
const [tenant, setTenant] = useState('tenant1');
const [ruleType, setRuleType] = useState('access');
const tenantData = {
tenant1: {
name: 'Acme Corp',
plan: 'enterprise',
features: ['advanced-rules', 'api-access', 'audit-logs']
},
tenant2: {
name: 'StartupXYZ',
plan: 'pro',
features: ['basic-rules', 'api-access']
}
};
return (
<div className="min-h-screen bg-gray-100">
<header className="bg-white shadow">
<div className="container mx-auto px-6 py-4">
<div className="flex items-center justify-between">
<h1 className="text-2xl font-bold">SaaS Rule Engine</h1>
<div className="flex items-center space-x-4">
<select
value={tenant}
onChange={(e) => setTenant(e.target.value)}
className="border rounded px-3 py-2"
>
<option value="tenant1">Acme Corp</option>
<option value="tenant2">StartupXYZ</option>
</select>
<select
value={ruleType}
onChange={(e) => setRuleType(e.target.value)}
className="border rounded px-3 py-2"
>
<option value="access">Access Control</option>
<option value="validation">Validation</option>
<option value="pricing">Pricing</option>
</select>
</div>
</div>
</div>
</header>
<main className="container mx-auto py-8 px-6">
<div className="bg-white rounded-lg shadow p-6">
<div className="mb-6">
<h2 className="text-xl font-semibold">
{tenantData[tenant].name} - {ruleType.charAt(0).toUpperCase() + ruleType.slice(1)} Rules
</h2>
<p className="text-gray-600">
Plan: {tenantData[tenant].plan} | Features: {tenantData[tenant].features.join(', ')}
</p>
</div>
{ruleType === 'access' && <RBACBuilder />}
{ruleType === 'validation' && <RegistrationValidationBuilder />}
{ruleType === 'pricing' && <DynamicPricingBuilder />}
</div>
</main>
</div>
);
}
```
---
For more examples and detailed implementation guides, see the [main documentation](../README.md).
================================================
FILE: packages/builder/docs/hooks.md
================================================
# Hooks Reference
Comprehensive guide to all hooks available in @usex/rule-engine-builder.
## Table of Contents
- [State Management Hooks](#state-management-hooks)
- [UI Interaction Hooks](#ui-interaction-hooks)
- [Utility Hooks](#utility-hooks)
- [Custom Hook Patterns](#custom-hook-patterns)
## State Management Hooks
### useEnhancedRuleStore
Advanced rule state management with history and undo/redo functionality.
```typescript
interface EnhancedRuleStore {
// Current State
rule: RuleType;
history: HistoryEntry[];
historyIndex: number;
expandedGroups: Set<string>;
// Rule Management
updateRule: (rule: RuleType, action?: string, description?: string) => void;
updateConditions: (conditions: Condition[]) => void;
setRule: (rule: RuleType, action?: string, description?: string) => void;
// History Operations
undo: () => void;
redo: () => void;
canUndo: () => boolean;
canRedo: () => boolean;
getUndoInfo: () => HistoryInfo | null;
getRedoInfo: () => HistoryInfo | null;
getHistoryInfo: () => { current: number; total: number };
// UI State Management
expandAll: () => void;
collapseAll: () => void;
toggleGroup: (groupId: string) => void;
isGroupExpanded: (groupId: string) => boolean;
// Utilities
clearHistory: () => void;
exportHistory: () => HistoryEntry[];
importHistory: (history: HistoryEntry[]) => void;
}
interface HistoryEntry {
rule: RuleType;
timestamp: number;
action: string;
description: string;
changes?: {
before: any;
after: any;
};
}
```
**Usage:**
```tsx
import { useEnhancedRuleStore } from '@usex/rule-engine-builder';
function RuleEditor() {
const {
rule,
updateRule,
undo,
redo,
canUndo,
canRedo,
getHistoryInfo
} = useEnhancedRuleStore();
const handleAddCondition = () => {
const newRule = {
...rule,
conditions: [
...(Array.isArray(rule.conditions) ? rule.conditions : [rule.conditions]),
{ and: [] }
]
};
updateRule(newRule, 'Add', 'Added new condition group');
};
const historyInfo = getHistoryInfo();
return (
<div>
<div className="flex gap-2 mb-4">
<button onClick={undo} disabled={!canUndo()}>
Undo
</button>
<button onClick={redo} disabled={!canRedo()}>
Redo
</button>
<span className="text-sm text-muted-foreground">
{historyInfo.current} / {historyInfo.total}
</span>
</div>
<button onClick={handleAddCondition}>
Add Condition
</button>
{/* Rule builder UI */}
</div>
);
}
```
**Features:**
- **History Management**: 100-entry history with automatic cleanup
- **Action Tracking**: Named actions with descriptions for clear audit trail
- **Change Detection**: Automatic before/after change tracking
- **UI State**: Persistent expand/collapse state for rule groups
- **Export/Import**: Full history serialization support
### useRuleStore
Basic rule state management for simpler use cases.
```typescript
interface RuleStore {
rule: RuleType;
setRule: (rule: RuleType) => void;
updateConditions: (conditions: Condition[]) => void;
reset: () => void;
}
```
**Usage:**
```tsx
import { useRuleStore } from '@usex/rule-engine-builder';
function SimpleRuleEditor() {
const { rule, setRule, updateConditions } = useRuleStore();
return (
<div>
{/* Simple rule editing UI */}
</div>
);
}
```
## UI Interaction Hooks
### useFieldDiscovery
Automatic field discovery from sample data with intelligent type inference.
```typescript
interface FieldDiscoveryOptions {
maxDepth?: number; // Maximum object nesting depth (default: 5)
includeArrayIndices?: boolean; // Include array index paths (default: false)
generateLabels?: boolean; // Auto-generate human-readable labels (default: true)
excludePaths?: string[]; // Paths to exclude from discovery
fieldTypes?: Record<string, FieldType>; // Override field types
groupBy?: 'path' | 'type' | 'custom'; // Grouping strategy
customGrouper?: (field: FieldConfig) => string; // Custom grouping function
}
interface FieldDiscoveryResult {
fields: FieldConfig[];
isLoading: boolean;
error: Error | null;
stats: {
totalFields: number;
byType: Record<FieldType, number>;
byGroup: Record<string, number>;
};
// Actions
discover: (data: any, options?: FieldDiscoveryOptions) => void;
addCustomField: (field: FieldConfig) => void;
removeField: (fieldName: string) => void;
updateField: (fieldName: string, updates: Partial<FieldConfig>) => void;
clearFields: () => void;
// Utilities
findField: (name: string) => FieldConfig | undefined;
getFieldsByGroup: (group: string) => FieldConfig[];
getFieldsByType: (type: FieldType) => FieldConfig[];
exportFields: () => FieldConfig[];
importFields: (fields: FieldConfig[]) => void;
}
```
**Usage:**
```tsx
import { useFieldDiscovery } from '@usex/rule-engine-builder';
function SmartRuleBuilder() {
const {
fields,
isLoading,
discover,
addCustomField,
stats
} = useFieldDiscovery();
const sampleData = {
user: {
name: 'John Doe',
age: 30,
email: 'john@example.com',
preferences: {
theme: 'dark',
notifications: true
}
},
orders: [
{ id: 1, total: 99.99, status: 'completed' },
{ id: 2, total: 149.99, status: 'pending' }
]
};
useEffect(() => {
discover(sampleData, {
maxDepth: 3,
includeArrayIndices: true,
generateLabels: true,
groupBy: 'path'
});
}, [sampleData]);
const handleAddCustomField = () => {
addCustomField({
name: 'customCalculation',
label: 'Custom Calculation',
type: 'number',
group: 'Calculated Fields',
description: 'Custom business logic calculation'
});
};
if (isLoading) return <div>Discovering fields...</div>;
return (
<div>
<div className="mb-4">
<h3>Discovered Fields ({stats.totalFields})</h3>
<div className="text-sm text-muted-foreground">
{Object.entries(stats.byType).map(([type, count]) => (
<span key={type} className="mr-4">
{type}: {count}
</span>
))}
</div>
</div>
<button onClick={handleAddCustomField}>
Add Custom Field
</button>
<TreeRuleBuilder
fields={fields}
sampleData={sampleData}
/>
</div>
);
}
```
**Field Discovery Algorithm:**
1. **Traversal**: Deep object traversal with cycle detection
2. **Type Inference**: Smart type detection based on value analysis
3. **Label Generation**: Humanized labels from camelCase/snake_case paths
4. **Grouping**: Automatic grouping by object hierarchy
5. **Validation**: Field validation and conflict resolution
### useKeyboardShortcuts
Comprehensive keyboard shortcut management with platform detection.
```typescript
interface ShortcutConfig {
key: string; // Key to press (case-insensitive)
ctrl?: boolean; // Ctrl key (Windows/Linux)
cmd?: boolean; // Cmd key (macOS) - auto-maps to ctrl on other platforms
shift?: boolean; // Shift key
alt?: boolean; // Alt/Option key
meta?: boolean; // Meta key (Windows key, Cmd key)
handler: (event: KeyboardEvent) => void; // Handler function
description: string; // Human-readable description
disabled?: boolean; // Temporarily disable shortcut
preventDefault?: boolean; // Prevent default browser behavior (default: true)
stopPropagation?: boolean; // Stop event propagation (default: true)
target?: string | Element; // Specific element to bind to (default: document)
}
interface KeyboardShortcutsAPI {
register: (shortcuts: ShortcutConfig[]) => void;
unregister: (keys: string[]) => void;
enable: (key: string) => void;
disable: (key: string) => void;
getRegistered: () => ShortcutConfig[];
isEnabled: (key: string) => boolean;
}
```
**Usage:**
```tsx
import { useKeyboardShortcuts } from '@usex/rule-engine-builder';
function RuleBuilderWithShortcuts() {
const { rule, updateRule, undo, redo, canUndo, canRedo } = useEnhancedRuleStore();
const [isHelpOpen, setIsHelpOpen] = useState(false);
useKeyboardShortcuts([
{
key: 'z',
ctrl: true,
handler: () => canUndo() && undo(),
description: 'Undo last action'
},
{
key: 'y',
ctrl: true,
handler: () => canRedo() && redo(),
description: 'Redo last action'
},
{
key: 'z',
ctrl: true,
shift: true,
handler: () => canRedo() && redo(),
description: 'Redo last action (alternative)'
},
{
key: 's',
ctrl: true,
handler: (e) => {
e.preventDefault();
handleSave();
},
description: 'Save rule'
},
{
key: 'r',
ctrl: true,
handler: () => addNewConditionGroup(),
description: 'Add new rule group'
},
{
key: 'e',
ctrl: true,
shift: true,
handler: () => expandAll(),
description: 'Expand all groups'
},
{
key: 'c',
ctrl: true,
shift: true,
handler: () => collapseAll(),
description: 'Collapse all groups'
},
{
key: '?',
shift: true,
handler: () => setIsHelpOpen(true),
description: 'Show keyboard shortcuts help'
},
{
key: 'Escape',
handler: () => setIsHelpOpen(false),
description: 'Close dialogs'
}
]);
return (
<div>
<TreeRuleBuilder />
{isHelpOpen && (
<KeyboardShortcutsHelp onClose={() => setIsHelpOpen(false)} />
)}
</div>
);
}
```
**Platform Handling:**
- **macOS**: `cmd` key automatically maps to Cmd key
- **Windows/Linux**: `ctrl` key maps to Ctrl key
- **Auto-detection**: Automatically detects platform and shows appropriate shortcuts
- **Conflict Resolution**: Prevents conflicting shortcuts and provides warnings
### useTheme
Theme management with system preference detection.
```typescript
interface ThemeAPI {
theme: 'light' | 'dark' | 'system';
resolvedTheme: 'light' | 'dark';
setTheme: (theme: 'light' | 'dark' | 'system') => void;
toggleTheme: () => void;
systemTheme: 'light' | 'dark';
}
```
**Usage:**
```tsx
import { useTheme } from '@usex/rule-engine-builder';
function ThemedRuleBuilder() {
const { theme, resolvedTheme, setTheme, toggleTheme } = useTheme();
return (
<div className={`min-h-screen ${resolvedTheme === 'dark' ? 'dark' : ''}`}>
<div className="bg-background text-foreground">
<header className="flex justify-between items-center p-4">
<h1>Rule Builder</h1>
<button onClick={toggleTheme}>
{resolvedTheme === 'dark' ? '☀️' : '🌙'}
</button>
</header>
<TreeRuleBuilder theme={theme} />
</div>
</div>
);
}
```
## Utility Hooks
### useDebounce
Debounce values and callbacks for performance optimization.
```typescript
function useDebounce<T>(value: T, delay: number): T;
function useDebounce<T extends (...args: any[]) => any>(
callback: T,
delay: number
): T;
```
**Usage:**
```tsx
import { useDebounce } from '@usex/rule-engine-builder';
function RuleBuilderWithDebouncing() {
const [rule, setRule] = useState(initialRule);
// Debounce rule changes to avoid excessive API calls
const debouncedRule = useDebounce(rule, 500);
// Debounce the save function
const debouncedSave = useDebounce((rule: RuleType) => {
saveRuleToServer(rule);
}, 1000);
useEffect(() => {
if (debouncedRule) {
debouncedSave(debouncedRule);
}
}, [debouncedRule]);
return (
<TreeRuleBuilder
onChange={setRule}
rule={rule}
/>
);
}
```
### useLocalStorage
Persistent local storage with automatic serialization.
```typescript
function useLocalStorage<T>(
key: string,
defaultValue: T,
options?: {
serializer?: {
read: (value: string) => T;
write: (value: T) => string;
};
syncAcrossTabs?: boolean;
}
): [T, (value: T | ((prev: T) => T)) => void, () => void];
```
**Usage:**
```tsx
import { useLocalStorage } from '@usex/rule-engine-builder';
function PersistentRuleBuilder() {
const [savedRule, setSavedRule, clearSavedRule] = useLocalStorage(
'rule-builder-draft',
{ conditions: [], default: null },
{ syncAcrossTabs: true }
);
const [userPreferences, setUserPreferences] = useLocalStorage(
'rule-builder-preferences',
{
theme: 'system' as const,
showJsonViewer: true,
autoSave: true
}
);
return (
<TreeRuleBuilder
initialRule={savedRule}
onChange={(rule) => {
if (userPreferences.autoSave) {
setSavedRule(rule);
}
}}
showJsonViewer={userPreferences.showJsonViewer}
theme={userPreferences.theme}
/>
);
}
```
### useEventListener
Type-safe event listener management.
```typescript
function useEventListener<T extends keyof WindowEventMap>(
eventType: T,
handler: (event: WindowEventMap[T]) => void,
options?: AddEventListenerOptions
): void;
function useEventListener<T extends keyof HTMLElementEventMap>(
eventType: T,
handler: (event: HTMLElementEventMap[T]) => void,
element: RefObject<HTMLElement>,
options?: AddEventListenerOptions
): void;
```
**Usage:**
```tsx
import { useEventListener } from '@usex/rule-engine-builder';
function RuleBuilderWithEvents() {
const containerRef = useRef<HTMLDivElement>(null);
// Global keyboard events
useEventListener('keydown', (event) => {
if (event.ctrlKey && event.key === 'k') {
event.preventDefault();
openCommandPalette();
}
});
// Container-specific events
useEventListener('drop', (event) => {
event.preventDefault();
handleRuleDrop(event);
}, containerRef);
return (
<div ref={containerRef}>
<TreeRuleBuilder />
</div>
);
}
```
## Custom Hook Patterns
### useAsyncRule
Handle async rule operations with loading states.
```typescript
function useAsyncRule() {
const [rule, setRule] = useState<RuleType | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
const loadRule = useCallback(async (ruleId: string) => {
setIsLoading(true);
setError(null);
try {
const loadedRule = await fetchRule(ruleId);
setRule(loadedRule);
} catch (err) {
setError(err as Error);
} finally {
setIsLoading(false);
}
}, []);
const saveRule = useCallback(async (ruleToSave: RuleType) => {
setIsLoading(true);
setError(null);
try {
const savedRule = await saveRuleToServer(ruleToSave);
setRule(savedRule);
return savedRule;
} catch (err) {
setError(err as Error);
throw err;
} finally {
setIsLoading(false);
}
}, []);
gitextract_v5gxdb39/ ├── .editorconfig ├── .gitattributes ├── .github/ │ ├── CODE_OF_CONDUCT.md │ └── workflows/ │ └── ci.yml ├── .gitignore ├── .idea/ │ ├── .gitignore │ ├── compiler.xml │ ├── git_toolbox_prj.xml │ ├── inspectionProfiles/ │ │ └── Project_Default.xml │ ├── jsLinters/ │ │ └── eslint.xml │ ├── modules.xml │ ├── prettier.xml │ ├── usex.iml │ └── vcs.xml ├── .npmignore ├── .npmrc ├── .nvmrc ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENCE ├── README.md ├── assets/ │ └── BRAND_ASSETS.md ├── docs/ │ ├── architecture.md │ ├── comparison.md │ └── getting-started.md ├── eslint.config.js ├── knip.json ├── package.json ├── packages/ │ ├── builder/ │ │ ├── .gitignore │ │ ├── CHANGELOG.md │ │ ├── README.md │ │ ├── components.json │ │ ├── docs/ │ │ │ ├── README.md │ │ │ ├── RuleEvaluator.md │ │ │ ├── components.md │ │ │ ├── examples.md │ │ │ ├── hooks.md │ │ │ └── integration.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src/ │ │ │ ├── App.tsx │ │ │ ├── components/ │ │ │ │ ├── AdvancedFieldInput.tsx │ │ │ │ ├── AnimatedNumber.tsx │ │ │ │ ├── ConditionGroup.tsx │ │ │ │ ├── ConstraintEditor.tsx │ │ │ │ ├── DiffViewer.tsx │ │ │ │ ├── DraggableConditionGroup.tsx │ │ │ │ ├── DynamicFieldSelector.tsx │ │ │ │ ├── EditableJsonViewer.tsx │ │ │ │ ├── FieldSelector.tsx │ │ │ │ ├── HistoryViewer.tsx │ │ │ │ ├── ImportExport.tsx │ │ │ │ ├── JsonViewer.tsx │ │ │ │ ├── JsonVisualizer.tsx │ │ │ │ ├── ModernConstraintEditor.tsx │ │ │ │ ├── ModernRuleBuilder.tsx │ │ │ │ ├── OperatorSelector.tsx │ │ │ │ ├── RegexValidator.tsx │ │ │ │ ├── ResizablePanel.tsx │ │ │ │ ├── RuleImportModal.tsx │ │ │ │ ├── RuleImporter.tsx │ │ │ │ ├── RuleViewer.tsx │ │ │ │ ├── SmartOperatorSelector.tsx │ │ │ │ ├── ThemeToggle.tsx │ │ │ │ ├── TreeConditionGroup.tsx │ │ │ │ ├── TreeConstraintEditor.tsx │ │ │ │ ├── TreeRuleBuilder.tsx │ │ │ │ ├── UndoRedoInfo.tsx │ │ │ │ ├── ValueInput.tsx │ │ │ │ ├── VisualFieldSelector.tsx │ │ │ │ ├── condition-group.tsx │ │ │ │ ├── editable-json-viewer.tsx │ │ │ │ ├── history-viewer.tsx │ │ │ │ ├── inputs/ │ │ │ │ │ ├── AnimatedNumberInput.tsx │ │ │ │ │ ├── ArrayInput.tsx │ │ │ │ │ ├── BooleanInput.tsx │ │ │ │ │ ├── DateInput.tsx │ │ │ │ │ ├── NumberInput.tsx │ │ │ │ │ └── SmartValueInput.tsx │ │ │ │ ├── operators/ │ │ │ │ │ ├── ArrayOperatorHandler.tsx │ │ │ │ │ ├── BooleanValidationHandler.tsx │ │ │ │ │ ├── ComparisonOperatorHandler.tsx │ │ │ │ │ ├── DateOperatorHandler.tsx │ │ │ │ │ ├── ExistenceOperatorHandler.tsx │ │ │ │ │ ├── LengthValidationHandler.tsx │ │ │ │ │ ├── NumberValidationHandler.tsx │ │ │ │ │ ├── SelfReferenceHandler.tsx │ │ │ │ │ ├── StringValidationHandler.tsx │ │ │ │ │ ├── TypeValidationHandler.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── resizable-panel.tsx │ │ │ │ ├── rule-builder.tsx │ │ │ │ ├── rule-editor.tsx │ │ │ │ ├── rule-evaluator.tsx │ │ │ │ ├── rule-import-modal.tsx │ │ │ │ ├── rule-viewer.tsx │ │ │ │ ├── theme-provider.tsx │ │ │ │ ├── theme-toggle.tsx │ │ │ │ └── ui/ │ │ │ │ ├── alert.tsx │ │ │ │ ├── badge.tsx │ │ │ │ ├── button.tsx │ │ │ │ ├── calendar.tsx │ │ │ │ ├── card.tsx │ │ │ │ ├── collapsible.tsx │ │ │ │ ├── command.tsx │ │ │ │ ├── dialog.tsx │ │ │ │ ├── dropdown-menu.tsx │ │ │ │ ├── input.tsx │ │ │ │ ├── label.tsx │ │ │ │ ├── popover.tsx │ │ │ │ ├── scroll-area.tsx │ │ │ │ ├── select.tsx │ │ │ │ ├── separator.tsx │ │ │ │ ├── sheet.tsx │ │ │ │ ├── slider.tsx │ │ │ │ ├── sonner.tsx │ │ │ │ ├── switch.tsx │ │ │ │ ├── tabs.tsx │ │ │ │ ├── textarea.tsx │ │ │ │ ├── tooltip.tsx │ │ │ │ └── zoom-dialog.tsx │ │ │ ├── constants/ │ │ │ │ └── operator-help.ts │ │ │ ├── data/ │ │ │ │ └── sample-data.ts │ │ │ ├── debug-test.tsx │ │ │ ├── demo.tsx │ │ │ ├── hooks/ │ │ │ │ ├── use-field-discovery.ts │ │ │ │ ├── use-keyboard-shortcuts.ts │ │ │ │ └── use-theme.ts │ │ │ ├── index.ts │ │ │ ├── lib/ │ │ │ │ └── utils.ts │ │ │ ├── main.tsx │ │ │ ├── stores/ │ │ │ │ ├── enhanced-rule-store.ts │ │ │ │ ├── rule-store.ts │ │ │ │ └── unified-rule-store.ts │ │ │ ├── styles/ │ │ │ │ ├── animations.css │ │ │ │ └── globals.css │ │ │ ├── test-demo.tsx │ │ │ ├── test-store-debug.tsx │ │ │ ├── types/ │ │ │ │ └── index.ts │ │ │ ├── utils/ │ │ │ │ ├── json-path.ts │ │ │ │ └── operators.ts │ │ │ └── vite-env.d.ts │ │ ├── tsconfig.app.json │ │ ├── tsconfig.json │ │ ├── tsconfig.node.json │ │ ├── vercel.json │ │ └── vite.config.ts │ └── core/ │ ├── CHANGELOG.md │ ├── README.md │ ├── benchmarks/ │ │ ├── builder.bench.ts │ │ ├── engine.bench.ts │ │ ├── introspector.bench.ts │ │ ├── json-path.bench.ts │ │ ├── mutator.bench.ts │ │ └── validator.bench.ts │ ├── docs/ │ │ ├── README.md │ │ ├── api-reference-v2.md │ │ ├── api-reference.md │ │ ├── best-practices.md │ │ ├── index.md │ │ ├── migration-guide.md │ │ ├── operators.md │ │ ├── refactoring-summary.md │ │ ├── typescript-guide.md │ │ └── v2-migration-guide.md │ ├── package.json │ ├── src/ │ │ ├── enums/ │ │ │ ├── condition-types.enum.ts │ │ │ ├── index.ts │ │ │ └── operators.enum.ts │ │ ├── examples/ │ │ │ └── custom-operator.example.ts │ │ ├── index.ts │ │ ├── operators/ │ │ │ ├── base.ts │ │ │ ├── factory.ts │ │ │ ├── implementations/ │ │ │ │ ├── array.ts │ │ │ │ ├── boolean.ts │ │ │ │ ├── comparison.ts │ │ │ │ ├── date-time.ts │ │ │ │ ├── existence.ts │ │ │ │ ├── index.ts │ │ │ │ ├── numeric.ts │ │ │ │ ├── pattern.ts │ │ │ │ ├── string.ts │ │ │ │ └── type.ts │ │ │ ├── index.ts │ │ │ ├── like.md │ │ │ └── registry.ts │ │ ├── services/ │ │ │ ├── builder.ts │ │ │ ├── evaluator.ts │ │ │ ├── index.ts │ │ │ ├── introspector.ts │ │ │ ├── logger.ts │ │ │ ├── mutator.ts │ │ │ ├── object-discovery.ts │ │ │ ├── rule-engine.ts │ │ │ └── validator.ts │ │ ├── types/ │ │ │ ├── index.ts │ │ │ ├── introspection.type.ts │ │ │ ├── rule.type.ts │ │ │ └── validator.type.ts │ │ └── utils/ │ │ ├── clone.util.ts │ │ ├── date.util.ts │ │ ├── error.util.ts │ │ ├── extract-jsonpath-expressions.util.ts │ │ ├── index.ts │ │ ├── is-object.util.ts │ │ └── time.util.ts │ ├── test/ │ │ ├── builder.spec.ts │ │ ├── engine.spec.ts │ │ ├── introspector.spec.ts │ │ ├── json-path.spec.ts │ │ ├── mutator.spec.ts │ │ ├── operators.spec.ts │ │ ├── rule-engine.spec.ts │ │ ├── rulesets/ │ │ │ ├── invalid2.json.ts │ │ │ ├── password-rule.json.ts │ │ │ ├── regex-rules.json.ts │ │ │ ├── self-fields-constraints.json.ts │ │ │ ├── valid1.json.ts │ │ │ ├── valid10.json.ts │ │ │ ├── valid11.json.ts │ │ │ ├── valid12.json.ts │ │ │ ├── valid13.json.ts │ │ │ ├── valid2.json.ts │ │ │ ├── valid3.json.ts │ │ │ ├── valid4.json.ts │ │ │ ├── valid5.json.ts │ │ │ ├── valid6.json.ts │ │ │ ├── valid7.json.ts │ │ │ ├── valid8.json.ts │ │ │ └── valid9.json.ts │ │ ├── utils.spec.ts │ │ └── validator.spec.ts │ ├── tsconfig.build.json │ ├── tsconfig.json │ ├── tsup.config.ts │ └── vitest.config.ts └── pnpm-workspace.yaml
SYMBOL INDEX (753 symbols across 92 files)
FILE: packages/builder/src/App.tsx
function AppContent (line 56) | function AppContent() {
function App (line 216) | function App() {
FILE: packages/builder/src/components/AdvancedFieldInput.tsx
type AdvancedFieldInputProps (line 31) | interface AdvancedFieldInputProps {
type FieldSuggestion (line 45) | interface FieldSuggestion {
constant RECENT_FIELDS_KEY (line 77) | const RECENT_FIELDS_KEY = "rule-builder-recent-fields";
constant POPULAR_FIELDS_KEY (line 78) | const POPULAR_FIELDS_KEY = "rule-builder-popular-fields";
constant MAX_RECENT_FIELDS (line 79) | const MAX_RECENT_FIELDS = 10;
constant MAX_SUGGESTIONS (line 80) | const MAX_SUGGESTIONS = 50;
constant AI_FIELD_PATTERNS (line 83) | const AI_FIELD_PATTERNS = [
constant JSON_PATH_TEMPLATES (line 111) | const JSON_PATH_TEMPLATES = [
function getFieldType (line 149) | function getFieldType(value: any): string {
function extractFieldsFromData (line 157) | function extractFieldsFromData(
function fuzzyMatch (line 201) | function fuzzyMatch(input: string, target: string): number {
function AdvancedFieldInput (line 227) | function AdvancedFieldInput({
FILE: packages/builder/src/components/AnimatedNumber.tsx
type AnimatedNumberProps (line 4) | interface AnimatedNumberProps {
FILE: packages/builder/src/components/DiffViewer.tsx
type DiffViewerProps (line 29) | interface DiffViewerProps {
type DiffLine (line 179) | interface DiffLine {
type DiffStats (line 189) | interface DiffStats {
FILE: packages/builder/src/components/DraggableConditionGroup.tsx
type DraggableConditionGroupProps (line 25) | interface DraggableConditionGroupProps {
FILE: packages/builder/src/components/DynamicFieldSelector.tsx
type DynamicFieldSelectorProps (line 32) | interface DynamicFieldSelectorProps {
FILE: packages/builder/src/components/EditableJsonViewer.tsx
type EditableJsonViewerProps (line 41) | interface EditableJsonViewerProps {
FILE: packages/builder/src/components/HistoryViewer.tsx
type HistoryViewerProps (line 42) | interface HistoryViewerProps {
FILE: packages/builder/src/components/JsonViewer.tsx
type JsonViewerProps (line 16) | interface JsonViewerProps {
FILE: packages/builder/src/components/JsonVisualizer.tsx
type JsonViewerProps (line 20) | interface JsonViewerProps {
function JsonViewer (line 28) | function JsonViewer({
type JsonNodeProps (line 50) | interface JsonNodeProps {
function JsonNode (line 59) | function JsonNode({
function JsonValue (line 212) | function JsonValue({ data }: { data: any }) {
FILE: packages/builder/src/components/ModernConstraintEditor.tsx
type ModernConstraintEditorProps (line 25) | interface ModernConstraintEditorProps {
FILE: packages/builder/src/components/ModernRuleBuilder.tsx
type ModernRuleBuilderProps (line 32) | interface ModernRuleBuilderProps {
FILE: packages/builder/src/components/OperatorSelector.tsx
type ExtendedOperatorSelectorProps (line 22) | interface ExtendedOperatorSelectorProps extends OperatorSelectorProps {
FILE: packages/builder/src/components/RegexValidator.tsx
type RegexValidatorProps (line 20) | interface RegexValidatorProps {
type RegexMatch (line 29) | interface RegexMatch {
FILE: packages/builder/src/components/ResizablePanel.tsx
type ResizablePanelProps (line 4) | interface ResizablePanelProps {
FILE: packages/builder/src/components/RuleImportModal.tsx
type RuleImportModalProps (line 23) | interface RuleImportModalProps {
FILE: packages/builder/src/components/RuleImporter.tsx
type RuleImporterProps (line 11) | interface RuleImporterProps {
FILE: packages/builder/src/components/SmartOperatorSelector.tsx
type ExtendedOperatorSelectorProps (line 33) | interface ExtendedOperatorSelectorProps extends OperatorSelectorProps {
constant RECENT_OPERATORS_KEY (line 39) | const RECENT_OPERATORS_KEY = "rule-builder-recent-operators";
constant OPERATOR_USAGE_KEY (line 40) | const OPERATOR_USAGE_KEY = "rule-builder-operator-usage";
constant MAX_RECENT_OPERATORS (line 41) | const MAX_RECENT_OPERATORS = 5;
constant SMART_RECOMMENDATIONS (line 44) | const SMART_RECOMMENDATIONS = [
FILE: packages/builder/src/components/TreeConditionGroup.tsx
type TreeConditionGroupProps (line 28) | interface TreeConditionGroupProps {
FILE: packages/builder/src/components/TreeConstraintEditor.tsx
type TreeConstraintEditorProps (line 46) | interface TreeConstraintEditorProps {
FILE: packages/builder/src/components/TreeRuleBuilder.tsx
type TreeRuleBuilderProps (line 43) | interface TreeRuleBuilderProps {
function handleSave (line 295) | async function handleSave() {
FILE: packages/builder/src/components/UndoRedoInfo.tsx
type UndoRedoInfoProps (line 12) | interface UndoRedoInfoProps {
FILE: packages/builder/src/components/VisualFieldSelector.tsx
type VisualFieldSelectorProps (line 41) | interface VisualFieldSelectorProps {
type FieldNode (line 53) | interface FieldNode {
function getTypeColor (line 75) | function getTypeColor(type: string) {
function buildFieldTree (line 197) | function buildFieldTree(
FILE: packages/builder/src/components/editable-json-viewer.tsx
type EditableJsonViewerProps (line 41) | interface EditableJsonViewerProps {
FILE: packages/builder/src/components/history-viewer.tsx
type HistoryViewerProps (line 42) | interface HistoryViewerProps {
FILE: packages/builder/src/components/inputs/AnimatedNumberInput.tsx
type AnimatedNumberInputProps (line 10) | interface AnimatedNumberInputProps {
FILE: packages/builder/src/components/inputs/ArrayInput.tsx
type ArrayInputProps (line 11) | interface ArrayInputProps {
FILE: packages/builder/src/components/inputs/BooleanInput.tsx
type BooleanInputProps (line 6) | interface BooleanInputProps {
FILE: packages/builder/src/components/inputs/DateInput.tsx
type DateInputProps (line 9) | interface DateInputProps {
FILE: packages/builder/src/components/inputs/NumberInput.tsx
type NumberInputProps (line 6) | interface NumberInputProps {
FILE: packages/builder/src/components/inputs/SmartValueInput.tsx
type SmartValueInputProps (line 27) | interface SmartValueInputProps {
FILE: packages/builder/src/components/operators/index.tsx
type OperatorHandlerProps (line 17) | interface OperatorHandlerProps {
FILE: packages/builder/src/components/resizable-panel.tsx
type ResizablePanelProps (line 4) | interface ResizablePanelProps {
FILE: packages/builder/src/components/rule-evaluator.tsx
type EvaluationDetails (line 44) | interface EvaluationDetails {
type RuleEvaluatorProps (line 58) | interface RuleEvaluatorProps {
FILE: packages/builder/src/components/rule-import-modal.tsx
type RuleImportModalProps (line 23) | interface RuleImportModalProps {
FILE: packages/builder/src/components/theme-provider.tsx
type Theme (line 3) | type Theme = "dark" | "light" | "system";
type ThemeProviderProps (line 5) | interface ThemeProviderProps {
type ThemeProviderState (line 11) | interface ThemeProviderState {
function ThemeProvider (line 23) | function ThemeProvider({
FILE: packages/builder/src/components/theme-toggle.tsx
function ThemeToggle (line 11) | function ThemeToggle() {
FILE: packages/builder/src/components/ui/badge.tsx
type BadgeProps (line 30) | interface BadgeProps
function Badge (line 34) | function Badge({ className, variant, ...props }: BadgeProps) {
FILE: packages/builder/src/components/ui/button.tsx
type ButtonProps (line 37) | interface ButtonProps
FILE: packages/builder/src/components/ui/calendar.tsx
type CalendarProps (line 8) | type CalendarProps = React.ComponentProps<typeof DayPicker>;
function Calendar (line 10) | function Calendar({
FILE: packages/builder/src/components/ui/command.tsx
type CommandDialogProps (line 27) | interface CommandDialogProps extends DialogProps {}
FILE: packages/builder/src/components/ui/sheet.tsx
type SheetContentProps (line 54) | interface SheetContentProps
FILE: packages/builder/src/components/ui/sonner.tsx
type ToasterProps (line 4) | type ToasterProps = React.ComponentProps<typeof Sonner>;
FILE: packages/builder/src/components/ui/textarea.tsx
type TextareaProps (line 5) | interface TextareaProps
FILE: packages/builder/src/constants/operator-help.ts
type OperatorHelp (line 1) | interface OperatorHelp {
FILE: packages/builder/src/debug-test.tsx
function TestComponent (line 26) | function TestComponent() {
function DebugTest (line 357) | function DebugTest() {
FILE: packages/builder/src/demo.tsx
type StatsData (line 44) | interface StatsData {
function DemoApp (line 51) | function DemoApp() {
FILE: packages/builder/src/hooks/use-field-discovery.ts
type UseFieldDiscoveryOptions (line 4) | interface UseFieldDiscoveryOptions {
function useFieldDiscovery (line 11) | function useFieldDiscovery(options: UseFieldDiscoveryOptions = {}) {
FILE: packages/builder/src/hooks/use-keyboard-shortcuts.ts
type ShortcutConfig (line 3) | interface ShortcutConfig {
FILE: packages/builder/src/hooks/use-theme.ts
type Theme (line 3) | type Theme = "light" | "dark" | "system";
function useTheme (line 5) | function useTheme() {
FILE: packages/builder/src/lib/utils.ts
function cn (line 5) | function cn(...inputs: ClassValue[]) {
FILE: packages/builder/src/stores/enhanced-rule-store.ts
type HistoryEntry (line 5) | interface HistoryEntry {
type EnhancedRuleStore (line 16) | interface EnhancedRuleStore {
constant MAX_HISTORY (line 61) | const MAX_HISTORY = 100;
FILE: packages/builder/src/stores/rule-store.ts
type RuleStore (line 4) | interface RuleStore {
constant MAX_HISTORY (line 26) | const MAX_HISTORY = 50;
FILE: packages/builder/src/stores/unified-rule-store.ts
type HistoryEntry (line 12) | interface HistoryEntry {
type ValidationError (line 23) | interface ValidationError {
type UnifiedRuleStore (line 28) | interface UnifiedRuleStore {
constant MAX_HISTORY (line 96) | const MAX_HISTORY = 100;
FILE: packages/builder/src/test-demo.tsx
function TestDemo (line 8) | function TestDemo() {
FILE: packages/builder/src/test-store-debug.tsx
function StoreDebugComponent (line 5) | function StoreDebugComponent() {
function StoreDebugTest (line 93) | function StoreDebugTest() {
FILE: packages/builder/src/types/index.ts
type RuleBuilderState (line 10) | interface RuleBuilderState {
type ValidationError (line 16) | interface ValidationError {
type RuleBuilderContextType (line 21) | interface RuleBuilderContextType {
type RuleBuilderProviderProps (line 38) | interface RuleBuilderProviderProps {
type RuleBuilderProps (line 45) | interface RuleBuilderProps {
type RuleEditorProps (line 58) | interface RuleEditorProps {
type ConditionGroupProps (line 65) | interface ConditionGroupProps {
type ConstraintEditorProps (line 76) | interface ConstraintEditorProps {
type FieldSelectorProps (line 86) | interface FieldSelectorProps {
type OperatorSelectorProps (line 95) | interface OperatorSelectorProps {
type ValueInputProps (line 104) | interface ValueInputProps {
type RuleViewerProps (line 114) | interface RuleViewerProps {
type FieldConfig (line 122) | interface FieldConfig {
type OperatorConfig (line 132) | interface OperatorConfig {
type ThemeConfig (line 141) | interface ThemeConfig {
type ImportExportProps (line 158) | interface ImportExportProps {
type ResultEditorProps (line 164) | interface ResultEditorProps {
type ConditionPath (line 173) | type ConditionPath = string;
type ConstraintPath (line 174) | type ConstraintPath = string;
FILE: packages/builder/src/utils/json-path.ts
type PathSegment (line 5) | interface PathSegment {
function parseJsonPath (line 14) | function parseJsonPath(path: string): PathSegment[] {
function buildJsonPath (line 78) | function buildJsonPath(segments: PathSegment[]): string {
function getValueByPath (line 107) | function getValueByPath(obj: any, path: string): any {
function findRecursive (line 163) | function findRecursive(obj: any, key: string): any {
function validateJsonPath (line 187) | function validateJsonPath(path: string): {
function getAllPaths (line 210) | function getAllPaths(obj: any, maxDepth: number = 10): string[] {
function fieldToJsonPath (line 249) | function fieldToJsonPath(field: string): string {
function jsonPathToField (line 260) | function jsonPathToField(path: string): string {
function buildPath (line 277) | function buildPath(...parts: (string | number)[]): string {
FILE: packages/core/src/enums/condition-types.enum.ts
type ConditionTypes (line 2) | enum ConditionTypes {
FILE: packages/core/src/enums/operators.enum.ts
type Operators (line 1) | enum Operators {
FILE: packages/core/src/examples/custom-operator.example.ts
class IPv4Operator (line 13) | class IPv4Operator extends BaseOperatorStrategy<string, void> {
method evaluate (line 26) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 36) | isValidFieldType(value: unknown): value is string {
class CreditCardOperator (line 44) | class CreditCardOperator extends BaseOperatorStrategy<string, string> {
method evaluate (line 57) | evaluate(context: OperatorContext): boolean {
method isValidLuhn (line 75) | private isValidLuhn(cardNumber: string): boolean {
method matchesCardType (line 98) | private matchesCardType(cardNumber: string, type: string): boolean {
method isValidFieldType (line 110) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 114) | isValidConstraintType(value: unknown): value is string {
class RangeOverlapOperator (line 125) | class RangeOverlapOperator extends BaseOperatorStrategy<
method evaluate (line 142) | evaluate(context: OperatorContext): boolean {
method isValidRange (line 159) | private isValidRange(value: unknown): value is [number, number] {
method isValidFieldType (line 169) | isValidFieldType(value: unknown): value is [number, number] {
method isValidConstraintType (line 173) | isValidConstraintType(value: unknown): value is [number, number] {
method validate (line 177) | override validate(
class BusinessHoursOperator (line 206) | class BusinessHoursOperator extends BaseOperatorStrategy<Date, void> {
method evaluate (line 220) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 246) | isValidFieldType(value: unknown): value is Date {
function customOperatorExample (line 258) | async function customOperatorExample() {
function createRegexOperator (line 325) | function createRegexOperator(
FILE: packages/core/src/operators/base.ts
type FieldType (line 6) | type FieldType =
type ValueType (line 19) | type ValueType = FieldType | "regex" | "range" | "void";
type OperatorMetadata (line 24) | interface OperatorMetadata {
type OperatorCategory (line 74) | enum OperatorCategory {
type OperatorContext (line 90) | interface OperatorContext {
type ValidationResult (line 115) | interface ValidationResult {
type OperatorStrategy (line 124) | interface OperatorStrategy<TField = any, TValue = any> {
method validate (line 184) | validate(context: OperatorContext): ValidationResult {
method formatMessage (line 229) | formatMessage(template: string, context: OperatorContext): string {
type OperatorFactory (line 240) | type OperatorFactory = () => OperatorStrategy;
type OperatorConstructor (line 245) | type OperatorConstructor = new () => OperatorStrategy;
FILE: packages/core/src/operators/factory.ts
constant BUILT_IN_OPERATORS (line 140) | const BUILT_IN_OPERATORS: Array<OperatorConstructor> = [
function registerBuiltInOperators (line 276) | function registerBuiltInOperators(override = false): void {
function registerCustomOperator (line 289) | function registerCustomOperator(
function registerCustomOperators (line 301) | function registerCustomOperators(
function initializeOperators (line 312) | function initializeOperators(): void {
FILE: packages/core/src/operators/implementations/array.ts
class ContainsOperator (line 8) | class ContainsOperator extends BaseOperatorStrategy<any[], any> {
method evaluate (line 21) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 29) | isValidFieldType(value: unknown): value is any[] {
class NotContainsOperator (line 37) | class NotContainsOperator extends BaseOperatorStrategy<any[], any> {
method evaluate (line 52) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 56) | isValidFieldType(value: unknown): value is any[] {
class ContainsAnyOperator (line 64) | class ContainsAnyOperator extends BaseOperatorStrategy<any[], any[]> {
method evaluate (line 78) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 87) | isValidFieldType(value: unknown): value is any[] {
method isValidConstraintType (line 91) | isValidConstraintType(value: unknown): value is any[] {
class NotContainsAnyOperator (line 99) | class NotContainsAnyOperator extends BaseOperatorStrategy<any[], any[]> {
method evaluate (line 116) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 120) | isValidFieldType(value: unknown): value is any[] {
method isValidConstraintType (line 124) | isValidConstraintType(value: unknown): value is any[] {
class ContainsAllOperator (line 132) | class ContainsAllOperator extends BaseOperatorStrategy<any[], any[]> {
method evaluate (line 146) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 155) | isValidFieldType(value: unknown): value is any[] {
method isValidConstraintType (line 159) | isValidConstraintType(value: unknown): value is any[] {
class NotContainsAllOperator (line 167) | class NotContainsAllOperator extends BaseOperatorStrategy<any[], any[]> {
method evaluate (line 184) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 188) | isValidFieldType(value: unknown): value is any[] {
method isValidConstraintType (line 192) | isValidConstraintType(value: unknown): value is any[] {
class ArrayLengthOperator (line 200) | class ArrayLengthOperator extends BaseOperatorStrategy<any[], number> {
method evaluate (line 213) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 222) | isValidFieldType(value: unknown): value is any[] {
method isValidConstraintType (line 226) | isValidConstraintType(value: unknown): value is number {
class ArrayMinLengthOperator (line 234) | class ArrayMinLengthOperator extends BaseOperatorStrategy<
method evaluate (line 250) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 259) | isValidFieldType(value: unknown): value is any[] {
method isValidConstraintType (line 263) | isValidConstraintType(value: unknown): value is number {
class ArrayMaxLengthOperator (line 271) | class ArrayMaxLengthOperator extends BaseOperatorStrategy<
method evaluate (line 287) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 296) | isValidFieldType(value: unknown): value is any[] {
method isValidConstraintType (line 300) | isValidConstraintType(value: unknown): value is number {
class SelfContainsAnyOperator (line 308) | class SelfContainsAnyOperator extends BaseOperatorStrategy<
method evaluate (line 326) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 335) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 339) | isValidConstraintType(value: unknown): value is any[] {
class SelfNotContainsAnyOperator (line 347) | class SelfNotContainsAnyOperator extends BaseOperatorStrategy<
method evaluate (line 367) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 371) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 375) | isValidConstraintType(value: unknown): value is any[] {
class SelfContainsAllOperator (line 383) | class SelfContainsAllOperator extends BaseOperatorStrategy<
method evaluate (line 401) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 410) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 414) | isValidConstraintType(value: unknown): value is any[] {
class SelfNotContainsAllOperator (line 422) | class SelfNotContainsAllOperator extends BaseOperatorStrategy<
method evaluate (line 442) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 446) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 450) | isValidConstraintType(value: unknown): value is any[] {
class SelfContainsNoneOperator (line 459) | class SelfContainsNoneOperator extends BaseOperatorStrategy<
method evaluate (line 480) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 484) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 488) | isValidConstraintType(value: unknown): value is any[] {
FILE: packages/core/src/operators/implementations/boolean.ts
class BooleanOperator (line 9) | class BooleanOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 22) | evaluate(context: OperatorContext): boolean {
class NotBooleanOperator (line 31) | class NotBooleanOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 44) | evaluate(context: OperatorContext): boolean {
class BooleanStringOperator (line 53) | class BooleanStringOperator extends BaseOperatorStrategy<string, void> {
method evaluate (line 66) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 74) | isValidFieldType(value: unknown): value is string {
class NotBooleanStringOperator (line 82) | class NotBooleanStringOperator extends BaseOperatorStrategy<
method evaluate (line 100) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 104) | isValidFieldType(value: unknown): value is string {
class BooleanNumberOperator (line 112) | class BooleanNumberOperator extends BaseOperatorStrategy<number, void> {
method evaluate (line 125) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 132) | isValidFieldType(value: unknown): value is number {
class NotBooleanNumberOperator (line 140) | class NotBooleanNumberOperator extends BaseOperatorStrategy<
method evaluate (line 158) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 162) | isValidFieldType(value: unknown): value is number {
class BooleanNumberStringOperator (line 170) | class BooleanNumberStringOperator extends BaseOperatorStrategy<
method evaluate (line 187) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 195) | isValidFieldType(value: unknown): value is string {
class NotBooleanNumberStringOperator (line 203) | class NotBooleanNumberStringOperator extends BaseOperatorStrategy<
method evaluate (line 221) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 225) | isValidFieldType(value: unknown): value is string {
class TruthyOperator (line 233) | class TruthyOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 246) | evaluate(context: OperatorContext): boolean {
class NotTruthyOperator (line 255) | class NotTruthyOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 270) | evaluate(context: OperatorContext): boolean {
class FalsyOperator (line 278) | class FalsyOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 291) | evaluate(context: OperatorContext): boolean {
class NotFalsyOperator (line 300) | class NotFalsyOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 315) | evaluate(context: OperatorContext): boolean {
FILE: packages/core/src/operators/implementations/comparison.ts
class EqualsOperator (line 9) | class EqualsOperator extends BaseOperatorStrategy<any, any> {
method evaluate (line 22) | evaluate(context: OperatorContext): boolean {
class NotEqualsOperator (line 48) | class NotEqualsOperator extends BaseOperatorStrategy<any, any> {
method evaluate (line 64) | evaluate(context: OperatorContext): boolean {
class GreaterThanOperator (line 72) | class GreaterThanOperator extends BaseOperatorStrategy<
method evaluate (line 89) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 99) | isValidFieldType(value: unknown): value is number | string | Date {
method isValidConstraintType (line 107) | isValidConstraintType(value: unknown): value is number | string | Date {
class GreaterThanOrEqualsOperator (line 115) | class GreaterThanOrEqualsOperator extends BaseOperatorStrategy<
method evaluate (line 136) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 143) | isValidFieldType(value: unknown): value is number | string | Date {
method isValidConstraintType (line 147) | isValidConstraintType(value: unknown): value is number | string | Date {
class LessThanOperator (line 155) | class LessThanOperator extends BaseOperatorStrategy<
method evaluate (line 171) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 181) | isValidFieldType(value: unknown): value is number | string | Date {
method isValidConstraintType (line 189) | isValidConstraintType(value: unknown): value is number | string | Date {
class LessThanOrEqualsOperator (line 197) | class LessThanOrEqualsOperator extends BaseOperatorStrategy<
method evaluate (line 218) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 225) | isValidFieldType(value: unknown): value is number | string | Date {
method isValidConstraintType (line 229) | isValidConstraintType(value: unknown): value is number | string | Date {
class InOperator (line 237) | class InOperator extends BaseOperatorStrategy<any, any[]> {
method evaluate (line 251) | evaluate(context: OperatorContext): boolean {
method isValidConstraintType (line 258) | isValidConstraintType(value: unknown): value is any[] {
class NotInOperator (line 266) | class NotInOperator extends BaseOperatorStrategy<any, any[]> {
method evaluate (line 282) | evaluate(context: OperatorContext): boolean {
method isValidConstraintType (line 286) | isValidConstraintType(value: unknown): value is any[] {
class BetweenOperator (line 294) | class BetweenOperator extends BaseOperatorStrategy<
method evaluate (line 310) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 321) | isValidFieldType(value: unknown): value is number {
method isValidConstraintType (line 325) | isValidConstraintType(value: unknown): value is [number, number] {
method validate (line 334) | override validate(
class NotBetweenOperator (line 360) | class NotBetweenOperator extends BaseOperatorStrategy<
method evaluate (line 379) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 383) | isValidFieldType(value: unknown): value is number {
method isValidConstraintType (line 387) | isValidConstraintType(value: unknown): value is [number, number] {
method validate (line 391) | override validate(
FILE: packages/core/src/operators/implementations/date-time.ts
function parseDate (line 8) | function parseDate(value: any): Date | null {
function parseTime (line 20) | function parseTime(value: string): number | null {
class DateAfterOperator (line 45) | class DateAfterOperator extends BaseOperatorStrategy<
method evaluate (line 62) | evaluate(context: OperatorContext): boolean {
class DateAfterNowOperator (line 77) | class DateAfterNowOperator extends BaseOperatorStrategy<
method evaluate (line 93) | evaluate(context: OperatorContext): boolean {
class DateBeforeOperator (line 106) | class DateBeforeOperator extends BaseOperatorStrategy<
method evaluate (line 123) | evaluate(context: OperatorContext): boolean {
class DateBeforeNowOperator (line 138) | class DateBeforeNowOperator extends BaseOperatorStrategy<
method evaluate (line 154) | evaluate(context: OperatorContext): boolean {
class DateEqualsOperator (line 167) | class DateEqualsOperator extends BaseOperatorStrategy<
method evaluate (line 184) | evaluate(context: OperatorContext): boolean {
class DateEqualsToNowOperator (line 199) | class DateEqualsToNowOperator extends BaseOperatorStrategy<
method evaluate (line 215) | evaluate(context: OperatorContext): boolean {
class DateNotEqualsOperator (line 230) | class DateNotEqualsOperator extends BaseOperatorStrategy<
method evaluate (line 249) | evaluate(context: OperatorContext): boolean {
class DateAfterOrEqualsOperator (line 257) | class DateAfterOrEqualsOperator extends BaseOperatorStrategy<
method evaluate (line 275) | evaluate(context: OperatorContext): boolean {
class DateBeforeOrEqualsOperator (line 290) | class DateBeforeOrEqualsOperator extends BaseOperatorStrategy<
method evaluate (line 308) | evaluate(context: OperatorContext): boolean {
class DateBetweenOperator (line 323) | class DateBetweenOperator extends BaseOperatorStrategy<
method evaluate (line 340) | evaluate(context: OperatorContext): boolean {
method isValidConstraintType (line 355) | isValidConstraintType(value: unknown): value is [any, any] {
class DateNotBetweenOperator (line 363) | class DateNotBetweenOperator extends BaseOperatorStrategy<
method evaluate (line 382) | evaluate(context: OperatorContext): boolean {
method isValidConstraintType (line 386) | isValidConstraintType(value: unknown): value is [any, any] {
class TimeAfterOperator (line 394) | class TimeAfterOperator extends BaseOperatorStrategy<string, string> {
method evaluate (line 408) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 422) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 426) | isValidConstraintType(value: unknown): value is string {
class TimeBeforeOperator (line 434) | class TimeBeforeOperator extends BaseOperatorStrategy<string, string> {
method evaluate (line 448) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 462) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 466) | isValidConstraintType(value: unknown): value is string {
class TimeEqualsOperator (line 474) | class TimeEqualsOperator extends BaseOperatorStrategy<string, string> {
method evaluate (line 488) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 502) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 506) | isValidConstraintType(value: unknown): value is string {
class TimeBetweenOperator (line 514) | class TimeBetweenOperator extends BaseOperatorStrategy<
method evaluate (line 531) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 552) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 556) | isValidConstraintType(value: unknown): value is [string, string] {
class DateOperator (line 569) | class DateOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 582) | evaluate(context: OperatorContext): boolean {
class NotDateOperator (line 592) | class NotDateOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 607) | evaluate(context: OperatorContext): boolean {
class TimeAfterOrEqualsOperator (line 615) | class TimeAfterOrEqualsOperator extends BaseOperatorStrategy<
method evaluate (line 633) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 647) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 651) | isValidConstraintType(value: unknown): value is string {
class TimeBeforeOrEqualsOperator (line 659) | class TimeBeforeOrEqualsOperator extends BaseOperatorStrategy<
method evaluate (line 677) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 691) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 695) | isValidConstraintType(value: unknown): value is string {
class TimeNotEqualsOperator (line 703) | class TimeNotEqualsOperator extends BaseOperatorStrategy<
method evaluate (line 720) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 734) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 738) | isValidConstraintType(value: unknown): value is string {
class TimeNotBetweenOperator (line 746) | class TimeNotBetweenOperator extends BaseOperatorStrategy<
method evaluate (line 763) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 784) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 788) | isValidConstraintType(value: unknown): value is [string, string] {
class DateNotEqualsToNowOperator (line 801) | class DateNotEqualsToNowOperator extends BaseOperatorStrategy<
method evaluate (line 819) | evaluate(context: OperatorContext): boolean {
class DateAfterNowOrEqualsOperator (line 827) | class DateAfterNowOrEqualsOperator extends BaseOperatorStrategy<
method evaluate (line 844) | evaluate(context: OperatorContext): boolean {
class DateBeforeNowOrEqualsOperator (line 857) | class DateBeforeNowOrEqualsOperator extends BaseOperatorStrategy<
method evaluate (line 874) | evaluate(context: OperatorContext): boolean {
FILE: packages/core/src/operators/implementations/existence.ts
class ExistsOperator (line 8) | class ExistsOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 21) | evaluate(context: OperatorContext): boolean {
class NotExistsOperator (line 39) | class NotExistsOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 54) | evaluate(context: OperatorContext): boolean {
class NullOrUndefinedOperator (line 62) | class NullOrUndefinedOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 75) | evaluate(context: OperatorContext): boolean {
class NotNullOrUndefinedOperator (line 84) | class NotNullOrUndefinedOperator extends BaseOperatorStrategy<
method evaluate (line 102) | evaluate(context: OperatorContext): boolean {
class EmptyOperator (line 110) | class EmptyOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 124) | evaluate(context: OperatorContext): boolean {
class NotEmptyOperator (line 148) | class NotEmptyOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 163) | evaluate(context: OperatorContext): boolean {
class NullOrWhiteSpaceOperator (line 171) | class NullOrWhiteSpaceOperator extends BaseOperatorStrategy<
method evaluate (line 188) | evaluate(context: OperatorContext): boolean {
class NotNullOrWhiteSpaceOperator (line 204) | class NotNullOrWhiteSpaceOperator extends BaseOperatorStrategy<
method evaluate (line 223) | evaluate(context: OperatorContext): boolean {
FILE: packages/core/src/operators/implementations/numeric.ts
class NumericOperator (line 9) | class NumericOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 22) | evaluate(context: OperatorContext): boolean {
class NotNumericOperator (line 41) | class NotNumericOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 56) | evaluate(context: OperatorContext): boolean {
class NumberOperator (line 64) | class NumberOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 77) | evaluate(context: OperatorContext): boolean {
class NotNumberOperator (line 86) | class NotNumberOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 101) | evaluate(context: OperatorContext): boolean {
class IntegerOperator (line 109) | class IntegerOperator extends BaseOperatorStrategy<number, void> {
method evaluate (line 122) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 127) | isValidFieldType(value: unknown): value is number {
class NotIntegerOperator (line 135) | class NotIntegerOperator extends BaseOperatorStrategy<number, void> {
method evaluate (line 150) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 154) | isValidFieldType(value: unknown): value is number {
class FloatOperator (line 162) | class FloatOperator extends BaseOperatorStrategy<number, void> {
method evaluate (line 175) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 180) | isValidFieldType(value: unknown): value is number {
class NotFloatOperator (line 188) | class NotFloatOperator extends BaseOperatorStrategy<number, void> {
method evaluate (line 203) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 207) | isValidFieldType(value: unknown): value is number {
class PositiveOperator (line 215) | class PositiveOperator extends BaseOperatorStrategy<number, void> {
method evaluate (line 228) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 233) | isValidFieldType(value: unknown): value is number {
class NotPositiveOperator (line 241) | class NotPositiveOperator extends BaseOperatorStrategy<number, void> {
method evaluate (line 256) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 260) | isValidFieldType(value: unknown): value is number {
class NegativeOperator (line 268) | class NegativeOperator extends BaseOperatorStrategy<number, void> {
method evaluate (line 281) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 286) | isValidFieldType(value: unknown): value is number {
class NotNegativeOperator (line 294) | class NotNegativeOperator extends BaseOperatorStrategy<number, void> {
method evaluate (line 309) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 313) | isValidFieldType(value: unknown): value is number {
class ZeroOperator (line 321) | class ZeroOperator extends BaseOperatorStrategy<number, void> {
method evaluate (line 334) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 339) | isValidFieldType(value: unknown): value is number {
class NotZeroOperator (line 347) | class NotZeroOperator extends BaseOperatorStrategy<number, void> {
method evaluate (line 362) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 366) | isValidFieldType(value: unknown): value is number {
class MinOperator (line 374) | class MinOperator extends BaseOperatorStrategy<number, number> {
method evaluate (line 388) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 398) | isValidFieldType(value: unknown): value is number {
method isValidConstraintType (line 402) | isValidConstraintType(value: unknown): value is number {
class MaxOperator (line 410) | class MaxOperator extends BaseOperatorStrategy<number, number> {
method evaluate (line 424) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 434) | isValidFieldType(value: unknown): value is number {
method isValidConstraintType (line 438) | isValidConstraintType(value: unknown): value is number {
class NumberBetweenOperator (line 446) | class NumberBetweenOperator extends BaseOperatorStrategy<
method evaluate (line 462) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 479) | isValidFieldType(value: unknown): value is number {
method isValidConstraintType (line 483) | isValidConstraintType(value: unknown): value is [number, number] {
class NotNumberBetweenOperator (line 496) | class NotNumberBetweenOperator extends BaseOperatorStrategy<
method evaluate (line 515) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 519) | isValidFieldType(value: unknown): value is number {
method isValidConstraintType (line 523) | isValidConstraintType(value: unknown): value is [number, number] {
FILE: packages/core/src/operators/implementations/pattern.ts
class EmailOperator (line 9) | class EmailOperator extends BaseOperatorStrategy<string, void> {
method evaluate (line 24) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 32) | isValidFieldType(value: unknown): value is string {
class NotEmailOperator (line 40) | class NotEmailOperator extends BaseOperatorStrategy<string, void> {
method evaluate (line 55) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 59) | isValidFieldType(value: unknown): value is string {
class UrlOperator (line 67) | class UrlOperator extends BaseOperatorStrategy<string, void> {
method evaluate (line 80) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 93) | isValidFieldType(value: unknown): value is string {
class NotUrlOperator (line 101) | class NotUrlOperator extends BaseOperatorStrategy<string, void> {
method evaluate (line 116) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 120) | isValidFieldType(value: unknown): value is string {
class UUIDOperator (line 128) | class UUIDOperator extends BaseOperatorStrategy<string, void> {
method evaluate (line 144) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 152) | isValidFieldType(value: unknown): value is string {
class NotUUIDOperator (line 160) | class NotUUIDOperator extends BaseOperatorStrategy<string, void> {
method evaluate (line 175) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 179) | isValidFieldType(value: unknown): value is string {
class AlphaOperator (line 187) | class AlphaOperator extends BaseOperatorStrategy<string, void> {
method evaluate (line 203) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 211) | isValidFieldType(value: unknown): value is string {
class NotAlphaOperator (line 219) | class NotAlphaOperator extends BaseOperatorStrategy<string, void> {
method evaluate (line 235) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 239) | isValidFieldType(value: unknown): value is string {
class AlphaNumericOperator (line 247) | class AlphaNumericOperator extends BaseOperatorStrategy<string, void> {
method evaluate (line 263) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 271) | isValidFieldType(value: unknown): value is string {
class NotAlphaNumericOperator (line 279) | class NotAlphaNumericOperator extends BaseOperatorStrategy<
method evaluate (line 298) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 302) | isValidFieldType(value: unknown): value is string {
class PersianAlphaOperator (line 310) | class PersianAlphaOperator extends BaseOperatorStrategy<string, void> {
method evaluate (line 324) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 332) | isValidFieldType(value: unknown): value is string {
class NotPersianAlphaOperator (line 340) | class NotPersianAlphaOperator extends BaseOperatorStrategy<
method evaluate (line 359) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 363) | isValidFieldType(value: unknown): value is string {
class PersianAlphaNumericOperator (line 371) | class PersianAlphaNumericOperator extends BaseOperatorStrategy<
method evaluate (line 390) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 398) | isValidFieldType(value: unknown): value is string {
class NotPersianAlphaNumericOperator (line 406) | class NotPersianAlphaNumericOperator extends BaseOperatorStrategy<
method evaluate (line 425) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 429) | isValidFieldType(value: unknown): value is string {
class LowerCaseOperator (line 437) | class LowerCaseOperator extends BaseOperatorStrategy<string, void> {
method evaluate (line 450) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 458) | isValidFieldType(value: unknown): value is string {
class NotLowerCaseOperator (line 466) | class NotLowerCaseOperator extends BaseOperatorStrategy<string, void> {
method evaluate (line 481) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 485) | isValidFieldType(value: unknown): value is string {
class UpperCaseOperator (line 493) | class UpperCaseOperator extends BaseOperatorStrategy<string, void> {
method evaluate (line 506) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 514) | isValidFieldType(value: unknown): value is string {
class NotUpperCaseOperator (line 522) | class NotUpperCaseOperator extends BaseOperatorStrategy<string, void> {
method evaluate (line 537) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 541) | isValidFieldType(value: unknown): value is string {
FILE: packages/core/src/operators/implementations/string.ts
class LikeOperator (line 8) | class LikeOperator extends BaseOperatorStrategy<string, string> {
method evaluate (line 21) | evaluate(context: OperatorContext): boolean {
method performLikeMatch (line 30) | private performLikeMatch(
method isValidFieldType (line 66) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 70) | isValidConstraintType(value: unknown): value is string {
class NotLikeOperator (line 78) | class NotLikeOperator extends BaseOperatorStrategy<string, string> {
method evaluate (line 93) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 97) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 101) | isValidConstraintType(value: unknown): value is string {
class StartsWithOperator (line 109) | class StartsWithOperator extends BaseOperatorStrategy<string, string> {
method evaluate (line 122) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 131) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 135) | isValidConstraintType(value: unknown): value is string {
class EndsWithOperator (line 143) | class EndsWithOperator extends BaseOperatorStrategy<string, string> {
method evaluate (line 156) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 165) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 169) | isValidConstraintType(value: unknown): value is string {
class ContainsStringOperator (line 177) | class ContainsStringOperator extends BaseOperatorStrategy<
method evaluate (line 194) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 203) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 207) | isValidConstraintType(value: unknown): value is string {
class StringLengthOperator (line 215) | class StringLengthOperator extends BaseOperatorStrategy<string, number> {
method evaluate (line 228) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 237) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 241) | isValidConstraintType(value: unknown): value is number {
class MinLengthOperator (line 249) | class MinLengthOperator extends BaseOperatorStrategy<string, number> {
method evaluate (line 262) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 271) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 275) | isValidConstraintType(value: unknown): value is number {
class MaxLengthOperator (line 283) | class MaxLengthOperator extends BaseOperatorStrategy<string, number> {
method evaluate (line 296) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 305) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 309) | isValidConstraintType(value: unknown): value is number {
class LengthBetweenOperator (line 317) | class LengthBetweenOperator extends BaseOperatorStrategy<
method evaluate (line 334) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 345) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 349) | isValidConstraintType(value: unknown): value is [number, number] {
method validate (line 358) | override validate(
class NotLengthBetweenOperator (line 390) | class NotLengthBetweenOperator extends BaseOperatorStrategy<
method evaluate (line 409) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 413) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 417) | isValidConstraintType(value: unknown): value is [number, number] {
class NotStringLengthOperator (line 430) | class NotStringLengthOperator extends BaseOperatorStrategy<
method evaluate (line 450) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 454) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 458) | isValidConstraintType(value: unknown): value is number {
class MatchesOperator (line 466) | class MatchesOperator extends BaseOperatorStrategy<string, string> {
method evaluate (line 481) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 506) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 510) | isValidConstraintType(value: unknown): value is string {
method validate (line 514) | override validate(
class NotMatchesOperator (line 552) | class NotMatchesOperator extends BaseOperatorStrategy<string, string> {
method evaluate (line 568) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 572) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 576) | isValidConstraintType(value: unknown): value is string {
method validate (line 580) | override validate(
FILE: packages/core/src/operators/implementations/type.ts
class StringOperator (line 8) | class StringOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 21) | evaluate(context: OperatorContext): boolean {
class NotStringOperator (line 30) | class NotStringOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 45) | evaluate(context: OperatorContext): boolean {
class ObjectOperator (line 53) | class ObjectOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 66) | evaluate(context: OperatorContext): boolean {
class NotObjectOperator (line 79) | class NotObjectOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 94) | evaluate(context: OperatorContext): boolean {
class ArrayOperator (line 102) | class ArrayOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 115) | evaluate(context: OperatorContext): boolean {
class NotArrayOperator (line 124) | class NotArrayOperator extends BaseOperatorStrategy<any, void> {
method evaluate (line 139) | evaluate(context: OperatorContext): boolean {
FILE: packages/core/src/operators/index.ts
function equalsOperator (line 30) | function equalsOperator(value: any, compareValue: any): boolean {
function greaterThanOperator (line 62) | function greaterThanOperator(value: any, compareValue: any): boolean {
function greaterThanOrEqualsOperator (line 75) | function greaterThanOrEqualsOperator(
function lessThanOperator (line 90) | function lessThanOperator(value: any, compareValue: any): boolean {
function lessThanOrEqualsOperator (line 103) | function lessThanOrEqualsOperator(
function likeOperator (line 140) | function likeOperator(
function isNullOrWhiteSpaceOperator (line 235) | function isNullOrWhiteSpaceOperator(value: string): boolean {
function isNumericOperator (line 239) | function isNumericOperator(value: any): boolean {
function isBooleanOperator (line 243) | function isBooleanOperator(value: any): boolean {
function isDateOperator (line 247) | function isDateOperator(value: any): boolean {
function isEmailOperator (line 255) | function isEmailOperator(value: string): boolean {
function isUrlOperator (line 260) | function isUrlOperator(value: string): boolean {
function isUuidOperator (line 269) | function isUuidOperator(value: string): boolean {
function isAlphaOperator (line 284) | function isAlphaOperator(value: string): boolean {
function isPersianAlphaOperator (line 288) | function isPersianAlphaOperator(value: string): boolean {
function isAlphaNumericOperator (line 294) | function isAlphaNumericOperator(value: string): boolean {
function isPersianAlphaNumericOperator (line 299) | function isPersianAlphaNumericOperator(value: string): boolean {
function isLowerCaseOperator (line 305) | function isLowerCaseOperator(value: string): boolean {
function isUpperCaseOperator (line 309) | function isUpperCaseOperator(value: string): boolean {
function isStringOperator (line 313) | function isStringOperator(value: any): boolean {
function isObjectOperator (line 317) | function isObjectOperator(value: any): boolean {
function isArrayOperator (line 321) | function isArrayOperator(value: any): boolean {
function isBooleanStringOperator (line 325) | function isBooleanStringOperator(value: string): boolean {
function isBooleanNumberOperator (line 329) | function isBooleanNumberOperator(value: any): boolean {
function isBooleanNumberStringOperator (line 333) | function isBooleanNumberStringOperator(value: any): boolean {
function isNumberOperator (line 337) | function isNumberOperator(value: any): boolean {
function isIntegerOperator (line 353) | function isIntegerOperator(value: any): boolean {
function isFloatOperator (line 359) | function isFloatOperator(value: any): boolean {
function isPositiveOperator (line 368) | function isPositiveOperator(value: any): boolean {
function isNegativeOperator (line 374) | function isNegativeOperator(value: any): boolean {
function isZeroOperator (line 380) | function isZeroOperator(value: any): boolean {
function isNumberBetweenOperator (line 386) | function isNumberBetweenOperator(
function isLengthOperator (line 397) | function isLengthOperator(value: any, compareValue: any): boolean {
function isMinLengthOperator (line 404) | function isMinLengthOperator(value: any, compareValue: any): boolean {
function isMaxLengthOperator (line 411) | function isMaxLengthOperator(value: any, compareValue: any): boolean {
function IsLengthBetweenOperator (line 418) | function IsLengthBetweenOperator(
function isMinOperator (line 429) | function isMinOperator(value: any, compareValue: any): boolean {
function isMaxOperator (line 436) | function isMaxOperator(value: any, compareValue: any): boolean {
function isBetweenOperator (line 440) | function isBetweenOperator(value: any, compareValues: any[]): boolean {
function isFalsyOperator (line 448) | function isFalsyOperator(value: any): boolean {
function isTruthyOperator (line 461) | function isTruthyOperator(value: any): boolean {
function inOperator (line 472) | function inOperator(value: any, compareValues: any[]): boolean {
function containsOperator (line 478) | function containsOperator(value: any, compareValue: any): boolean {
function selfContainsAllOperator (line 484) | function selfContainsAllOperator(
function selfContainsAnyOperator (line 493) | function selfContainsAnyOperator(
function selfContainsNoneOperator (line 502) | function selfContainsNoneOperator(
function containsAnyOperator (line 511) | function containsAnyOperator(value: any, compareValues: any[]): boolean {
function containsAllOperator (line 517) | function containsAllOperator(value: any, compareValues: any[]): boolean {
function matchesOperator (line 523) | function matchesOperator(value: string, pattern: string): boolean {
function isExistsInObjectOperator (line 533) | function isExistsInObjectOperator(key: any, obj: any): boolean {
function isNullOrUndefinedOperator (line 539) | function isNullOrUndefinedOperator(value: any): boolean {
function isEmptyOperator (line 543) | function isEmptyOperator(value: any): boolean {
function isDateAfterOperator (line 551) | function isDateAfterOperator(left: any, right: any): boolean {
function isDateAfterNowOperator (line 565) | function isDateAfterNowOperator(value: any): boolean {
function isDateBeforeOperator (line 573) | function isDateBeforeOperator(left: any, right: any): boolean {
function isDateBeforeNowOperator (line 587) | function isDateBeforeNowOperator(value: any): boolean {
function isDateAfterOrEqualsOperator (line 595) | function isDateAfterOrEqualsOperator(left: any, right: any): boolean {
function isDateAfterNowOrEqualsOperator (line 606) | function isDateAfterNowOrEqualsOperator(value: any): boolean {
function isDateBeforeOrEqualsOperator (line 614) | function isDateBeforeOrEqualsOperator(left: any, right: any): boolean {
function isDateBeforeNowOrEqualsOperator (line 625) | function isDateBeforeNowOrEqualsOperator(value: any): boolean {
function isDateEqualsOperator (line 633) | function isDateEqualsOperator(left: any, right: any): boolean {
function isDateEqualsToNowOperator (line 644) | function isDateEqualsToNowOperator(dateValue: any): boolean {
function isDateBetweenOperator (line 654) | function isDateBetweenOperator(left: any, rightRange: any[]): boolean {
function isTimeAfterOperator (line 674) | function isTimeAfterOperator(left: any, right: any): boolean {
function isTimeBeforeOperator (line 682) | function isTimeBeforeOperator(left: any, right: any): boolean {
function isTimeAfterOrEqualsOperator (line 690) | function isTimeAfterOrEqualsOperator(left: any, right: any): boolean {
function isTimeBeforeOrEqualsOperator (line 698) | function isTimeBeforeOrEqualsOperator(left: any, right: any): boolean {
function isTimeEqualsOperator (line 706) | function isTimeEqualsOperator(left: any, right: any): boolean {
function isTimeBetweenOperator (line 714) | function isTimeBetweenOperator(left: any, right: any[]): boolean {
FILE: packages/core/src/operators/registry.ts
class OperatorRegistry (line 14) | class OperatorRegistry {
method constructor (line 20) | private constructor() {
method getInstance (line 27) | static getInstance(): OperatorRegistry {
method register (line 39) | register(
method registerMany (line 68) | registerMany(
method unregister (line 81) | unregister(name: OperatorsType): boolean {
method get (line 92) | get(name: OperatorsType): OperatorStrategy | null {
method has (line 101) | has(name: OperatorsType): boolean {
method getOperatorNames (line 108) | getOperatorNames(): OperatorsType[] {
method getAllMetadata (line 115) | getAllMetadata(): OperatorMetadata[] {
method getByCategory (line 123) | getByCategory(category: OperatorCategory): OperatorMetadata[] {
method getByFieldType (line 131) | getByFieldType(fieldType: string): OperatorMetadata[] {
method clear (line 140) | clear(): void {
method isInitialized (line 149) | isInitialized(): boolean {
method markInitialized (line 156) | markInitialized(): void {
method getNegatedOperator (line 165) | getNegatedOperator(name: OperatorsType): OperatorsType | null {
method createInstance (line 219) | private createInstance(
method export (line 231) | export(): {
method import (line 250) | import(data: {
FILE: packages/core/src/services/builder.ts
class RuleBuilder (line 11) | class RuleBuilder<T = any> {
method constructor (line 15) | constructor(public readonly validator: Validator) {}
method add (line 22) | add(node: Condition<T>): RuleBuilder<T> {
method default (line 34) | default(value: RuleType["default"]): RuleBuilder<T> {
method build (line 47) | build(validate?: boolean): RuleType<T> {
method condition (line 68) | condition(
method constraint (line 87) | constraint(
FILE: packages/core/src/services/evaluator.ts
class Evaluator (line 16) | class Evaluator<T = any> {
method evaluate (line 47) | evaluate(
method evaluateRule (line 76) | private evaluateRule(
method evaluateCondition (line 127) | private evaluateCondition(
method evaluateConstraint (line 240) | private evaluateConstraint(
method resolveConstraintValue (line 324) | private resolveConstraintValue(value: any, criteria: Criteria): any {
method mutateResultMessage (line 366) | mutateResultMessage(
FILE: packages/core/src/services/introspector.ts
type EnhancedIntrospectionResult (line 23) | interface EnhancedIntrospectionResult<R = any>
class Introspector (line 76) | class Introspector {
method introspect (line 100) | introspect<R = any>(
method validateOperators (line 188) | validateOperators(rule: RuleType): { isValid: boolean; errors: string[...
method getUsedOperators (line 203) | getUsedOperators(rule: RuleType): Set<OperatorsType> {
method validateConditionsOperators (line 215) | private validateConditionsOperators(
method collectOperatorsFromConditions (line 242) | private collectOperatorsFromConditions(
method buildOperatorMetadata (line 264) | private buildOperatorMetadata() {
method resetState (line 296) | private resetState(): void {
method resolveCriteriaRanges (line 314) | private resolveCriteriaRanges<T>(
method populateCriteriaRangeOptions (line 382) | private populateCriteriaRangeOptions<T>(
method updateCriteriaRangeOptions (line 476) | private updateCriteriaRangeOptions(
method addOptionToCriteriaRange (line 562) | private addOptionToCriteriaRange<T>(
method isCurrentStepChildOf (line 696) | private isCurrentStepChildOf(parentType: ConditionType): boolean {
method lastStep (line 717) | get lastStep(): IntrospectionStep | null {
FILE: packages/core/src/services/logger.ts
class Logger (line 1) | class Logger {
method debug (line 2) | static debug(...opts: any[]): void {
FILE: packages/core/src/services/mutator.ts
class Mutator (line 29) | class Mutator {
method add (line 51) | add(
method remove (line 76) | remove(names: string | Array<string>): void {
method removeAll (line 93) | removeAll(): void {
method clearCache (line 105) | clearCache(name?: string): void {
method mutate (line 127) | async mutate(criteria: Criteria): Promise<Criteria> {
method hasMutations (line 172) | private hasMutations(criteria: CriteriaObject, result = false): boolean {
method applyMutations (line 195) | private async applyMutations(criteria: CriteriaObject): Promise<void> {
method execMutation (line 225) | private async execMutation(
FILE: packages/core/src/services/object-discovery.ts
class ObjectDiscovery (line 20) | class ObjectDiscovery<T = any> {
method getConditions (line 25) | getConditions(rule: RuleType<T>): Array<Condition<T>> {
method conditionType (line 33) | conditionType(condition: Condition<T>): ConditionType | null {
method isGranular (line 51) | isGranular(rule: RuleType<T>): boolean {
method isCondition (line 72) | isCondition(obj: object): obj is Condition {
method isConstraint (line 80) | isConstraint(obj: object): obj is Constraint {
method resolveProperty (line 103) | resolveProperty(path: string, json: Criteria<T>): any {
method updateProperty (line 142) | updateProperty(path: string, json: Criteria<T>, value: any): any {
method resolveTextPathExpressions (line 187) | resolveTextPathExpressions(str: string, criteria: Criteria<T>): string {
FILE: packages/core/src/services/rule-engine.ts
type RuleEngineConfig (line 18) | interface RuleEngineConfig {
class RuleEngine (line 53) | class RuleEngine {
method constructor (line 66) | private constructor(config?: RuleEngineConfig) {
method getInstance (line 73) | static getInstance(config?: RuleEngineConfig): RuleEngine {
method configure (line 83) | configure(config?: RuleEngineConfig): void {
method evaluate (line 137) | async evaluate<T = any>(
method checkIsPassed (line 206) | async checkIsPassed(
method getEvaluateResult (line 245) | async getEvaluateResult<T = any>(
method evaluateMany (line 280) | async evaluateMany<T = any>(
method introspect (line 303) | introspect<R = any>(
method validate (line 323) | validate(rule: RuleType): ReturnType<Validator["validate"]> {
method validateOperators (line 330) | validateOperators(rule: RuleType): { isValid: boolean; errors: string[...
method getUsedOperators (line 337) | getUsedOperators(rule: RuleType): Set<string> {
method builder (line 344) | builder(): RuleBuilder {
method registerMutation (line 351) | registerMutation(field: string, mutation: (value: any) => any): void {
method addMutation (line 358) | addMutation(field: string, mutation: (value: any) => any): void {
method removeMutation (line 365) | removeMutation(field: string): void {
method clearMutationCache (line 372) | clearMutationCache(field?: string): void {
method clearMutations (line 379) | clearMutations(): void {
method clearCache (line 386) | clearCache(): void {
method getOperatorRegistry (line 393) | getOperatorRegistry() {
method getCacheKey (line 400) | private getCacheKey(rule: RuleType, criteria: Criteria): string {
method evaluate (line 426) | static async evaluate<T = any>(
method checkIsPassed (line 455) | static async checkIsPassed(
method getEvaluateResult (line 484) | static async getEvaluateResult<T = any>(
method introspect (line 496) | static introspect<R = any>(
method validate (line 507) | static validate(rule: RuleType): ReturnType<Validator["validate"]> {
method builder (line 511) | static builder(): RuleBuilder {
method addMutation (line 516) | static addMutation(field: string, mutation: (value: any) => any): void {
method removeMutation (line 520) | static removeMutation(field: string): void {
method clearMutationCache (line 524) | static clearMutationCache(field?: string): void {
FILE: packages/core/src/services/validator.ts
class Validator (line 18) | class Validator<T = any> {
method validate (line 45) | validate(rule: RuleType<T>): RuleError {
method validateCondition (line 118) | private validateCondition(
method validateConstraint (line 201) | private validateConstraint(constraint: Constraint): RuleError {
method isValidCondition (line 279) | private isValidCondition(obj: any): RuleError {
FILE: packages/core/src/types/introspection.type.ts
type IntrospectionStepChange (line 3) | interface IntrospectionStepChange {
type IntrospectionStep (line 8) | interface IntrospectionStep {
FILE: packages/core/src/types/rule.type.ts
type ConditionType (line 4) | type ConditionType =
type OperatorsType (line 8) | type OperatorsType =
type Constraint (line 137) | interface Constraint {
type EvaluationResult (line 188) | interface EvaluationResult<T = any> {
type EngineResult (line 197) | type EngineResult<T = any> = Omit<EvaluationResult<T>, "isPassed">;
type CriteriaObject (line 198) | type CriteriaObject<T = any> = Record<string, T>;
type Criteria (line 199) | type Criteria<T = any> = CriteriaObject<T> | Array<T>;
type Condition (line 201) | interface Condition<R = any> {
type RuleType (line 228) | interface RuleType<R = any> {
type CriteriaRange (line 234) | interface CriteriaRange<R = any> {
type IntrospectionResult (line 239) | interface IntrospectionResult<R = any> {
FILE: packages/core/src/types/validator.type.ts
type ValidationResult (line 1) | interface ValidationResult {
FILE: packages/core/src/utils/clone.util.ts
function clone (line 1) | function clone<T>(data: T): T {
FILE: packages/core/src/utils/date.util.ts
function getDate (line 1) | function getDate(date = new Date()) {
function dateWithTzOffset (line 5) | function dateWithTzOffset(date?: Date) {
FILE: packages/core/src/utils/error.util.ts
class RuleError (line 3) | class RuleError extends Error {
method constructor (line 4) | constructor(validationResult: ValidationResult) {
method toModel (line 24) | toModel?(): ValidationResult {
class RuleTypeError (line 35) | class RuleTypeError extends Error {
method constructor (line 36) | constructor(message: string) {
FILE: packages/core/src/utils/extract-jsonpath-expressions.util.ts
function extractJsonPathExpressions (line 9) | function extractJsonPathExpressions(text: string): Array<string> {
FILE: packages/core/src/utils/is-object.util.ts
function kindOf (line 1) | function kindOf(inp: any): string {
function isObject (line 5) | function isObject(inp: any) {
FILE: packages/core/src/utils/time.util.ts
function convertTimeToMs (line 1) | function convertTimeToMs(timeString: string) {
function isValidTime (line 15) | function isValidTime(timeString: string) {
FILE: packages/core/test/rule-engine.spec.ts
class PostalCodeOperator (line 101) | class PostalCodeOperator extends BaseOperatorStrategy<string, string> {
method evaluate (line 113) | evaluate(context: OperatorContext): boolean {
method isValidFieldType (line 135) | isValidFieldType(value: unknown): value is string {
method isValidConstraintType (line 139) | isValidConstraintType(value: unknown): value is string {
type UserData (line 264) | interface UserData {
type RuleResult (line 270) | interface RuleResult {
Condensed preview — 237 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,792K chars).
[
{
"path": ".editorconfig",
"chars": 224,
"preview": "root = true\n\n[*]\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\ncharset = utf-8\n\n[*.js]\nin"
},
{
"path": ".gitattributes",
"chars": 66,
"preview": "# Auto detect text files and perform LF normalization\n* text=auto\n"
},
{
"path": ".github/CODE_OF_CONDUCT.md",
"chars": 6593,
"preview": "# Code of Conduct\n\n## Our Pledge\n\nThe **@usex/rule-engine** project is committed to fostering an open, welcoming, and in"
},
{
"path": ".github/workflows/ci.yml",
"chars": 1434,
"preview": "name: ci\n\non:\n pull_request:\n branches:\n - master\n - develop\n push:\n branches:\n - master\n - "
},
{
"path": ".gitignore",
"chars": 113,
"preview": "**/dist\n**/node_modules\n**/coverage\n.vscode\n.DS_Store\n.eslintcache\n*.log*\n**/*.env*\n.husky\n.claude\napps/*/.next/\n"
},
{
"path": ".idea/.gitignore",
"chars": 125,
"preview": "# Default ignored files\n/shelf/\n/workspace.xml\n# Datasource local storage ignored files\n/dataSources/\n/dataSources.local"
},
{
"path": ".idea/compiler.xml",
"chars": 180,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"TypeScriptCompiler\">\n <option name=\"u"
},
{
"path": ".idea/git_toolbox_prj.xml",
"chars": 480,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"GitToolBoxProjectSettings\">\n <option "
},
{
"path": ".idea/inspectionProfiles/Project_Default.xml",
"chars": 251,
"preview": "<component name=\"InspectionProjectProfileManager\">\n <profile version=\"1.0\">\n <option name=\"myName\" value=\"Project De"
},
{
"path": ".idea/jsLinters/eslint.xml",
"chars": 174,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"EslintConfiguration\">\n <option name=\""
},
{
"path": ".idea/modules.xml",
"chars": 260,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"ProjectModuleManager\">\n <modules>\n "
},
{
"path": ".idea/prettier.xml",
"chars": 337,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"PrettierConfiguration\">\n <option name"
},
{
"path": ".idea/usex.iml",
"chars": 600,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"WEB_MODULE\" version=\"4\">\n <component name=\"NewModuleRootManager\">\n"
},
{
"path": ".idea/vcs.xml",
"chars": 167,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"VcsDirectoryMappings\">\n <mapping dire"
},
{
"path": ".npmignore",
"chars": 243,
"preview": "# Ignore everything by default\n*\n\n# Include the dist folder and its contents\n!dist\n!dist/**\n\n# Exclude .tsbuildinfo file"
},
{
"path": ".npmrc",
"chars": 32,
"preview": "strict-peer-dependencies=false\n\n"
},
{
"path": ".nvmrc",
"chars": 7,
"preview": "24.4.1\n"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 3388,
"preview": "# Contributor Covenant Code of Conduct\n\n## Our pledge\n\nIn the interest of fostering an open and welcoming environment, w"
},
{
"path": "CONTRIBUTING.md",
"chars": 5827,
"preview": "# Contributing to @usex/rule-engine\n\nFirst off, thank you for considering contributing to @usex/rule-engine! It's people"
},
{
"path": "LICENCE",
"chars": 1066,
"preview": "MIT License\n\nCopyright (c) 2022 Ali Torki\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
},
{
"path": "README.md",
"chars": 26503,
"preview": "<div align=\"center\">\n <img src=\"./assets/core-logo.png\" alt=\"Rule Engine\" width=\"120\" />\n\n <h1>@usex/rule-engine</h1>\n"
},
{
"path": "assets/BRAND_ASSETS.md",
"chars": 5993,
"preview": "# @usex/rule-engine Brand Assets\n\n> **Official brand assets and usage guidelines for the @usex/rule-engine project**\n\n##"
},
{
"path": "docs/architecture.md",
"chars": 12555,
"preview": "# Architecture Overview\n\nThis document provides a comprehensive overview of the Rule Engine architecture, design decisio"
},
{
"path": "docs/comparison.md",
"chars": 10070,
"preview": "# Rule Engine Comparison\n\nThis document compares @usex/rule-engine with other popular rule engines to help you make an i"
},
{
"path": "docs/getting-started.md",
"chars": 11153,
"preview": "# Getting Started Guide\n\nWelcome to the Rule Engine! This guide will help you get up and running quickly with both the c"
},
{
"path": "eslint.config.js",
"chars": 1861,
"preview": "import antfu from \"@antfu/eslint-config\";\n\nexport default antfu({\n formatters: {\n prettierOptions: {\n printWidt"
},
{
"path": "knip.json",
"chars": 99,
"preview": "{\n \"$schema\": \"https://unpkg.com/knip@5/schema.json\",\n \"project\": [\"./packages/*/src/**/*.ts\"]\n}\n"
},
{
"path": "package.json",
"chars": 1899,
"preview": "{\n \"name\": \"rule-engine-monorepo\",\n \"preview\": true,\n \"type\": \"module\",\n \"packageManager\": \"pnpm@10.17.1\",\n \"descri"
},
{
"path": "packages/builder/.gitignore",
"chars": 263,
"preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndis"
},
{
"path": "packages/builder/CHANGELOG.md",
"chars": 4821,
"preview": "# Changelog\n\nAll notable changes to this project will be documented in this file. See [standard-version](https://github."
},
{
"path": "packages/builder/README.md",
"chars": 18197,
"preview": "<div align=\"center\">\n <img src=\"../../assets/builder-logo.svg\" alt=\"Rule Engine Builder Logo\" width=\"120\" />\n\n <h1>@us"
},
{
"path": "packages/builder/components.json",
"chars": 425,
"preview": "{\n \"$schema\": \"https://ui.shadcn.com/schema.json\",\n \"style\": \"new-york\",\n \"rsc\": false,\n \"tsx\": true,\n \"tailwind\": "
},
{
"path": "packages/builder/docs/README.md",
"chars": 9406,
"preview": "# @usex/rule-engine-builder Documentation\n\nWelcome to the comprehensive documentation for @usex/rule-engine-builder - a "
},
{
"path": "packages/builder/docs/RuleEvaluator.md",
"chars": 3822,
"preview": "# RuleEvaluator Component\n\nThe `RuleEvaluator` component provides a comprehensive interface for testing and evaluating r"
},
{
"path": "packages/builder/docs/components.md",
"chars": 14129,
"preview": "# Component Reference\n\nComprehensive reference for all components in @usex/rule-engine-builder.\n\n## Table of Contents\n\n-"
},
{
"path": "packages/builder/docs/examples.md",
"chars": 37361,
"preview": "# Examples and Use Cases\n\nComprehensive collection of real-world examples using @usex/rule-engine-builder.\n\n## Table of "
},
{
"path": "packages/builder/docs/hooks.md",
"chars": 19254,
"preview": "# Hooks Reference\n\nComprehensive guide to all hooks available in @usex/rule-engine-builder.\n\n## Table of Contents\n\n- [St"
},
{
"path": "packages/builder/docs/integration.md",
"chars": 21219,
"preview": "# Integration Guide\n\nComplete guide for integrating @usex/rule-engine-builder into your applications.\n\n## Table of Conte"
},
{
"path": "packages/builder/index.html",
"chars": 2241,
"preview": "<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\"/>\n <link rel=\"icon\" type=\"image/svg+xml\" href=\"/ico"
},
{
"path": "packages/builder/package.json",
"chars": 4309,
"preview": "{\n \"name\": \"@usex/rule-engine-builder\",\n \"type\": \"module\",\n \"version\": \"0.0.3\",\n \"private\": false,\n \"description\": "
},
{
"path": "packages/builder/src/App.tsx",
"chars": 7265,
"preview": "import { RuleEngine } from \"@usex/rule-engine\";\nimport { TestTube, PlayCircle, AlertCircle } from \"lucide-react\";\nimport"
},
{
"path": "packages/builder/src/components/AdvancedFieldInput.tsx",
"chars": 22452,
"preview": "\"use client\";\n\nimport type { FieldConfig } from \"../types\";\nimport { Command as CommandPrimitive } from \"cmdk\";\nimport {"
},
{
"path": "packages/builder/src/components/AnimatedNumber.tsx",
"chars": 996,
"preview": "import React from \"react\";\nimport NumberFlow, { useCanAnimate } from \"@number-flow/react\";\n\ninterface AnimatedNumberProp"
},
{
"path": "packages/builder/src/components/ConditionGroup.tsx",
"chars": 8480,
"preview": "import React from \"react\";\nimport { CardHeader, CardContent, Card } from \"./ui/card\";\nimport { Button } from \"./ui/butto"
},
{
"path": "packages/builder/src/components/ConstraintEditor.tsx",
"chars": 4164,
"preview": "import React from \"react\";\nimport { CardContent, Card } from \"./ui/card\";\nimport { Button } from \"./ui/button\";\nimport {"
},
{
"path": "packages/builder/src/components/DiffViewer.tsx",
"chars": 21483,
"preview": "import * as Diff from \"diff\";\nimport { motion, AnimatePresence } from \"framer-motion\";\nimport {\n Plus,\n Minus,\n GitBr"
},
{
"path": "packages/builder/src/components/DraggableConditionGroup.tsx",
"chars": 7811,
"preview": "import React from \"react\";\nimport { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nim"
},
{
"path": "packages/builder/src/components/DynamicFieldSelector.tsx",
"chars": 11617,
"preview": "import React, { useState, useMemo } from \"react\";\nimport {\n CommandSeparator,\n CommandList,\n CommandItem,\n CommandIn"
},
{
"path": "packages/builder/src/components/EditableJsonViewer.tsx",
"chars": 15728,
"preview": "import type { RuleType, EvaluationResult } from \"@usex/rule-engine\";\nimport { RuleEngine } from \"@usex/rule-engine\";\nimp"
},
{
"path": "packages/builder/src/components/FieldSelector.tsx",
"chars": 4421,
"preview": "import React from \"react\";\nimport {\n SelectValue,\n SelectTrigger,\n SelectLabel,\n SelectItem,\n SelectGroup,\n Select"
},
{
"path": "packages/builder/src/components/HistoryViewer.tsx",
"chars": 25719,
"preview": "import type { HistoryEntry } from \"../stores/unified-rule-store\";\nimport { formatDistanceToNow, format } from \"date-fns\""
},
{
"path": "packages/builder/src/components/ImportExport.tsx",
"chars": 2167,
"preview": "import React from \"react\";\nimport { Button } from \"./ui/button\";\nimport { Upload, Download } from \"lucide-react\";\nimport"
},
{
"path": "packages/builder/src/components/JsonViewer.tsx",
"chars": 4990,
"preview": "import React, { useMemo } from \"react\";\nimport { CardTitle, CardHeader, CardContent, Card } from \"./ui/card\";\nimport { B"
},
{
"path": "packages/builder/src/components/JsonVisualizer.tsx",
"chars": 8167,
"preview": "\"use client\";\n\nimport * as React from \"react\";\nimport {\n MoreHorizontal,\n Copy,\n ChevronUp,\n ChevronRight,\n Chevron"
},
{
"path": "packages/builder/src/components/ModernConstraintEditor.tsx",
"chars": 8014,
"preview": "import React from \"react\";\nimport { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nim"
},
{
"path": "packages/builder/src/components/ModernRuleBuilder.tsx",
"chars": 25682,
"preview": "import React from \"react\";\nimport {\n useSensors,\n useSensor,\n PointerSensor,\n DragOverlay,\n DndContext,\n closestCe"
},
{
"path": "packages/builder/src/components/OperatorSelector.tsx",
"chars": 6482,
"preview": "import type { OperatorsType } from \"@usex/rule-engine\";\nimport type { OperatorSelectorProps } from \"../types\";\nimport { "
},
{
"path": "packages/builder/src/components/RegexValidator.tsx",
"chars": 12328,
"preview": "import { Regex, Info, Copy, CheckCircle2, AlertCircle } from \"lucide-react\";\nimport React, { useState, useMemo, useEffec"
},
{
"path": "packages/builder/src/components/ResizablePanel.tsx",
"chars": 4308,
"preview": "import React, { useState, useRef, useEffect, useCallback } from \"react\";\nimport { cn } from \"../lib/utils\";\n\ninterface R"
},
{
"path": "packages/builder/src/components/RuleImportModal.tsx",
"chars": 9092,
"preview": "import React, { useState, useRef } from \"react\";\nimport { Button } from \"./ui/button\";\nimport { Label } from \"./ui/label"
},
{
"path": "packages/builder/src/components/RuleImporter.tsx",
"chars": 7983,
"preview": "import React, { useState, useRef } from \"react\";\nimport { Button } from \"./ui/button\";\nimport { Label } from \"./ui/label"
},
{
"path": "packages/builder/src/components/RuleViewer.tsx",
"chars": 2627,
"preview": "import React from \"react\";\nimport { CardTitle, CardHeader, CardContent, Card } from \"./ui/card\";\nimport { Button } from "
},
{
"path": "packages/builder/src/components/SmartOperatorSelector.tsx",
"chars": 18115,
"preview": "import type { OperatorsType } from \"@usex/rule-engine\";\nimport type { OperatorSelectorProps } from \"../types\";\nimport { "
},
{
"path": "packages/builder/src/components/ThemeToggle.tsx",
"chars": 1395,
"preview": "import React from \"react\";\nimport { Sun, Moon, Monitor } from \"lucide-react\";\nimport { Button } from \"./ui/button\";\nimpo"
},
{
"path": "packages/builder/src/components/TreeConditionGroup.tsx",
"chars": 12825,
"preview": "import type { Constraint, ConditionType, Condition } from \"@usex/rule-engine\";\nimport type { FieldConfig } from \"../type"
},
{
"path": "packages/builder/src/components/TreeConstraintEditor.tsx",
"chars": 17954,
"preview": "import type { Constraint } from \"@usex/rule-engine\";\nimport type { FieldConfig } from \"../types\";\nimport { Operators } f"
},
{
"path": "packages/builder/src/components/TreeRuleBuilder.tsx",
"chars": 25550,
"preview": "import type { Condition } from \"@usex/rule-engine\";\nimport type { FieldConfig } from \"../types\";\nimport { RuleEngine } f"
},
{
"path": "packages/builder/src/components/UndoRedoInfo.tsx",
"chars": 3998,
"preview": "import React from \"react\";\nimport { RotateCw, RotateCcw, Clock } from \"lucide-react\";\nimport { Button } from \"./ui/butto"
},
{
"path": "packages/builder/src/components/ValueInput.tsx",
"chars": 3339,
"preview": "import React from \"react\";\nimport { Input } from \"./ui/input\";\nimport { Button } from \"./ui/button\";\nimport { X, Plus } "
},
{
"path": "packages/builder/src/components/VisualFieldSelector.tsx",
"chars": 19676,
"preview": "import type { FieldConfig } from \"../types\";\nimport {\n Type,\n ToggleRight,\n Search,\n List,\n Layers,\n Hash,\n GripV"
},
{
"path": "packages/builder/src/components/condition-group.tsx",
"chars": 8801,
"preview": "import React from \"react\";\nimport { CardHeader, CardContent, Card } from \"./ui/card\";\nimport { Button } from \"./ui/butto"
},
{
"path": "packages/builder/src/components/editable-json-viewer.tsx",
"chars": 15728,
"preview": "import type { RuleType, EvaluationResult } from \"@usex/rule-engine\";\nimport { RuleEngine } from \"@usex/rule-engine\";\nimp"
},
{
"path": "packages/builder/src/components/history-viewer.tsx",
"chars": 25719,
"preview": "import type { HistoryEntry } from \"../stores/unified-rule-store\";\nimport { formatDistanceToNow, format } from \"date-fns\""
},
{
"path": "packages/builder/src/components/inputs/AnimatedNumberInput.tsx",
"chars": 4875,
"preview": "import React, { useState, useRef } from \"react\";\nimport NumberFlow, { useCanAnimate } from \"@number-flow/react\";\nimport "
},
{
"path": "packages/builder/src/components/inputs/ArrayInput.tsx",
"chars": 2784,
"preview": "import React from \"react\";\nimport { Button } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport { Badge } "
},
{
"path": "packages/builder/src/components/inputs/BooleanInput.tsx",
"chars": 682,
"preview": "import React from \"react\";\nimport { Switch } from \"../ui/switch\";\nimport { Label } from \"../ui/label\";\nimport { cn } fro"
},
{
"path": "packages/builder/src/components/inputs/DateInput.tsx",
"chars": 1841,
"preview": "import React from \"react\";\nimport { format } from \"date-fns\";\nimport { Calendar as CalendarIcon } from \"lucide-react\";\ni"
},
{
"path": "packages/builder/src/components/inputs/NumberInput.tsx",
"chars": 1723,
"preview": "import React from \"react\";\nimport { Input } from \"../ui/input\";\nimport { Slider } from \"../ui/slider\";\nimport { cn } fro"
},
{
"path": "packages/builder/src/components/inputs/SmartValueInput.tsx",
"chars": 7541,
"preview": "import React from \"react\";\nimport { Input } from \"../ui/input\";\nimport { DateInput } from \"./DateInput\";\nimport { Animat"
},
{
"path": "packages/builder/src/components/operators/ArrayOperatorHandler.tsx",
"chars": 5958,
"preview": "import React from \"react\";\nimport { Input } from \"../ui/input\";\nimport { Button } from \"../ui/button\";\nimport { Label } "
},
{
"path": "packages/builder/src/components/operators/BooleanValidationHandler.tsx",
"chars": 9072,
"preview": "import React from \"react\";\nimport { Label } from \"../ui/label\";\nimport { Badge } from \"../ui/badge\";\nimport { Switch } f"
},
{
"path": "packages/builder/src/components/operators/ComparisonOperatorHandler.tsx",
"chars": 9976,
"preview": "import type { OperatorHandlerProps } from \"./index\";\nimport { Sparkles, Info, Hash } from \"lucide-react\";\nimport React f"
},
{
"path": "packages/builder/src/components/operators/DateOperatorHandler.tsx",
"chars": 9984,
"preview": "import React from \"react\";\nimport { Input } from \"../ui/input\";\nimport { Button } from \"../ui/button\";\nimport { Label } "
},
{
"path": "packages/builder/src/components/operators/ExistenceOperatorHandler.tsx",
"chars": 5459,
"preview": "import React from \"react\";\nimport { Label } from \"../ui/label\";\nimport { Badge } from \"../ui/badge\";\nimport { XCircle, I"
},
{
"path": "packages/builder/src/components/operators/LengthValidationHandler.tsx",
"chars": 12482,
"preview": "import React from \"react\";\nimport { Input } from \"../ui/input\";\nimport { Label } from \"../ui/label\";\nimport { Badge } fr"
},
{
"path": "packages/builder/src/components/operators/NumberValidationHandler.tsx",
"chars": 11480,
"preview": "import React from \"react\";\nimport { Input } from \"../ui/input\";\nimport { Label } from \"../ui/label\";\nimport { Badge } fr"
},
{
"path": "packages/builder/src/components/operators/SelfReferenceHandler.tsx",
"chars": 3485,
"preview": "import React from \"react\";\nimport { DynamicFieldSelector } from \"../DynamicFieldSelector\";\nimport { Badge } from \"../ui/"
},
{
"path": "packages/builder/src/components/operators/StringValidationHandler.tsx",
"chars": 9886,
"preview": "import React from \"react\";\nimport { Input } from \"../ui/input\";\nimport { Button } from \"../ui/button\";\nimport { Label } "
},
{
"path": "packages/builder/src/components/operators/TypeValidationHandler.tsx",
"chars": 8205,
"preview": "import React from \"react\";\nimport { Label } from \"../ui/label\";\nimport { Badge } from \"../ui/badge\";\nimport {\n Type,\n "
},
{
"path": "packages/builder/src/components/operators/index.tsx",
"chars": 5097,
"preview": "import React from \"react\";\nimport { Operators } from \"@usex/rule-engine\";\nimport type { OperatorsType } from \"@usex/rule"
},
{
"path": "packages/builder/src/components/resizable-panel.tsx",
"chars": 4308,
"preview": "import React, { useState, useRef, useEffect, useCallback } from \"react\";\nimport { cn } from \"../lib/utils\";\n\ninterface R"
},
{
"path": "packages/builder/src/components/rule-builder.tsx",
"chars": 11410,
"preview": "import React, { useState, useEffect, useCallback } from \"react\";\nimport { RuleEditor } from \"./rule-editor\";\nimport { Ru"
},
{
"path": "packages/builder/src/components/rule-editor.tsx",
"chars": 11835,
"preview": "import React, { useState, useCallback } from \"react\";\nimport { CardContent, Card } from \"./ui/card\";\nimport { Button } f"
},
{
"path": "packages/builder/src/components/rule-evaluator.tsx",
"chars": 30399,
"preview": "import type {\n EvaluationResult,\n Constraint,\n Condition,\n} from \"@usex/rule-engine\";\nimport { RuleEngine } from \"@us"
},
{
"path": "packages/builder/src/components/rule-import-modal.tsx",
"chars": 9092,
"preview": "import React, { useState, useRef } from \"react\";\nimport { Button } from \"./ui/button\";\nimport { Label } from \"./ui/label"
},
{
"path": "packages/builder/src/components/rule-viewer.tsx",
"chars": 2627,
"preview": "import React from \"react\";\nimport { CardTitle, CardHeader, CardContent, Card } from \"./ui/card\";\nimport { Button } from "
},
{
"path": "packages/builder/src/components/theme-provider.tsx",
"chars": 1590,
"preview": "import React, { useState, useEffect, use, createContext } from \"react\";\n\ntype Theme = \"dark\" | \"light\" | \"system\";\n\ninte"
},
{
"path": "packages/builder/src/components/theme-toggle.tsx",
"chars": 1180,
"preview": "import { Sun, Moon } from \"lucide-react\";\nimport { useTheme } from \"./theme-provider\";\nimport { Button } from \"./ui/butt"
},
{
"path": "packages/builder/src/components/ui/alert.tsx",
"chars": 1682,
"preview": "import * as React from \"react\";\nimport { cva } from \"class-variance-authority\";\nimport type { VariantProps } from \"class"
},
{
"path": "packages/builder/src/components/ui/badge.tsx",
"chars": 1473,
"preview": "import * as React from \"react\";\nimport { cva } from \"class-variance-authority\";\nimport type { VariantProps } from \"class"
},
{
"path": "packages/builder/src/components/ui/button.tsx",
"chars": 1967,
"preview": "import * as React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva } from \"class-variance-authori"
},
{
"path": "packages/builder/src/components/ui/calendar.tsx",
"chars": 2417,
"preview": "import * as React from \"react\";\nimport { DayPicker } from \"react-day-picker\";\nimport { cn } from \"../../lib/utils\";\n\nimp"
},
{
"path": "packages/builder/src/components/ui/card.tsx",
"chars": 1928,
"preview": "import * as React from \"react\";\n\nimport { cn } from \"../../lib/utils\";\n\nconst Card = ({\n className,\n ref,\n ...props\n}"
},
{
"path": "packages/builder/src/components/ui/collapsible.tsx",
"chars": 320,
"preview": "import * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\";\n\nconst Collapsible = CollapsiblePrimitive.Root;\n\nco"
},
{
"path": "packages/builder/src/components/ui/command.tsx",
"chars": 5057,
"preview": "import * as React from \"react\";\nimport type { DialogProps } from \"@radix-ui/react-dialog\";\nimport { Command as CommandPr"
},
{
"path": "packages/builder/src/components/ui/dialog.tsx",
"chars": 3967,
"preview": "import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { X } from \"lucide-react\";\nimport * as React from \"rea"
},
{
"path": "packages/builder/src/components/ui/dropdown-menu.tsx",
"chars": 7691,
"preview": "import * as React from \"react\";\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport { Circle,"
},
{
"path": "packages/builder/src/components/ui/input.tsx",
"chars": 802,
"preview": "import * as React from \"react\";\n\nimport { cn } from \"../../lib/utils\";\n\nconst Input = ({\n ref,\n className,\n type,\n ."
},
{
"path": "packages/builder/src/components/ui/label.tsx",
"chars": 788,
"preview": "import * as React from \"react\";\nimport * as LabelPrimitive from \"@radix-ui/react-label\";\nimport { cva } from \"class-vari"
},
{
"path": "packages/builder/src/components/ui/popover.tsx",
"chars": 1275,
"preview": "import * as React from \"react\";\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\n\nimport { cn } from \"../../"
},
{
"path": "packages/builder/src/components/ui/scroll-area.tsx",
"chars": 1716,
"preview": "import * as React from \"react\";\nimport * as ScrollAreaPrimitive from \"@radix-ui/react-scroll-area\";\nimport { cn } from \""
},
{
"path": "packages/builder/src/components/ui/select.tsx",
"chars": 5835,
"preview": "import * as React from \"react\";\nimport * as SelectPrimitive from \"@radix-ui/react-select\";\nimport { ChevronUp, ChevronDo"
},
{
"path": "packages/builder/src/components/ui/separator.tsx",
"chars": 759,
"preview": "import * as React from \"react\";\nimport * as SeparatorPrimitive from \"@radix-ui/react-separator\";\n\nimport { cn } from \".."
},
{
"path": "packages/builder/src/components/ui/sheet.tsx",
"chars": 4433,
"preview": "import * as React from \"react\";\nimport * as SheetPrimitive from \"@radix-ui/react-dialog\";\nimport { cva } from \"class-var"
},
{
"path": "packages/builder/src/components/ui/slider.tsx",
"chars": 1108,
"preview": "import * as React from \"react\";\nimport * as SliderPrimitive from \"@radix-ui/react-slider\";\n\nimport { cn } from \"../../li"
},
{
"path": "packages/builder/src/components/ui/sonner.tsx",
"chars": 902,
"preview": "import { useTheme } from \"../../hooks/use-theme\";\nimport { Toaster as Sonner } from \"sonner\";\n\ntype ToasterProps = React"
},
{
"path": "packages/builder/src/components/ui/switch.tsx",
"chars": 1171,
"preview": "import * as React from \"react\";\nimport * as SwitchPrimitives from \"@radix-ui/react-switch\";\n\nimport { cn } from \"../../l"
},
{
"path": "packages/builder/src/components/ui/tabs.tsx",
"chars": 1961,
"preview": "import * as React from \"react\";\nimport * as TabsPrimitive from \"@radix-ui/react-tabs\";\n\nimport { cn } from \"../../lib/ut"
},
{
"path": "packages/builder/src/components/ui/textarea.tsx",
"chars": 780,
"preview": "import * as React from \"react\";\n\nimport { cn } from \"../../lib/utils\";\n\nexport interface TextareaProps\n extends React.T"
},
{
"path": "packages/builder/src/components/ui/tooltip.tsx",
"chars": 1189,
"preview": "import * as React from \"react\";\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\n\nimport { cn } from \"../../"
},
{
"path": "packages/builder/src/components/ui/zoom-dialog.tsx",
"chars": 3926,
"preview": "import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { X } from \"lucide-react\";\nimport * as React from \"rea"
},
{
"path": "packages/builder/src/constants/operator-help.ts",
"chars": 11687,
"preview": "export interface OperatorHelp {\n name: string;\n description: string;\n examples: Array<{\n field: string;\n operat"
},
{
"path": "packages/builder/src/data/sample-data.ts",
"chars": 8064,
"preview": "// Comprehensive sample data for showcasing the rule builder\nimport type { FieldConfig } from \"../types\";\n\nexport const "
},
{
"path": "packages/builder/src/debug-test.tsx",
"chars": 11406,
"preview": "import React from \"react\";\nimport { useRuleBuilder } from \"./stores/unified-rule-store\";\nimport { ConditionTypes } from "
},
{
"path": "packages/builder/src/demo.tsx",
"chars": 37388,
"preview": "import { useState, useEffect, StrictMode } from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport { RuleBui"
},
{
"path": "packages/builder/src/hooks/use-field-discovery.ts",
"chars": 7808,
"preview": "import { useState, useEffect, useCallback } from \"react\";\nimport type { FieldConfig } from \"../types\";\n\ninterface UseFie"
},
{
"path": "packages/builder/src/hooks/use-keyboard-shortcuts.ts",
"chars": 1855,
"preview": "import { useEffect, useCallback } from \"react\";\n\ninterface ShortcutConfig {\n key: string;\n ctrl?: boolean;\n cmd?: boo"
},
{
"path": "packages/builder/src/hooks/use-theme.ts",
"chars": 1500,
"preview": "import { useState, useEffect } from \"react\";\n\ntype Theme = \"light\" | \"dark\" | \"system\";\n\nexport function useTheme() {\n "
},
{
"path": "packages/builder/src/index.ts",
"chars": 2464,
"preview": "// Import styles\nimport \"./styles/globals.css\";\n\n// Sub-components (for advanced usage)\nexport { DiffViewer } from \"./co"
},
{
"path": "packages/builder/src/lib/utils.ts",
"chars": 192,
"preview": "import { clsx } from \"clsx\";\nimport type { ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport f"
},
{
"path": "packages/builder/src/main.tsx",
"chars": 213,
"preview": "import { StrictMode } from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport { App } from \"./App\";\n\ncreateR"
},
{
"path": "packages/builder/src/stores/enhanced-rule-store.ts",
"chars": 6360,
"preview": "import { create } from \"zustand\";\nimport { devtools } from \"zustand/middleware\";\nimport type { RuleType, EngineResult, C"
},
{
"path": "packages/builder/src/stores/rule-store.ts",
"chars": 2318,
"preview": "import { create } from \"zustand\";\nimport type { RuleType, EngineResult, Condition } from \"@usex/rule-engine\";\n\ninterface"
},
{
"path": "packages/builder/src/stores/unified-rule-store.ts",
"chars": 18005,
"preview": "import React from \"react\";\nimport { create } from \"zustand\";\nimport { devtools } from \"zustand/middleware\";\nimport type "
},
{
"path": "packages/builder/src/styles/animations.css",
"chars": 1656,
"preview": "/* Custom animations for the demo page */\n\n@keyframes float {\n 0%, 100% {\n transform: translateY(0px) translateX(0px"
},
{
"path": "packages/builder/src/styles/globals.css",
"chars": 11391,
"preview": "@import \"tailwindcss\";\n\n@custom-variant dark (&:is(.dark *));\n\n@theme inline {\n --color-background: hsl(var(--backgroun"
},
{
"path": "packages/builder/src/test-demo.tsx",
"chars": 1141,
"preview": "import { StrictMode } from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport { RuleBuilder } from \"./compon"
},
{
"path": "packages/builder/src/test-store-debug.tsx",
"chars": 3004,
"preview": "import { useUnifiedRuleStore } from \"./stores/unified-rule-store\";\nimport { ConditionTypes } from \"@usex/rule-engine\";\ni"
},
{
"path": "packages/builder/src/types/index.ts",
"chars": 4282,
"preview": "import type {\n RuleType,\n OperatorsType,\n EngineResult,\n Constraint,\n ConditionType,\n Condition,\n} from \"@usex/rul"
},
{
"path": "packages/builder/src/utils/json-path.ts",
"chars": 6312,
"preview": "/**\n * Utilities for working with JSON Path expressions\n */\n\ninterface PathSegment {\n type: \"property\" | \"index\" | \"wil"
},
{
"path": "packages/builder/src/utils/operators.ts",
"chars": 9244,
"preview": "import { Operators } from \"@usex/rule-engine\";\nimport type { OperatorsType } from \"@usex/rule-engine\";\nimport type { Ope"
},
{
"path": "packages/builder/src/vite-env.d.ts",
"chars": 38,
"preview": "/// <reference types=\"vite/client\" />\n"
},
{
"path": "packages/builder/tsconfig.app.json",
"chars": 702,
"preview": "{\n \"compilerOptions\": {\n \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.app.tsbuildinfo\",\n \"target\": \"ES2020\",\n"
},
{
"path": "packages/builder/tsconfig.json",
"chars": 213,
"preview": "{\n \"compilerOptions\": {\n \"baseUrl\": \".\",\n \"paths\": {\n \"@/*\": [\"./src/*\"]\n }\n },\n \"references\": [\n { "
},
{
"path": "packages/builder/tsconfig.node.json",
"chars": 630,
"preview": "{\n \"compilerOptions\": {\n \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.node.tsbuildinfo\",\n \"target\": \"ES2022\","
},
{
"path": "packages/builder/vercel.json",
"chars": 131,
"preview": "{\n \"installCommand\": \"pnpm install --frozen-lockfile\",\n \"buildCommand\": \"pnpm run build:demo\",\n \"outputDirectory\": \"d"
},
{
"path": "packages/builder/vite.config.ts",
"chars": 1670,
"preview": "import { defineConfig } from \"vite\";\nimport tailwindcss from \"@tailwindcss/vite\";\nimport react from \"@vitejs/plugin-reac"
},
{
"path": "packages/core/CHANGELOG.md",
"chars": 4821,
"preview": "# Changelog\n\nAll notable changes to this project will be documented in this file. See [standard-version](https://github."
},
{
"path": "packages/core/README.md",
"chars": 23527,
"preview": "<div align=\"center\">\n <img src=\"../../assets/core-logo.svg\" alt=\"Rule Engine Core Logo\" width=\"120\" />\n\n <h1>@usex/rul"
},
{
"path": "packages/core/benchmarks/builder.bench.ts",
"chars": 2161,
"preview": "import { expect, describe, bench } from \"vitest\";\nimport { RuleEngine, Operators, ConditionTypes } from \"@root\";\n\ndescri"
},
{
"path": "packages/core/benchmarks/engine.bench.ts",
"chars": 7293,
"preview": "import { describe, bench } from \"vitest\";\nimport type { OperatorsType } from \"@root\";\nimport { RuleEngine, Operators } f"
},
{
"path": "packages/core/benchmarks/introspector.bench.ts",
"chars": 551,
"preview": "import { describe, bench } from \"vitest\";\nimport { RuleEngine } from \"@root\";\n// Assets\nimport { valid2Json } from \"../t"
},
{
"path": "packages/core/benchmarks/json-path.bench.ts",
"chars": 2377,
"preview": "import { describe, bench } from \"vitest\";\nimport { RuleEngine, ObjectDiscovery } from \"@root\";\n// Rules\nimport { selfFie"
},
{
"path": "packages/core/benchmarks/mutator.bench.ts",
"chars": 2635,
"preview": "// Utilities\nimport { describe, bench } from \"vitest\";\nimport { RuleEngine, Operators } from \"@root\";\n// Assets\nimport {"
},
{
"path": "packages/core/benchmarks/validator.bench.ts",
"chars": 1107,
"preview": "import { describe, bench } from \"vitest\";\nimport { RuleEngine, Operators } from \"@root\";\n// Assets\nimport { valid1Json }"
},
{
"path": "packages/core/docs/README.md",
"chars": 3743,
"preview": "# Documentation Structure\n\nThis directory contains comprehensive documentation for @usex/rule-engine.\n\n## 📚 Documentatio"
},
{
"path": "packages/core/docs/api-reference-v2.md",
"chars": 9902,
"preview": "# API Reference v2.1\n\nComplete API reference for @usex/rule-engine v2.1 with enhanced TypeScript support.\n\n## Table of C"
},
{
"path": "packages/core/docs/api-reference.md",
"chars": 10779,
"preview": "# API Reference\n\nComplete API documentation for @usex/rule-engine.\n\n## Table of Contents\n\n- [RuleEngine Class](#ruleengi"
},
{
"path": "packages/core/docs/best-practices.md",
"chars": 13166,
"preview": "# Best Practices Guide\n\nThis guide covers best practices for using @usex/rule-engine effectively in production environme"
},
{
"path": "packages/core/docs/index.md",
"chars": 4600,
"preview": "# @usex/rule-engine Documentation\n\nWelcome to the comprehensive documentation for @usex/rule-engine - a simple yet power"
},
{
"path": "packages/core/docs/migration-guide.md",
"chars": 12174,
"preview": "# Migration Guide\n\nThis guide helps you migrate from other rule engines to @usex/rule-engine.\n\n## Table of Contents\n\n- ["
},
{
"path": "packages/core/docs/operators.md",
"chars": 15715,
"preview": "# Complete Operator Reference\n\nThis document provides a comprehensive reference for all 126 operators available in @usex"
},
{
"path": "packages/core/docs/refactoring-summary.md",
"chars": 4890,
"preview": "# Rule Engine v2.1 Refactoring Summary\n\nThis document summarizes all the changes made during the TypeScript improvements"
},
{
"path": "packages/core/docs/typescript-guide.md",
"chars": 9613,
"preview": "# TypeScript Guide for @usex/rule-engine\n\nThis guide covers the enhanced TypeScript features in @usex/rule-engine v2.1, "
},
{
"path": "packages/core/docs/v2-migration-guide.md",
"chars": 13065,
"preview": "# Migration Guide: Upgrading to RuleEngine V2\n\nThis guide will help you migrate from the original RuleEngine to the new "
},
{
"path": "packages/core/package.json",
"chars": 3055,
"preview": "{\n \"name\": \"@usex/rule-engine\",\n \"type\": \"module\",\n \"version\": \"0.0.2\",\n \"packageManager\": \"pnpm@10.17.1\",\n \"descri"
},
{
"path": "packages/core/src/enums/condition-types.enum.ts",
"chars": 488,
"preview": "// Purpose: Enumerates the types of logical operators that can be used to combine multiple criteria.\nexport enum Conditi"
},
{
"path": "packages/core/src/enums/index.ts",
"chars": 74,
"preview": "export * from \"./condition-types.enum\";\nexport * from \"./operators.enum\";\n"
},
{
"path": "packages/core/src/enums/operators.enum.ts",
"chars": 33437,
"preview": "export enum Operators {\n // Comparison Operators on Strings\n Equals = \"equals\", // Check if the field value is equal t"
},
{
"path": "packages/core/src/examples/custom-operator.example.ts",
"chars": 10032,
"preview": "/**\n * Example: Creating custom operators\n */\n\nimport { OperatorCategory, BaseOperatorStrategy } from \"@root/operators/b"
},
{
"path": "packages/core/src/index.ts",
"chars": 2135,
"preview": "// Enums\nexport * from \"@root/enums\";\n// Explicit re-export for better TypeScript support\nexport { ConditionTypes, Opera"
},
{
"path": "packages/core/src/operators/base.ts",
"chars": 5515,
"preview": "import type { OperatorsType } from \"@root/types\";\n\n/**\n * Type representing the expected field types for operators\n */\ne"
},
{
"path": "packages/core/src/operators/factory.ts",
"chars": 7556,
"preview": "import { operatorRegistry } from \"./registry\";\nimport type { OperatorFactory, OperatorConstructor } from \"./base\";\n\n// I"
},
{
"path": "packages/core/src/operators/implementations/array.ts",
"chars": 14222,
"preview": "import { Operators } from \"@root/enums\";\nimport { OperatorCategory, BaseOperatorStrategy } from \"../base\";\nimport type {"
},
{
"path": "packages/core/src/operators/implementations/boolean.ts",
"chars": 9217,
"preview": "import { Operators } from \"@root/enums\";\nimport { OperatorCategory, BaseOperatorStrategy } from \"../base\";\nimport type {"
},
{
"path": "packages/core/src/operators/implementations/comparison.ts",
"chars": 11746,
"preview": "import { isObject } from \"@root/utils\";\nimport { Operators } from \"@root/enums\";\nimport { OperatorCategory, BaseOperator"
},
{
"path": "packages/core/src/operators/implementations/date-time.ts",
"chars": 24933,
"preview": "import { Operators } from \"@root/enums\";\nimport { OperatorCategory, BaseOperatorStrategy } from \"../base\";\nimport type {"
},
{
"path": "packages/core/src/operators/implementations/existence.ts",
"chars": 6574,
"preview": "import { Operators } from \"@root/enums\";\nimport { OperatorCategory, BaseOperatorStrategy } from \"../base\";\nimport type {"
},
{
"path": "packages/core/src/operators/implementations/index.ts",
"chars": 268,
"preview": "export * from \"./array\";\nexport * from \"./boolean\";\n// Comparison operators\nexport * from \"./comparison\";\nexport * from "
},
{
"path": "packages/core/src/operators/implementations/numeric.ts",
"chars": 14825,
"preview": "import { Operators } from \"@root/enums\";\nimport { OperatorCategory, BaseOperatorStrategy } from \"../base\";\nimport type {"
},
{
"path": "packages/core/src/operators/implementations/pattern.ts",
"chars": 15324,
"preview": "import { Operators } from \"@root/enums\";\nimport { OperatorCategory, BaseOperatorStrategy } from \"../base\";\nimport type {"
},
{
"path": "packages/core/src/operators/implementations/string.ts",
"chars": 16501,
"preview": "import { Operators } from \"@root/enums\";\nimport { OperatorCategory, BaseOperatorStrategy } from \"../base\";\nimport type {"
},
{
"path": "packages/core/src/operators/implementations/type.ts",
"chars": 4062,
"preview": "import { Operators } from \"@root/enums\";\nimport { OperatorCategory, BaseOperatorStrategy } from \"../base\";\nimport type {"
},
{
"path": "packages/core/src/operators/index.ts",
"chars": 20493,
"preview": "import {\n isValidTime,\n isObject,\n dateWithTzOffset,\n convertTimeToMs,\n} from \"@root/utils\";\nimport { isBefore, isAf"
},
{
"path": "packages/core/src/operators/like.md",
"chars": 7865,
"preview": "# Like Operator\nIt provides a safe and expressive way to parse and evaluate SQL WHERE LIKE filter expressions with wildc"
},
{
"path": "packages/core/src/operators/registry.ts",
"chars": 7658,
"preview": "import { Operators } from \"@root/enums\";\nimport type { OperatorsType } from \"@root/types\";\nimport type {\n OperatorStrat"
},
{
"path": "packages/core/src/services/builder.ts",
"chars": 2330,
"preview": "import type { Validator } from \"@root/services/validator\";\n// Types\nimport type {\n RuleType,\n OperatorsType,\n Constra"
},
{
"path": "packages/core/src/services/evaluator.ts",
"chars": 12650,
"preview": "import { ObjectDiscovery } from \"@root/services/object-discovery\";\nimport { operatorRegistry } from \"@root/operators/reg"
},
{
"path": "packages/core/src/services/index.ts",
"chars": 208,
"preview": "export * from \"./builder\";\nexport * from \"./evaluator\";\nexport * from \"./introspector\";\nexport * from \"./logger\";\nexport"
},
{
"path": "packages/core/src/services/introspector.ts",
"chars": 22175,
"preview": "import { RuleTypeError, clone } from \"@root/utils\";\nimport { Logger } from \"@root/services/logger\";\nimport { ObjectDisco"
},
{
"path": "packages/core/src/services/logger.ts",
"chars": 131,
"preview": "export class Logger {\n static debug(...opts: any[]): void {\n if (!process.env.DEBUG) return;\n console.debug(...op"
},
{
"path": "packages/core/src/services/mutator.ts",
"chars": 9396,
"preview": "// Utilities\nimport { clone } from \"@root/utils\";\nimport { createHash } from \"node:crypto\";\nimport { EventEmitter } from"
},
{
"path": "packages/core/src/services/object-discovery.ts",
"chars": 6087,
"preview": "// Utilities\nimport { isEmpty } from \"ramda\";\nimport { JSONPath } from \"jsonpath-plus\";\nimport { isObject, extractJsonPa"
},
{
"path": "packages/core/src/services/rule-engine.ts",
"chars": 13343,
"preview": "import { Validator } from \"@root/services/validator\";\nimport { Evaluator } from \"@root/services/evaluator\";\nimport { Mut"
},
{
"path": "packages/core/src/services/validator.ts",
"chars": 11050,
"preview": "import { isEmpty } from \"ramda\";\nimport { RuleError, isObject } from \"@root/utils\";\nimport { isStringOperator } from \"@r"
},
{
"path": "packages/core/src/types/index.ts",
"chars": 101,
"preview": "export * from \"./introspection.type\";\nexport * from \"./rule.type\";\nexport * from \"./validator.type\";\n"
},
{
"path": "packages/core/src/types/introspection.type.ts",
"chars": 322,
"preview": "import type { ConditionType } from \"@root/types\";\n\nexport interface IntrospectionStepChange {\n key: string;\n value: un"
},
{
"path": "packages/core/src/types/rule.type.ts",
"chars": 7343,
"preview": "// Enums\nimport type { Operators, ConditionTypes } from \"@root/enums\";\n\nexport type ConditionType =\n | ConditionTypes.O"
},
{
"path": "packages/core/src/types/validator.type.ts",
"chars": 117,
"preview": "export interface ValidationResult {\n isValid: boolean;\n error?: {\n message: string;\n element: object;\n };\n}\n"
},
{
"path": "packages/core/src/utils/clone.util.ts",
"chars": 73,
"preview": "export function clone<T>(data: T): T {\n return structuredClone(data);\n}\n"
}
]
// ... and 37 more files (download for full content)
About this extraction
This page contains the full source code of the ali-master/rule-engine GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 237 files (1.6 MB), approximately 398.8k tokens, and a symbol index with 753 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.