Skip to main content

Record Context

Every formula is evaluated against a FormulaContext — the object that represents the Salesforce record and its environment.

Basic Fields

The record property is a flat object mapping field names to their values — the same shape as a SOQL query result:

import { evaluateFormula } from '@jetstreamapp/sf-formula-parser';

evaluateFormula('Name & " - $" & TEXT(Amount)', {
record: {
Name: 'Acme Corp',
Amount: 50000,
},
});
// "Acme Corp - $50000"

Field values can be any FormulaValue:

TypeExample
number42, 3.14
string"Acme Corp"
booleantrue, false
Datenew Date('2024-01-15')
SfTime{ timeInMillis: 43200000 } (noon)
GeoLocation{ latitude: 37.7749, longitude: -122.4194 }
nullnull (blank field)

Access fields on related records using dot-notation in the formula. Related records are nested directly in the record object:

// Formula: Account.Name
evaluateFormula('Account.Name', {
record: {
Account: { Name: 'Acme Corp' },
},
});
// "Acme Corp"

Multi-Level Relationships

Relationships can be nested:

// Formula: Contact.Account.Industry
evaluateFormula('Contact.Account.Industry', {
record: {
Contact: {
Account: { Industry: 'Technology' },
},
},
});
// "Technology"

Global Variables

Salesforce global variables like $User, $Profile, and $Organization are supported via the globals property:

// Formula: $User.FirstName
evaluateFormula('$User.FirstName', {
record: {},
globals: {
$User: {
FirstName: 'Jane',
LastName: 'Smith',
Email: 'jane@example.com',
},
},
});
// "Jane"

Prior Value Support

For trigger-context formulas that use ISCHANGED, PRIORVALUE, ISNEW, or ISCLONE:

// ISCHANGED(Status) - true when Status differs from prior value
evaluateFormula('ISCHANGED(Status)', {
record: { Status: 'Closed' },
priorRecord: { Status: 'Open' },
});
// true

// PRIORVALUE(Amount) - returns the previous value
evaluateFormula('PRIORVALUE(Amount)', {
record: { Amount: 200 },
priorRecord: { Amount: 100 },
});
// 100

// ISNEW() - true when the record is newly created
evaluateFormula('ISNEW()', {
record: {},
isNew: true,
});
// true

// ISCLONE() - true when the record is a clone
evaluateFormula('ISCLONE()', {
record: {},
isClone: true,
});
// true

Evaluation Options

Pass options as the third argument to evaluateFormula:

evaluateFormula(formula, context, {
treatBlanksAsZeroes: true, // default
now: new Date('2024-06-15T12:00:00Z'),
});

treatBlanksAsZeroes

Default: true

When enabled (the Salesforce default), null/blank values are coerced:

  • Blank numbers become 0
  • Blank text becomes ""

When disabled, null values propagate through calculations, which can be useful for detecting missing data.

now

Override the timestamp returned by NOW() and TODAY(). Essential for writing deterministic tests:

evaluateFormula('TEXT(TODAY())', context, {
now: new Date('2024-06-15T12:00:00Z'),
});
// Returns a consistent result regardless of when the test runs

Full Interface

// A flat record — fields and related records coexist as keys
type FormulaRecord = { [key: string]: FormulaValue | FormulaRecord };

interface FormulaContext {
record: FormulaRecord;
globals?: Record<string, FormulaRecord>;
priorRecord?: FormulaRecord;
isNew?: boolean;
isClone?: boolean;
}

interface EvaluationOptions {
treatBlanksAsZeroes?: boolean;
now?: Date;
}

type FormulaValue = number | string | boolean | Date | SfTime | GeoLocation | null;