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 ================================================ ================================================ FILE: .idea/git_toolbox_prj.xml ================================================ ================================================ FILE: .idea/inspectionProfiles/Project_Default.xml ================================================ ================================================ FILE: .idea/jsLinters/eslint.xml ================================================ ================================================ FILE: .idea/modules.xml ================================================ ================================================ FILE: .idea/prettier.xml ================================================ ================================================ FILE: .idea/usex.iml ================================================ ================================================ FILE: .idea/vcs.xml ================================================ ================================================ 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( rule: RuleType, data: unknown ): Promise> { // 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 ``` (): 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 ================================================
Rule Engine

@usex/rule-engine

🎯 The Ultimate JSON-Based Rule Engine for Modern Applications

npm version license codecov downloads stars bundle size

Quick StartPackagesExamplesDocumentationWhy This?

Open Source Rule Engine - A JSON rule engine for declarative business logic. | Product Hunt
--- **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)**
[![npm](https://img.shields.io/npm/v/@usex/rule-engine.svg?style=flat-square)](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)**
[![npm](https://img.shields.io/npm/v/@usex/rule-engine-builder.svg?style=flat-square)](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 = { 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(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 = { 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( 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 (

Build Your Business Rules Visually

{rule && ( )}
); } ``` ## 💡 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 = { 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( 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 { name: string; category: string; evaluate(fieldValue: T, operatorValue: V): boolean; } // ✅ Type-safe custom operator implementation class DateRangeOperator implements CustomOperator { 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(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 Star History Chart ---
**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.**
================================================ 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; // Cache for performance private cache: Map; // Core methods async evaluate(rule: RuleType, criteria: any): Promise>; validate(rule: RuleType): ValidationResult; introspect(rule: RuleType): IntrospectionResult; // Static API static evaluate(...args): Promise>; 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 | `(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; 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; 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( rule: RuleType, items: any[], concurrency: number = 10 ): Promise[]> { 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; mutations?: Record; validators?: Record; } class PluginManager { private plugins: Map = 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 (
{rule && (

Generated Rule:

{JSON.stringify(rule, null, 2)}
)}
); } ``` ### 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' } ]; ``` ### 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'] } }; ``` ## 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 ================================================
Rule Engine Builder Logo

@usex/rule-engine-builder

🎨 Visual Rule Constructor for React Applications

npm version license codecov downloads stars

Quick StartComponentsExamplesWhy Visual Builder?

--- 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! 🎨 ``` ## 🚀 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 (

Build Your Business Rules

{rule && (

Generated Rule:

{JSON.stringify(rule, null, 2)}
)}
); 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 ``` ### RuleEvaluator Real-time rule evaluation with visual feedback. ```tsx ``` ### ModernConstraintEditor Advanced constraint editing with intelligent suggestions. ```tsx ``` ## 🔧 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 (

Discount Rule Builder

); } ``` ### 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 (

Access Control Rules

{ console.log('Access Decision:', result); }} />
); } ``` ### 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 (

Form Validation Rules

{validationRules.map((rule, index) => (

Rule {index + 1}

{ const updated = [...validationRules]; updated[index] = newRule; setValidationRules(updated); }} availableFields={formFields} mode="validation" showPreview={false} />
))}
); } ``` ## 🎨 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)' } }; ``` ### Field Discovery ```tsx // Auto-discover fields from your data schema const fields = useFieldDiscovery(sampleData, { maxDepth: 3, includeArrays: true, typeInference: true }); { console.log('New field discovered:', field); }} /> ``` ### History Management ```tsx function RuleBuilderWithHistory() { const [rule, setRule] = useState(null); const { history, undo, redo, canUndo, canRedo } = useRuleHistory(); return (
Step {history.currentIndex + 1} of {history.entries.length}
); } ``` ### 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 ``` ### Lazy Loading Components are loaded on-demand for better performance: ```tsx const LazyRuleBuilder = lazy(() => import('@usex/rule-engine-builder')); function App() { return ( Loading rule builder...}> ); } ``` ### 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), [] ); ``` ## 🎓 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 { id: string; conditions: Condition[]; result?: T; metadata?: { name: string; description: string; created: Date; modified: Date; }; } // Type-safe rule builder const Builder = () => { const [rule, setRule] = useState>(null); return ( 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( ); expect(screen.getByText('Age')).toBeInTheDocument(); expect(screen.getByText('Country')).toBeInTheDocument(); }); it('should handle drag and drop', () => { const onChange = jest.fn(); render( ); 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) ---
**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)
================================================ 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: `` - [ ] 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! 📖 ---

Made with ❤️ by the @usex/rule-engine community

GitHubnpmDocumentation

