Skip to main content

API Reference

Functions​

evaluateFormula(formula, context, options?)​

Parse and evaluate a formula in a single call. This is the simplest way to use the library.

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

const result = evaluateFormula('UPPER(LEFT(Name, 3))', { record: { Name: 'Acme Corp' } });
// "ACM"

Parameters:

ParameterTypeDescription
formulastringThe Salesforce formula string
contextFormulaContextThe record to evaluate against
optionsEvaluationOptionsOptional evaluation settings

Returns: FormulaValue — the result of evaluating the formula.


parseFormula(formula)​

Parse a formula string into an AST without evaluating it. Useful for caching parsed formulas, building linters, or inspecting formula structure.

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

const ast = parseFormula('1 + 2 * 3');
// Returns an ASTNode tree

Parameters:

ParameterTypeDescription
formulastringThe Salesforce formula string

Returns: ASTNode — the root node of the parsed AST.


createEvaluator(registry?, context?, options?)​

Create a reusable Evaluator instance. Useful when evaluating many formulas against the same context, or when using a custom function registry.

import { createEvaluator, createDefaultRegistry } from '@jetstreamapp/sf-formula-parser';

const evaluator = createEvaluator(createDefaultRegistry(), { record: { Status: 'Active', Amount: 100 } });

Parameters:

ParameterTypeDefaultDescription
registryFunctionRegistryDefault registryFunction registry to use
contextFormulaContext{ record: {} }Record context
optionsEvaluationOptionsundefinedEvaluation options

Returns: Evaluator


createDefaultRegistry()​

Create a FunctionRegistry pre-loaded with all 90+ built-in Salesforce functions.

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

const registry = createDefaultRegistry();

Returns: FunctionRegistry


extractFields(formula)​

Extract all field references from a formula string without evaluating it. Returns a deduplicated array of field names in the order they appear. Useful for determining which fields to query before evaluation.

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

const fields = extractFields('IF(Amount > 100, $User.FirstName, Name)');
// ['Amount', '$User.FirstName', 'Name']

Parameters:

ParameterTypeDescription
formulastringThe Salesforce formula string

Returns: string[] — deduplicated array of dot-joined field reference strings.


extractFieldsByCategory(formula)​

Extract and categorize field references from a formula string. Fields are grouped by their $-prefix into object fields, globals, custom metadata, custom labels, custom settings, and custom permissions.

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

const result = extractFieldsByCategory('IF($User.IsActive, $Label.Greeting & " " & Name, $Setup.Default__c.Value__c)');
// {
// objectFields: ['Name'],
// globals: { '$User': ['$User.IsActive'] },
// customMetadata: [],
// customLabels: ['$Label.Greeting'],
// customSettings: ['$Setup.Default__c.Value__c'],
// customPermissions: [],
// }

Parameters:

ParameterTypeDescription
formulastringThe Salesforce formula string

Returns: ExtractedFields — categorized field references.


formatFormula(formula, options?)​

Pretty-print a formula with consistent spacing and indentation. Formatting never changes the meaning of the formula: parentheses, comments, and string/number literals are preserved exactly, and the output always parses to the same AST as the input. Function names and keywords are upper-cased. See Formatting for the layout rules.

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

formatFormula('if(and(ispickval(StageName,"Closed Won"),Amount>100000),"Big Deal",if(Amount>50000,"Medium Deal","Small Deal"))');
// IF(
// AND(ISPICKVAL(StageName, "Closed Won"), Amount > 100000),
// "Big Deal",
// IF(Amount > 50000, "Medium Deal", "Small Deal")
// )

Parameters:

ParameterTypeDescription
formulastringThe Salesforce formula string
optionsFormatOptionsOptional printWidth / tabWidth / useTabs

Returns: string — the formatted formula (no trailing newline). Throws LexerError / ParseError for invalid formulas.


formatAST(node, options?)​

Print an ASTNode back to formula source using the same layout rules as formatFormula. Useful after transforming an AST programmatically. Since the AST carries no parentheses or comments, only the parentheses required by operator precedence are emitted and strings are double-quoted.

import { parseFormula, formatAST } from '@jetstreamapp/sf-formula-parser';

const ast = parseFormula('(a * b) + c');
formatAST(ast);
// a * b + c

Parameters:

ParameterTypeDescription
nodeASTNodeThe root AST node to print
optionsFormatOptionsOptional printWidth / tabWidth / useTabs

Returns: string — the formatted formula.


walkAST(node, visitor)​

Walk an AST tree in pre-order, calling the visitor function on each node. Useful for building custom analysis tools on top of the parsed AST.

import { parseFormula, walkAST } from '@jetstreamapp/sf-formula-parser';

const ast = parseFormula('IF(Amount > 100, Name, "default")');
const functionNames: string[] = [];

walkAST(ast, node => {
if (node.type === 'FunctionCall') {
functionNames.push(node.name);
}
});
// functionNames: ['IF']

Parameters:

ParameterTypeDescription
nodeASTNodeThe root AST node to start walking
visitor(node: ASTNode) => voidCallback invoked on each node

Classes​

FunctionRegistry​

A registry that maps function names to implementations. Case-insensitive.

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

const registry = new FunctionRegistry();

// Register a custom function
registry.register('DOUBLE', ctx => {
const val = ctx.evaluate(ctx.args[0]);
return (val as number) * 2;
});

