Implementation:Helicone Helicone ToFilterNode
| Knowledge Sources | |
|---|---|
| Domains | Filtering, DataLayer |
| Last Updated | 2026-02-14 06:32 GMT |
Overview
Converts new FilterAST expression trees into the legacy FilterNode binary tree format, serving as a critical adapter between the modern filter API and the existing SQL compilation pipeline.
Description
toFilterNode.ts provides the toFilterNode function that recursively transforms the new FilterExpression AST (Abstract Syntax Tree) into the legacy FilterNode format. This is a bridge module that enables incremental migration from the old filter system while maintaining full backward compatibility with the SQL filter compilation layer.
The conversion handles several key transformations:
- Operator mapping -- Maps new operator names to legacy ones (e.g.,
eqtoequals,neqtonot-equals,gte/ltepass through). - Property fields -- Detects property fields by explicit
subtype: "property"or by hyphenated column names and nests them under apropertieskey in the filter leaf. - Score fields -- Handles
subtype: "score"fields by nesting under ascoreskey. - Virtual fields -- Special-cases the
ai_gatewayvirtual column, mapping it torequest_referrerwith appropriate values. - Logical operators -- Converts
AndExpressionandOrExpressionarrays into right-recursive binaryFilterBranchtrees. - Null/empty handling -- Returns an empty
FilterLeaffor null, undefined, or "all" type filters.
The module also includes two helper functions: isPropertyField (determines if a field should be treated as a property) and getTableFromField (resolves the appropriate legacy table name from a field specification).
Usage
Use this function when you need to convert a modern FilterExpression (from the FilterAST API) into the legacy FilterNode tree format that the SQL compilation pipeline expects. This is particularly important during the migration period where both filter formats coexist.
Code Reference
Source Location
- Repository: Helicone
- File: packages/filters/toFilterNode.ts
Signature
export function toFilterNode(
filter: FilterExpression | string | null,
): FilterNode;
Import
import { toFilterNode } from "@helicone-package/filters/toFilterNode";
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| filter | string | null | Yes | A FilterExpression object, a JSON string representation, or null. Supports types: "all", "condition", "and", "or" |
Outputs
| Name | Type | Description |
|---|---|---|
| (return) | FilterNode |
A legacy FilterNode tree (either a FilterLeaf for simple conditions or a FilterBranch for composite expressions) |
Error Handling
The function throws errors in the following cases:
- Invalid JSON string input
- Filter object missing the
typeproperty - Condition expression missing
field,operator, orvalue - AND/OR expression with non-array
expressionsproperty - Unknown filter type
Internal Operator Mapping
| New Operator | Legacy Operator |
|---|---|
| eq | equals |
| neq | not-equals |
| is | equals |
| gt | gt |
| gte | gte |
| lt | lt |
| lte | lte |
| like | like |
| ilike | ilike |
| contains | contains |
Usage Examples
import { toFilterNode } from "@helicone-package/filters/toFilterNode";
// Simple condition
const filterNode = toFilterNode({
type: "condition",
field: { table: "request_response_rmt", column: "model" },
operator: "eq",
value: "gpt-4"
});
// Result: { request_response_rmt: { model: { equals: "gpt-4" } } }
// AND expression with multiple conditions
const andFilter = toFilterNode({
type: "and",
expressions: [
{
type: "condition",
field: { table: "request_response_rmt", column: "model" },
operator: "eq",
value: "gpt-4"
},
{
type: "condition",
field: { table: "request_response_rmt", column: "status" },
operator: "gte",
value: 200
}
]
});
// Result: FilterBranch { left: {...}, operator: "and", right: {...} }
// Property field conversion
const propertyFilter = toFilterNode({
type: "condition",
field: {
table: "request_response_rmt",
column: "environment",
subtype: "property",
valueMode: "value",
key: "environment"
},
operator: "eq",
value: "production"
});
// Result: { request_response_rmt: { properties: { environment: { equals: "production" } } } }
// JSON string input
const fromString = toFilterNode('{"type":"all"}');
// Result: {} (empty FilterLeaf)