================================================ 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 ( ); } ``` ## 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
``` ## 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; onChange?: (rule: any) => void; onSave?: (rule: any) => void | Promise; 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; 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 ``` ### 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; onDataChange?: (data: Record) => 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 ``` ### 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 ``` ## Editor Components ### TreeConditionGroup Nested condition group management. ```typescript interface TreeConditionGroupProps { condition: Condition; path: number[]; depth: number; fields: FieldConfig[]; sampleData?: Record; customOperators?: Record; 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; customOperators?: Record; 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 ``` ### 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 ``` ### 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 ``` ### 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 ``` ### 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; // 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) => void; }); interface DiscoveryOptions { maxDepth?: number; includeArrayIndices?: boolean; generateLabels?: boolean; excludePaths?: string[]; fieldTypes?: Record; } ``` ### 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 (
); } ``` ### 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 (
{selectedVersions.length === 2 && ( )}
); } ``` --- 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 (

Dynamic Pricing Rules

Create rules to automatically adjust pricing based on customer, product, and context factors.

{/* Example rule preview */}

Example Pricing Rules:

  • • Gold/Platinum customers get 15% off electronics over $200
  • • First-time customers get 10% off their first order
  • • Bulk orders (5+ items) get 20% off
  • • Winter season: 25% off clothing items
); } ``` ### 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 (

Shipping Rate Rules

console.log('Shipping rule:', rule)} labels={{ addGroup: 'Add Shipping Condition', noRules: 'No shipping rules defined. Create rules to calculate shipping rates.' }} />
{/* Rate examples */}

Standard Shipping

$5.99 base + $0.50/lb

Expedited Shipping

$12.99 base + $1.00/lb

Overnight Shipping

$24.99 base + $2.00/lb

); } ``` ### 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 (

Promotional Campaign Rules

Define complex promotional rules with multiple conditions and customer targeting.

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' }} />
{/* Campaign examples */}

Example Campaign Rules:

New Customer Welcome

  • • First-time customers only
  • • 20% off first order
  • • Minimum $50 purchase

Loyalty Rewards

  • • 5+ previous orders
  • • 15% off electronics
  • • Free shipping included
); } ``` ## 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 (

Access Control Rules

Define role-based access control rules with fine-grained permissions.

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' }} />
{/* Access examples */}

Admin Access

  • • Full system access
  • • All resource types
  • • All actions allowed

Manager Access

  • • Department resources
  • • Team management
  • • Read/Write permissions

Employee Access

  • • Own resources only
  • • Public documents
  • • Limited actions
); } ``` ### 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 (

Multi-Factor Authentication Rules

Create intelligent MFA rules based on risk assessment and context.

console.log('MFA rule:', rule)} labels={{ addGroup: 'Add MFA Condition' }} />
{/* MFA scenarios */}

MFA Trigger Scenarios:

High Risk Scenarios:

  • • Unknown device or location
  • • High-sensitivity actions
  • • Elevated risk score (> 50)
  • • International access

Low Risk Scenarios:

  • • Trusted device + known location
  • • Low-sensitivity actions
  • • Recent successful authentication
  • • Low risk score (< 20)
); } ``` ## 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 (

Registration Validation Rules

Create comprehensive validation rules for user registration forms.

{/* Form testing */}

Test Validation

Sample Form Data:

              {JSON.stringify(formData, null, 2)}
            

Validation Rules:

  • • Email must be valid format
  • • Password minimum 8 characters
  • • Password must contain uppercase, lowercase, number, symbol
  • • Passwords must match
  • • Age must be 18 or older
  • • Terms must be accepted
); } ``` ### 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 (

Dynamic Form Validation

Create conditional validation rules that adapt based on form context and user role.

console.log('Dynamic validation rule:', rule)} labels={{ addGroup: 'Add Conditional Validation' }} />
{/* Validation scenarios */}

Step-Based Validation

  • • Step 1: Basic info required
  • • Step 2: Business details (if business account)
  • • Step 3: Payment info (if paid plan)
  • • Step 4: Final verification

Role-Based Validation

  • • Admin: All fields optional
  • • Business: Additional docs required
  • • Individual: Simplified validation
  • • Guest: Limited access
); } ``` ## 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 (

Lead Scoring Rules

Create intelligent lead scoring based on company fit and engagement metrics.

console.log('Lead scoring rule:', rule)} labels={{ addGroup: 'Add Scoring Condition' }} />
{/* Scoring matrix */}

Lead Scoring Matrix

Cold Lead (0-25)

  • • Small company
  • • Low engagement
  • • No demo interest

Warm Lead (26-50)

  • • Medium company
  • • Some engagement
  • • Content downloads

Hot Lead (51-75)

  • • Large company
  • • High engagement
  • • Pricing interest

Qualified Lead (76-100)

  • • Enterprise company
  • • Decision maker
  • • Demo requested
); } ``` ### 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 (

Inventory Management Rules

Automate inventory decisions with intelligent reordering and stock level management.

console.log('Inventory rule:', rule)} labels={{ addGroup: 'Add Inventory Condition' }} />
{/* Inventory actions */}

