Nostalgic Piano Music

    json-expression-eval
    TypeScript icon, indicating that this package has built-in type declarations

    4.1.0 • Public • Published

    Npm Version node Build status Test Coverage Maintainability Known Vulnerabilities

    json-expression-eval

    A Fully typed Node.js module that evaluates a json described boolean expressions using dynamic functions and a given context.

    The module is strictly typed, ensuring that passed expressions are 100% valid at compile time.

    This module is especially useful if you need to serialize complex expressions (to be saved in DB for example)

    Installation

    npm install json-expression-eval

    Or

    yarn add json-expression-eval

    Usage

    Please see tests and examples dir for more usages and examples (under /src)

    import {evaluate, Expression, ExpressionHandler, validate, ValidationContext} from 'json-expression-eval';
    import {Moment} from 'moment';
    import moment = require('moment');
    
    interface IExampleContext {
        userId: string;
        times: number | undefined;
        date: Moment;
        nested: {
            value: number | null;
            nested2: {
                value2?: number;
                value3: boolean;
            };
        };
    }
    
    type IExampleContextIgnore = Moment;
    
    type IExampleFunctionTable = {
        countRange: ([min, max]: [min: number, max: number], ctx: { times: number | undefined }) => boolean;
    }
    
    type IExampleExpression = Expression<IExampleContext, IExampleFunctionTable, IExampleContextIgnore>; // We pass Moment here to avoid TS exhaustion
    
    const context: IExampleContext = {
        userId: 'a@b.com',
        times: 3,
        date: moment(),
        nested: {
            value: null,
            nested2: {
                value3: true,
            },
        },
    };
    
    // For validation we must provide a full example context
    const validationContext: ValidationContext<IExampleContext, IExampleContextIgnore> = {
        userId: 'a@b.com',
        times: 3,
        date: moment(),
        nested: {
            value: 5,
            nested2: {
                value2: 6,
                value3: true,
            },
        },
    };
    
    const functionsTable: IExampleFunctionTable = {
        countRange: ([min, max]: [min: number, max: number], ctx: { times: number | undefined }): boolean => {
            return ctx.times === undefined ? false : ctx.times >= min && ctx.times < max;
        },
    };
    
    const expression: IExampleExpression = {
        or: [
            {
                userId: 'a@b.com',
            },
            {
                and: [
                    {
                        countRange: [2, 6],
                    },
                    {
                        'nested.nested2.value3': true,
                    },
                ],
            },
        ],
    };
    
    // Example usage 1
    const handler =
        new ExpressionHandler<IExampleContext, IExampleFunctionTable, IExampleContextIgnore>(expression, functionsTable);
    handler.validate(validationContext); // Should not throw
    console.log(handler.evaluate(context)); // true
    
    // Example usage 2
    validate<IExampleContext, IExampleFunctionTable, IExampleContextIgnore>(expression, validationContext, functionsTable); // Should not throw
    console.log(evaluate<IExampleContext, IExampleFunctionTable, IExampleContextIgnore>(expression, context, functionsTable)); // true

    Expression

    There are 4 types of operators you can use (evaluated in that order of precedence):

    • and - accepts a non-empty list of expressions
    • or - accepts a non-empty list of expressions
    • not - accepts another expressions
    • <user defined funcs> - accepts any type of argument and evaluated by the user defined functions and the given context.
    • <compare funcs> - operates on one of the context properties and compares it to a given value.
      • {property: {op: value}}
        • available ops:
          • gt - >
          • gte - >=
          • lt - <
          • lte - <=
          • eq - ===
          • neq - !==
          • regexp: RegExp - True if matches the compiled regular expression.
          • regexpi: RegExp - True if matches the compiled regular expression with the i flag set.
          • nin: any[] - True if not in an array of values. Comparison is done using the === operator
          • inq: any[] - True if in an array of values. Comparison is done using the === operator
          • between: readonly [number, number] (as const) - True if the value is between the two specified values: greater than or equal to first value and less than or equal to second value.
      • {property: value}
        • compares the property to that value (shorthand to the eq op)

    Nested properties in the context can also be accessed using a dot notation (see example above) In each expression level, you can only define 1 operator, and 1 only

    Example expressions, assuming we have the user and maxCount user defined functions in place can be:

    {  
       "or":[  
          {  
             "not":{  
                "user":"a@b.com"
             }
          },
          {  
             "maxCount":1
          },
          {  
             "times": { "eq" : 5}
          },
          {  
             "country": "USA"
          }
       ]
    }

    Install

    npm i json-expression-eval

    DownloadsWeekly Downloads

    75

    Version

    4.1.0

    License

    GPL-3.0

    Unpacked Size

    66.6 kB

    Total Files

    23

    Last publish

    Collaborators

    • regevbr