Methods:

MethodDescription
register(name, fn)Register a function by name
get(name)Get a function by name (returns undefined if not found)
has(name)Check if a function is registered

Evaluator​

The tree-walking evaluator. Evaluates an AST node against a record context.

import { Evaluator, createDefaultRegistry } from '@jetstreamapp/sf-formula-parser';

const evaluator = new Evaluator(createDefaultRegistry(), { record: { x: 10 } });

Parser​

The Pratt parser. Converts a formula string into an AST.

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

const ast = Parser.parse('1 + 2');

Types​

FormulaValue​

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

The result type of any formula evaluation.

FormulaRecord​

type FormulaRecord = { [key: string]: FormulaValue | FormulaRecord };

A flat record where field values and related records coexist as keys — the same shape as a SOQL query result.

FormulaContext​

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

See Record Context for full documentation.

EvaluationOptions​

interface EvaluationOptions {
returnType?: FormulaReturnType; // validate result type
schema?: SchemaInput; // flat FieldSchema[] or Record<string, FieldSchema[]> for related/global schemas
treatBlanksAsZeroes?: boolean; // default: true
now?: Date; // override current time
}
OptionTypeDefaultDescription
returnTypeFormulaReturnTypeundefinedWhen provided, validates the formula result matches the declared type. Throws FormulaError on mismatch.
schemaSchemaInputundefinedFlat FieldSchema[] for current object, or Record<string, FieldSchema[]> for related/global schemas. Compatible with describeSObject().fields.
treatBlanksAsZeroesbooleantrueWhen true, null/blank numeric fields are treated as 0 and blank text fields as "". Matches the Salesforce default.
nowDatenew Date()Override the current timestamp. Useful for deterministic tests with NOW() and TODAY().

FormatOptions​

interface FormatOptions {
printWidth?: number; // default: 80 — preferred maximum line width
tabWidth?: number; // default: 2 — spaces per indent level
useTabs?: boolean; // default: false — indent with tabs
}

Options for formatFormula and formatAST. See Formatting.

OptionTypeDefaultDescription
printWidthnumber80Preferred maximum line width. Constructs that fit stay on one line; longer ones break one item per line.
tabWidthnumber2Spaces per indentation level (also the visual width of a tab when useTabs is set).
useTabsbooleanfalseIndent with tabs instead of spaces.

FormulaReturnType​

type FormulaReturnType = 'number' | 'string' | 'boolean' | 'date' | 'datetime' | 'time';

FieldSchema​

interface FieldSchema {
name: string;
type: SalesforceFieldType;
}

Intentionally compatible with the Salesforce Field type from describeSObject() — pass describe.fields directly without transformation.

SalesforceFieldType​

type SalesforceFieldType =
| 'string'
| 'boolean'
| 'int'
| 'double'
| 'date'
| 'datetime'
| 'base64'
| 'id'
| 'reference'
| 'currency'
| 'textarea'
| 'percent'
| 'phone'
| 'url'
| 'email'
| 'combobox'
| 'picklist'
| 'multipicklist'
| 'anyType'
| 'location'
| 'time'
| 'encryptedstring'
| 'address'
| 'complexvalue';

ExtractedFields​

interface ExtractedFields {
objectFields: string[]; // Regular fields (no $ prefix)
globals: Record<string, string[]>; // e.g. { '$User': ['$User.FirstName'] }
customMetadata: string[]; // $CustomMetadata.* fields
customLabels: string[]; // $Label.* fields
customSettings: string[]; // $Setup.* fields
customPermissions: string[]; // $Permission.* fields
}

Returned by extractFieldsByCategory(). The globals map uses the original $-prefix as the key (e.g., $User, $Organization, $Profile, $UserRole, $System, $Api).

ASTNode​

The discriminated union type representing parsed formula nodes. Includes types for literals, field references, function calls, binary/unary operations, and more.

SfTime​

interface SfTime {
timeInMillis: number; // 0–86400000 (ms since midnight, GMT)
}

GeoLocation​

interface GeoLocation {
latitude: number;
longitude: number;
}

Error Classes​

FormulaError​

Base error class for all formula errors.

LexerError extends FormulaError​

Thrown when the formula string contains invalid tokens. Includes line and column properties.

ParseError extends FormulaError​

Thrown when the formula has a syntax error. Includes line and column properties.

import { FormulaError, LexerError, ParseError } from '@jetstreamapp/sf-formula-parser';

try {
evaluateFormula('IF(', { record: {} });
} catch (e) {
if (e instanceof ParseError) {
console.log(e.line, e.column); // position of the error
}
}

See Error Handling for more details.

Utility Functions​

The library also exports helper functions for type checking and coercion:

FunctionDescription
isBlank(value)Check if a value is null, undefined, or empty string
isSfTime(value)Type guard for SfTime values
isGeoLocation(value)Type guard for GeoLocation values
isDate(value)Type guard for Date values
isFormulaValue(value)Type guard — true for field values, false for nested records
isFormulaRecord(value)Type guard — true for nested records
toNumber(value)Coerce a formula value to a number
toText(value)Coerce a formula value to a string
toBoolean(value)Coerce a formula value to a boolean
toFormulaType(fieldType)Map a SalesforceFieldType to an internal FormulaType