Reorder Alert

  • • Stock below minimum
  • • High sales velocity
  • • Long supplier lead time

Overstock Warning

  • • Stock above maximum
  • • Decreasing sales trend
  • • Season ending

Optimal Stock

  • • Between min/max levels
  • • Stable sales trend
  • • Adequate supply buffer
); } ``` ## Integration Examples ### Complete E-commerce Platform ```tsx function EcommercePlatformDemo() { const [activeTab, setActiveTab] = useState('pricing'); return (

E-commerce Rule Engine Platform

{activeTab === 'pricing' && } {activeTab === 'shipping' && } {activeTab === 'promotions' && } {activeTab === 'inventory' && }
); } ``` ### 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 (

SaaS Rule Engine

{tenantData[tenant].name} - {ruleType.charAt(0).toUpperCase() + ruleType.slice(1)} Rules

Plan: {tenantData[tenant].plan} | Features: {tenantData[tenant].features.join(', ')}

{ruleType === 'access' && } {ruleType === 'validation' && } {ruleType === 'pricing' && }
); } ``` --- 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; // 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 (
{historyInfo.current} / {historyInfo.total}
{/* Rule builder UI */}
); } ``` **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 (
{/* Simple rule editing UI */}
); } ``` ## 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; // 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; byGroup: Record; }; // Actions discover: (data: any, options?: FieldDiscoveryOptions) => void; addCustomField: (field: FieldConfig) => void; removeField: (fieldName: string) => void; updateField: (fieldName: string, updates: Partial) => 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
Discovering fields...
; return (

Discovered Fields ({stats.totalFields})

{Object.entries(stats.byType).map(([type, count]) => ( {type}: {count} ))}
); } ``` **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 (
{isHelpOpen && ( setIsHelpOpen(false)} /> )}
); } ``` **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 (

Rule Builder

); } ``` ## Utility Hooks ### useDebounce Debounce values and callbacks for performance optimization. ```typescript function useDebounce(value: T, delay: number): T; function useDebounce 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 ( ); } ``` ### useLocalStorage Persistent local storage with automatic serialization. ```typescript function useLocalStorage( 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 ( { if (userPreferences.autoSave) { setSavedRule(rule); } }} showJsonViewer={userPreferences.showJsonViewer} theme={userPreferences.theme} /> ); } ``` ### useEventListener Type-safe event listener management. ```typescript function useEventListener( eventType: T, handler: (event: WindowEventMap[T]) => void, options?: AddEventListenerOptions ): void; function useEventListener( eventType: T, handler: (event: HTMLElementEventMap[T]) => void, element: RefObject, options?: AddEventListenerOptions ): void; ``` **Usage:** ```tsx import { useEventListener } from '@usex/rule-engine-builder'; function RuleBuilderWithEvents() { const containerRef = useRef(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 (
); } ``` ## Custom Hook Patterns ### useAsyncRule Handle async rule operations with loading states. ```typescript function useAsyncRule() { const [rule, setRule] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(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); } }, []); return { rule, isLoading, error, loadRule, saveRule, setRule }; } ``` ### useRuleValidation Real-time rule validation with detailed feedback. ```typescript function useRuleValidation(rule: RuleType | null) { const [validation, setValidation] = useState(null); useEffect(() => { if (!rule) { setValidation(null); return; } const validateAsync = async () => { try { const result = await RuleEngine.validate(rule); setValidation(result); } catch (error) { setValidation({ isValid: false, error: { message: error.message, path: '', details: error } }); } }; validateAsync(); }, [rule]); return validation; } ``` ### useRuleEvaluation Reactive rule evaluation with caching. ```typescript function useRuleEvaluation(rule: RuleType | null, data: any) { const [result, setResult] = useState(null); const [isEvaluating, setIsEvaluating] = useState(false); const evaluate = useCallback(async () => { if (!rule || !data) { setResult(null); return; } setIsEvaluating(true); try { const evaluationResult = await RuleEngine.evaluate(rule, data); setResult(evaluationResult); } catch (error) { setResult({ value: rule.default || false, isPassed: false, message: `Evaluation error: ${error.message}` }); } finally { setIsEvaluating(false); } }, [rule, data]); useEffect(() => { evaluate(); }, [evaluate]); return { result, isEvaluating, evaluate }; } ``` ### Hook Composition Example ```tsx function AdvancedRuleBuilder({ ruleId }: { ruleId?: string }) { // Core rule management const { rule, isLoading, error, loadRule, saveRule } = useAsyncRule(); const { updateRule, undo, redo, canUndo, canRedo } = useEnhancedRuleStore(); // Field discovery const { fields, discover } = useFieldDiscovery(); // Validation and evaluation const validation = useRuleValidation(rule); const { result: evaluationResult } = useRuleEvaluation(rule, sampleData); // UI state const { theme, toggleTheme } = useTheme(); const [preferences, setPreferences] = useLocalStorage('preferences', { autoSave: true, showValidation: true }); // Keyboard shortcuts useKeyboardShortcuts([ { key: 's', ctrl: true, handler: () => rule && saveRule(rule), description: 'Save rule' }, { key: 'z', ctrl: true, handler: () => canUndo() && undo(), description: 'Undo' } ]); // Auto-save const debouncedSave = useDebounce(saveRule, 2000); useEffect(() => { if (rule && preferences.autoSave) { debouncedSave(rule); } }, [rule, preferences.autoSave, debouncedSave]); // Load initial rule useEffect(() => { if (ruleId) { loadRule(ruleId); } }, [ruleId, loadRule]); if (isLoading) return
Loading rule...
; if (error) return
Error: {error.message}
; return (
{/* Validation feedback */} {preferences.showValidation && validation && !validation.isValid && ( {validation.error?.message} )} {/* Evaluation result */} {evaluationResult && (
Result: {JSON.stringify(evaluationResult.value)}
)} {/* Main rule builder */}
); } ``` --- For more information, see the [main documentation](../README.md). ================================================ FILE: packages/builder/docs/integration.md ================================================ # Integration Guide Complete guide for integrating @usex/rule-engine-builder into your applications. ## Table of Contents - [Framework Integration](#framework-integration) - [State Management Integration](#state-management-integration) - [Backend Integration](#backend-integration) - [Styling Integration](#styling-integration) - [Testing Integration](#testing-integration) - [Performance Optimization](#performance-optimization) ## Framework Integration ### React Integration #### Basic Setup ```tsx import { TreeRuleBuilder } from '@usex/rule-engine-builder'; import '@usex/rule-engine-builder/styles'; function App() { return (
); } ``` #### With React Router ```tsx import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import { TreeRuleBuilder } from '@usex/rule-engine-builder'; function RuleBuilderPage() { const { ruleId } = useParams(); const [rule, setRule] = useState(null); useEffect(() => { if (ruleId) { loadRule(ruleId).then(setRule); } }, [ruleId]); return ( ); } function App() { return ( } /> } /> ); } ``` #### With Context Providers ```tsx import { RuleBuilderProvider, useEnhancedRuleStore } from '@usex/rule-engine-builder'; function RuleBuilderWithContext() { return ( ); } function RuleBuilderContent() { const { rule, updateRule } = useEnhancedRuleStore(); return (
); } ``` ### Next.js Integration #### App Router (Next.js 13+) ```tsx // app/rules/page.tsx 'use client'; import dynamic from 'next/dynamic'; import { useState } from 'react'; const TreeRuleBuilder = dynamic( () => import('@usex/rule-engine-builder').then(mod => ({ default: mod.TreeRuleBuilder })), { ssr: false, loading: () =>
Loading rule builder...
} ); export default function RulesPage() { const [rule, setRule] = useState(null); return (

Rule Builder

); } ``` #### API Routes Integration ```tsx // app/api/rules/route.ts import { NextRequest, NextResponse } from 'next/server'; import { RuleEngine } from '@usex/rule-engine'; export async function POST(request: NextRequest) { const { rule, data } = await request.json(); try { // Validate rule const validation = RuleEngine.validate(rule); if (!validation.isValid) { return NextResponse.json( { error: validation.error.message }, { status: 400 } ); } // Evaluate rule const result = await RuleEngine.evaluate(rule, data); return NextResponse.json({ result }); } catch (error) { return NextResponse.json( { error: error.message }, { status: 500 } ); } } ``` #### Server Components with Client Boundary ```tsx // app/rules/[id]/page.tsx import { RuleBuilderClient } from './rule-builder-client'; async function getRuleData(id: string) { // Fetch rule data on server const response = await fetch(`${process.env.API_URL}/rules/${id}`); return response.json(); } export default async function RulePage({ params }: { params: { id: string } }) { const ruleData = await getRuleData(params.id); return (

