Skip to content

cesarParra/expression

Repository files navigation

Expression Logo

Powerful formula-syntax evaluator for Apex and LWC.

Features

  • Supports all the most important operators and functions available in Salesforce formulas
  • Support for lists and maps, including spread operator (...) support.
  • Automatically understands relationships and can extract data from child records
  • Comment support
  • String interpolations
  • Pre-built LWC component to evaluate Expressions in record pages and Experience Builder sites
  • And much more!

Examples

Basic Math Operations

Object simpleMath = expression.Evaluator.run('(1 + 1) * 10');
System.debug(simpleMath); // 20

Object respectsPemdas = expression.Evaluator.run('1 + 1 * 10 + 50 * 20 / 100 + (20 * 20 /10)');
System.debug(respectsPemdas); // 61

String Operations

Object simpleConcat = expression.Evaluator.run('"👋 hello " + "there!"');
System.debug(simpleConcat); // 👋 hello there!

Id recordId = '001Oy00000GkWjfIAF';
Object interpolation = expression.Evaluator.run('"👋 hello ${Name}"', recordId);
System.debug(interpolation); // 👋 hello Acme Inc.

Advanced Operations

// Calculating if a year is a leap year
Id recordId = '001Oy00000GkWjfIAF';
Object result = expression.Evaluator.run('OR(\n' +
    '  MOD( YEAR( DATEVALUE(CreatedDate) ), 400 ) = 0, \n' +
    '  AND( \n' +
    '   MOD( YEAR( DATEVALUE(CreatedDate) ), 4 ) = 0,\n' +
    '    MOD( YEAR( DATEVALUE(CreatedDate) ), 100 ) != 0\n' +
    '  )\n' +
    ')', recordId);
System.debug(result); // true

// Determining the the region of an address
Id recordId = '001Oy00000GkWjfIAF';
Object result = expression.Evaluator.run('IF(ISBLANK(BillingState), "None",\n' +
    'IF(CONTAINS("AK:AZ:CA:HA:NV:NM:OR:UT:WA", BillingState), "West",\n' +
    'IF(CONTAINS("CO:ID:MT:KS:OK:TX:WY", BillingState), "Central",\n' +
    'IF(CONTAINS("CT:ME:MA:NH:NY:PA:RI:VT", BillingState), "East",\n' +
    'IF(CONTAINS("AL:AR:DC:DE:FL:GA:KY:LA:MD:MS:NC:NJ:SC:TN:VA:WV", BillingState), "South",\n' +
    'IF(CONTAINS("IL:IN:IA:MI:MN:MO:NE:ND:OH:SD:WI", BillingState), "North", "Other"))))))', recordId);
System.debug(result); // South

Using Lists and Maps

Object listExample = expression.Evaluator.run('[1, 2, 3]');
System.debug(listExample); // (1 2 3)

Object mapExample = expression.Evaluator.run('{"key": "value"}');
System.debug(mapExample); // {key=value}

Piping Complex Operations

Id recordId = '001Oy00000GkWjfIAF';
Object result = expression.Evaluator.run(
    'ChildAccounts ' +
        '-> WHERE(AnnualRevenue > 200) ' +
        '-> WHERE(NumberOfEmployees > 10) ' +
        '-> MAP(Name)',
    recordId);
System.debug(result); // (Acme Inc. Acme Subsidiary)

Documentation

Table of Contents

For the full Expression language documentation, please visit cesarparra.github.io/expression/.


Contributing

Contributions are welcome! Feel free to open an issue or submit a pull request.

Setup

Create a scratch org by running:

sfdx force:org:create -f config/dev.json -a Expression --setdefaultusername

Push the source to the scratch org:

sfdx force:source:push

Assign the Expression Admin permission set to the default user:

sfdx force:user:permset:assign -n Expression_Admin

Debugging

While debugging, you might find it helpful to see the generated AST for a given expression.

The source code includes a Visitor implementation whose sole purpose is to do this, AstPrinter. When enabled, it will print the AST to the logs.

You can enable it by passing an expression.Configuration option to the run method with the printAst option enabled :

expression.Configuration config = new expression.Configuration().printAst();
Object value = expression.Evaluator.run('AND(true, false, 1=1)', config);
// Outputs to the logs:
// (AND true false (= 1 1))

Running tests

Run the tests with:

sfdx force:apex:test:run