Edit Rule: {ruleData.name}

); } ``` ```tsx // app/rules/[id]/rule-builder-client.tsx 'use client'; import { TreeRuleBuilder } from '@usex/rule-engine-builder'; interface RuleBuilderClientProps { initialRule: any; } export function RuleBuilderClient({ initialRule }: RuleBuilderClientProps) { return ( ); } ``` ### Vite Integration ```tsx // vite.config.ts import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [react()], optimizeDeps: { include: ['@usex/rule-engine-builder'] }, css: { postcss: './postcss.config.js' } }); ``` ```tsx // src/App.tsx import { TreeRuleBuilder } from '@usex/rule-engine-builder'; import '@usex/rule-engine-builder/styles'; function App() { return (
); } export default App; ``` ## State Management Integration ### Redux Toolkit Integration ```tsx // store/ruleSlice.ts import { createSlice, PayloadAction } from '@reduxjs/toolkit'; interface RuleState { currentRule: any; rules: Record; isLoading: boolean; error: string | null; } const initialState: RuleState = { currentRule: null, rules: {}, isLoading: false, error: null }; const ruleSlice = createSlice({ name: 'rules', initialState, reducers: { setCurrentRule: (state, action: PayloadAction) => { state.currentRule = action.payload; }, saveRule: (state, action: PayloadAction<{ id: string; rule: any }>) => { const { id, rule } = action.payload; state.rules[id] = rule; state.currentRule = rule; }, setLoading: (state, action: PayloadAction) => { state.isLoading = action.payload; }, setError: (state, action: PayloadAction) => { state.error = action.payload; } } }); export const { setCurrentRule, saveRule, setLoading, setError } = ruleSlice.actions; export default ruleSlice.reducer; ``` ```tsx // components/RuleBuilderRedux.tsx import { useSelector, useDispatch } from 'react-redux'; import { TreeRuleBuilder } from '@usex/rule-engine-builder'; import { setCurrentRule } from '../store/ruleSlice'; function RuleBuilderRedux() { const dispatch = useDispatch(); const { currentRule, isLoading } = useSelector((state: RootState) => state.rules); const handleRuleChange = (rule: any) => { dispatch(setCurrentRule(rule)); }; if (isLoading) return
Loading...
; return ( ); } ``` ### Zustand Integration ```tsx // store/ruleStore.ts import { create } from 'zustand'; import { persist } from 'zustand/middleware'; interface RuleStore { rule: any; history: any[]; setRule: (rule: any) => void; addToHistory: (rule: any) => void; clearHistory: () => void; } const useRuleStore = create()( persist( (set, get) => ({ rule: null, history: [], setRule: (rule) => { const { addToHistory } = get(); addToHistory(rule); set({ rule }); }, addToHistory: (rule) => { set((state) => ({ history: [...state.history.slice(-9), rule] // Keep last 10 })); }, clearHistory: () => set({ history: [] }) }), { name: 'rule-storage' } ) ); export default useRuleStore; ``` ### TanStack Query Integration ```tsx // hooks/useRuleQueries.ts import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { RuleEngine } from '@usex/rule-engine'; export function useRule(ruleId: string) { return useQuery({ queryKey: ['rule', ruleId], queryFn: () => fetchRule(ruleId), enabled: !!ruleId }); } export function useSaveRule() { const queryClient = useQueryClient(); return useMutation({ mutationFn: saveRule, onSuccess: (data, variables) => { queryClient.setQueryData(['rule', variables.id], data); queryClient.invalidateQueries({ queryKey: ['rules'] }); } }); } export function useValidateRule() { return useMutation({ mutationFn: (rule: any) => Promise.resolve(RuleEngine.validate(rule)) }); } export function useEvaluateRule() { return useMutation({ mutationFn: ({ rule, data }: { rule: any; data: any }) => RuleEngine.evaluate(rule, data) }); } ``` ```tsx // components/RuleBuilderWithQuery.tsx import { TreeRuleBuilder } from '@usex/rule-engine-builder'; import { useRule, useSaveRule, useValidateRule } from '../hooks/useRuleQueries'; function RuleBuilderWithQuery({ ruleId }: { ruleId: string }) { const { data: rule, isLoading } = useRule(ruleId); const saveRuleMutation = useSaveRule(); const validateRuleMutation = useValidateRule(); const handleSave = async (ruleToSave: any) => { // Validate first const validation = await validateRuleMutation.mutateAsync(ruleToSave); if (!validation.isValid) { throw new Error(validation.error.message); } // Save if valid await saveRuleMutation.mutateAsync({ id: ruleId, rule: ruleToSave }); }; if (isLoading) return
Loading rule...
; return ( ); } ``` ## Backend Integration ### Express.js API ```typescript // routes/rules.ts import express from 'express'; import { RuleEngine } from '@usex/rule-engine'; const router = express.Router(); // Validate rule endpoint router.post('/validate', async (req, res) => { try { const { rule } = req.body; const validation = RuleEngine.validate(rule); res.json(validation); } catch (error) { res.status(500).json({ error: error.message }); } }); // Evaluate rule endpoint router.post('/evaluate', async (req, res) => { try { const { rule, data } = req.body; const result = await RuleEngine.evaluate(rule, data); res.json(result); } catch (error) { res.status(500).json({ error: error.message }); } }); // Save rule endpoint router.post('/rules', async (req, res) => { try { const { rule, name, description } = req.body; // Validate rule before saving const validation = RuleEngine.validate(rule); if (!validation.isValid) { return res.status(400).json({ error: validation.error.message }); } // Save to database const savedRule = await saveRuleToDatabase({ rule, name, description, createdAt: new Date(), userId: req.user.id }); res.json(savedRule); } catch (error) { res.status(500).json({ error: error.message }); } }); export default router; ``` ### GraphQL Integration ```typescript // schema/rule.ts import { gql } from 'apollo-server-express'; import { RuleEngine } from '@usex/rule-engine'; export const typeDefs = gql` type Rule { id: ID! name: String! description: String rule: JSON! createdAt: String! updatedAt: String! } type ValidationResult { isValid: Boolean! error: String } type EvaluationResult { value: JSON! isPassed: Boolean! message: String } type Query { rule(id: ID!): Rule rules: [Rule!]! } type Mutation { createRule(name: String!, description: String, rule: JSON!): Rule! updateRule(id: ID!, name: String, description: String, rule: JSON): Rule! validateRule(rule: JSON!): ValidationResult! evaluateRule(rule: JSON!, data: JSON!): EvaluationResult! } `; export const resolvers = { Query: { rule: async (_, { id }, { dataSources }) => { return await dataSources.ruleAPI.getRule(id); }, rules: async (_, __, { dataSources }) => { return await dataSources.ruleAPI.getRules(); } }, Mutation: { createRule: async (_, { name, description, rule }, { dataSources }) => { const validation = RuleEngine.validate(rule); if (!validation.isValid) { throw new Error(validation.error.message); } return await dataSources.ruleAPI.createRule({ name, description, rule }); }, validateRule: async (_, { rule }) => { return RuleEngine.validate(rule); }, evaluateRule: async (_, { rule, data }) => { return await RuleEngine.evaluate(rule, data); } } }; ``` ### Database Integration ```typescript // models/Rule.ts import { Schema, model, Document } from 'mongoose'; interface IRule extends Document { name: string; description?: string; rule: any; version: number; isActive: boolean; tags: string[]; createdBy: string; createdAt: Date; updatedAt: Date; } const ruleSchema = new Schema({ name: { type: String, required: true }, description: { type: String }, rule: { type: Schema.Types.Mixed, required: true }, version: { type: Number, default: 1 }, isActive: { type: Boolean, default: true }, tags: [{ type: String }], createdBy: { type: String, required: true }, createdAt: { type: Date, default: Date.now }, updatedAt: { type: Date, default: Date.now } }); // Add validation middleware ruleSchema.pre('save', function(next) { const { RuleEngine } = require('@usex/rule-engine'); const validation = RuleEngine.validate(this.rule); if (!validation.isValid) { return next(new Error(validation.error.message)); } this.updatedAt = new Date(); next(); }); export const Rule = model('Rule', ruleSchema); ``` ## Styling Integration ### Tailwind CSS Integration ```tsx // tailwind.config.js module.exports = { content: [ './src/**/*.{js,jsx,ts,tsx}', './node_modules/@usex/rule-engine-builder/**/*.{js,jsx,ts,tsx}' ], theme: { extend: { colors: { 'rule-builder': { primary: '#3b82f6', secondary: '#6366f1', success: '#10b981', warning: '#f59e0b', danger: '#ef4444' } } } }, plugins: [] }; ``` ### Styled Components Integration ```tsx import styled, { ThemeProvider } from 'styled-components'; import { TreeRuleBuilder } from '@usex/rule-engine-builder'; const theme = { colors: { primary: '#3b82f6', background: '#ffffff', border: '#e5e7eb' }, spacing: { sm: '0.5rem', md: '1rem', lg: '1.5rem' } }; const StyledRuleBuilder = styled.div` .rule-builder { --primary-color: ${props => props.theme.colors.primary}; --background-color: ${props => props.theme.colors.background}; --border-color: ${props => props.theme.colors.border}; } `; function App() { return ( ); } ``` ### CSS Modules Integration ```css /* RuleBuilder.module.css */ .container { padding: 1rem; background: var(--background-color); border-radius: 0.5rem; } .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; } .content { min-height: 400px; } :global(.rule-engine-builder) { --primary-color: #3b82f6; --secondary-color: #6366f1; } ``` ```tsx import styles from './RuleBuilder.module.css'; import { TreeRuleBuilder } from '@usex/rule-engine-builder'; function RuleBuilderComponent() { return (

Rule Builder

); } ``` ## Testing Integration ### Jest Testing ```tsx // __tests__/RuleBuilder.test.tsx import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import { TreeRuleBuilder } from '@usex/rule-engine-builder'; // Mock the heavy dependencies jest.mock('@usex/rule-engine-builder', () => ({ TreeRuleBuilder: jest.fn(() =>
Rule Builder
) })); describe('RuleBuilder Integration', () => { it('renders rule builder component', () => { const handleChange = jest.fn(); render( ); expect(screen.getByTestId('rule-builder')).toBeInTheDocument(); }); it('calls onChange when rule changes', async () => { const handleChange = jest.fn(); const mockRule = { conditions: [], default: null }; // Mock implementation that calls onChange const MockTreeRuleBuilder = jest.fn(({ onChange }) => ( )); jest.mocked(TreeRuleBuilder).mockImplementation(MockTreeRuleBuilder); render(); fireEvent.click(screen.getByText('Update Rule')); await waitFor(() => { expect(handleChange).toHaveBeenCalledWith(mockRule); }); }); }); ``` ### Testing with Mock Service Worker ```tsx // __tests__/setup.ts import { setupServer } from 'msw/node'; import { rest } from 'msw'; export const server = setupServer( rest.post('/api/rules/validate', (req, res, ctx) => { return res( ctx.json({ isValid: true, error: null }) ); }), rest.post('/api/rules/evaluate', (req, res, ctx) => { return res( ctx.json({ value: true, isPassed: true, message: null }) ); }) ); beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); afterAll(() => server.close()); ``` ### E2E Testing with Playwright ```typescript // tests/rule-builder.spec.ts import { test, expect } from '@playwright/test'; test.describe('Rule Builder', () => { test('should create a new rule', async ({ page }) => { await page.goto('/rules/new'); // Wait for rule builder to load await page.waitForSelector('[data-testid="rule-builder"]'); // Add a condition group await page.click('[data-testid="add-condition-group"]'); // Select a field await page.click('[data-testid="field-selector"]'); await page.click('text=User Email'); // Select an operator await page.click('[data-testid="operator-selector"]'); await page.click('text=equals'); // Enter a value await page.fill('[data-testid="value-input"]', 'admin@example.com'); // Save the rule await page.click('[data-testid="save-button"]'); // Verify success message await expect(page.locator('text=Rule saved successfully')).toBeVisible(); }); test('should validate rule before saving', async ({ page }) => { await page.goto('/rules/new'); // Try to save empty rule await page.click('[data-testid="save-button"]'); // Should show validation error await expect(page.locator('text=Rule is invalid')).toBeVisible(); }); }); ``` ## Performance Optimization ### Code Splitting ```tsx import { lazy, Suspense } from 'react'; const TreeRuleBuilder = lazy(() => import('@usex/rule-engine-builder').then(module => ({ default: module.TreeRuleBuilder })) ); function App() { return ( Loading rule builder...}> ); } ``` ### Memoization ```tsx import { memo, useMemo, useCallback } from 'react'; import { TreeRuleBuilder } from '@usex/rule-engine-builder'; const MemoizedRuleBuilder = memo(TreeRuleBuilder); function OptimizedRuleBuilder({ data, onRuleChange }) { const fields = useMemo(() => { return discoverFields(data); }, [data]); const handleRuleChange = useCallback((rule) => { onRuleChange(rule); }, [onRuleChange]); return ( ); } ``` ### Virtual Scrolling ```tsx import { FixedSizeList as List } from 'react-window'; import { TreeRuleBuilder } from '@usex/rule-engine-builder'; function VirtualizedRuleList({ rules }) { const renderRule = useCallback(({ index, style }) => (
), [rules]); return ( {renderRule} ); } ``` ### Bundle Analysis ```bash # Analyze bundle size npm install --save-dev webpack-bundle-analyzer # Add script to package.json { "scripts": { "analyze": "npx webpack-bundle-analyzer build/static/js/*.js" } } # Run analysis npm run analyze ``` ### Performance Monitoring ```tsx import { Profiler } from 'react'; function onRenderCallback(id, phase, actualDuration) { console.log('Component:', id, 'Phase:', phase, 'Duration:', actualDuration); } function App() { return ( ); } ``` --- For more integration examples and best practices, see the [main documentation](../README.md). ================================================ FILE: packages/builder/index.html ================================================ Rule Engine - Demo
================================================ FILE: packages/builder/package.json ================================================ { "name": "@usex/rule-engine-builder", "type": "module", "version": "0.0.3", "private": false, "description": "Visual rule construction toolkit for React applications. Drag, drop, and compose complex business logic without writing JSON. Transform IF-THEN decisions into intuitive visual flows with real-time evaluation, undo/redo history, and TypeScript-powered intelligence.", "repository": { "type": "git", "url": "git+https://github.com/ali-master/rule-engine.git", "directory": "packages/builder" }, "keywords": [ "react-rule-builder", "visual-rule-engine", "business-logic-builder", "no-code-rules", "decision-tree-builder", "if-then-else-builder", "visual-programming", "business-rules-ui", "decision-engine-ui", "visual-json-builder", "rule-evaluation-ui", "interactive-rule-editor", "react" ], "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" }, "./styles": { "import": "./dist/style.css" } }, "main": "./dist/index.js", "module": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ "dist" ], "scripts": { "dev": "vite", "build": "tsc -b && vite build", "build:demo": "cd ../core && pnpm run build && cd ../builder && BUILD_MODE=demo vite build", "preview": "vite preview", "preview:demo": "BUILD_MODE=demo vite preview --outDir dist-demo", "test:types": "tsc --noEmit", "test:knip": "knip", "test:knip:fix": "knip --fix", "format:check": "prettier --check \"**/*.{ts,tsx,mdx}\"", "format": "prettier --write \"**/*.{ts,tsx,mdx}\"", "lint": "eslint \"src/**/*.{ts,tsx,js}\"", "lint:fix": "pnpm run lint --fix", "prepublishOnly": "pnpm lint", "release": "cross-env CI=true pnpm run build", "postrelease": "standard-version && pnpm publish --access public && git push --follow-tags origin master", "release:beta": "pnpm run build", "postrelease:beta": "standard-version --prerelease beta && pnpm publish --access public --tag beta && git push --follow-tags origin master" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "dependencies": { "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", "@number-flow/react": "^0.5.10", "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-hover-card": "^1.1.15", "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-scroll-area": "^1.2.10", "@radix-ui/react-select": "^2.2.6", "@radix-ui/react-separator": "^1.1.7", "@radix-ui/react-slider": "^1.3.6", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-switch": "^1.2.6", "@radix-ui/react-tabs": "^1.1.13", "@radix-ui/react-toast": "^1.2.15", "@radix-ui/react-toggle": "^1.1.10", "@radix-ui/react-toggle-group": "^1.1.11", "@radix-ui/react-tooltip": "^1.2.8", "@usex/rule-engine": "workspace:*", "@vercel/analytics": "^1.5.0", "@vercel/speed-insights": "^1.2.0", "class-variance-authority": "0.7.1", "clsx": "2.1.1", "cmdk": "^1.1.1", "date-fns": "^4.1.0", "diff": "^8.0.2", "framer-motion": "^12.23.18", "lucide-react": "0.544.0", "react-day-picker": "^9.11.0", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", "react-hook-form": "^7.63.0", "sonner": "^2.0.7", "tailwind-merge": "3.3.1", "tw-animate-css": "1.3.8", "vaul": "^1.1.2", "zustand": "^5.0.8" }, "devDependencies": { "@tailwindcss/vite": "^4.1.13", "@types/diff": "^8.0.0", "@types/react": "^19.1.13", "@types/react-dom": "^19.1.9", "@vitejs/plugin-react-swc": "^4.1.0", "autoprefixer": "^10.4.21", "postcss": "^8.5.6", "react": "^19.1.1", "react-dom": "^19.1.1", "tailwindcss": "^4.1.13", "vite": "^7.1.7", "vite-plugin-dts": "^4.5.4", "vite-plugin-node-polyfills": "^0.24.0" } } ================================================ FILE: packages/builder/src/App.tsx ================================================ import { RuleEngine } from "@usex/rule-engine"; import { TestTube, PlayCircle, AlertCircle } from "lucide-react"; import React, { useState } from "react"; import { Toaster, toast } from "sonner"; import { ThemeProvider } from "./components/theme-provider"; import { ThemeToggle } from "./components/theme-toggle"; import { TreeRuleBuilder } from "./components/TreeRuleBuilder"; import { AlertDescription, Alert } from "./components/ui/alert"; import { Button } from "./components/ui/button"; import { SheetTrigger, SheetTitle, SheetHeader, SheetDescription, SheetContent, Sheet, } from "./components/ui/sheet"; import { Textarea } from "./components/ui/textarea"; import { useEnhancedRuleStore } from "./stores/enhanced-rule-store"; import "./styles/globals.css"; const sampleData = { user: { id: "user-123", name: "John Doe", email: "john@example.com", age: 30, isActive: true, role: "admin", tags: ["premium", "verified", "beta"], profile: { bio: "Software developer", preferences: { theme: "dark", notifications: true, }, }, }, product: { id: "prod-456", name: "Premium Widget", price: 99.99, inStock: true, category: "electronics", tags: ["featured", "bestseller"], }, order: { id: "order-789", total: 299.97, status: "processing", itemCount: 3, createdAt: new Date().toISOString(), }, }; function AppContent() { const { rule } = useEnhancedRuleStore(); const [testData, setTestData] = useState(JSON.stringify(sampleData, null, 2)); const [testResult, setTestResult] = useState(null); const [isTestRunning, setIsTestRunning] = useState(false); const [isSheetOpen, setIsSheetOpen] = useState(false); const handleTestRule = async () => { setIsTestRunning(true); setTestResult(null); try { const data = JSON.parse(testData); const result = await RuleEngine.evaluate(rule, data); // Handle single result or array of results const isPassed = Array.isArray(result) ? result.every((r) => r.isPassed) : result.isPassed; setTestResult({ success: true, result, passed: isPassed, }); toast.success( isPassed ? "Rule evaluation passed!" : "Rule evaluation failed!", ); } catch (error: any) { setTestResult({ success: false, error: error.message, }); toast.error("Error evaluating rule"); } finally { setIsTestRunning(false); } }; return (
{/* Header */}

Rule Engine Builder

Build complex business rules with a tree structure

{/* Evaluate Button */} Evaluate Rule Test your rule against sample data