88 * @see docs/spec/formula.md for complete specification
99 */
1010
11+ import { ObjectQLError , ApiErrorCode } from './api' ;
12+
1113/**
1214 * Data types that formula expressions can return
1315 */
@@ -20,6 +22,30 @@ export type FormulaDataType =
2022 | 'currency' // Monetary value
2123 | 'percent' ; // Percentage (0-100)
2224
25+ /**
26+ * Valid formula return values based on data type
27+ */
28+ export type FormulaValue =
29+ | number
30+ | string
31+ | boolean
32+ | Date
33+ | null
34+ | undefined ;
35+
36+ /**
37+ * Valid field values that can be used in formula expressions
38+ */
39+ export type FormulaFieldValue =
40+ | string
41+ | number
42+ | boolean
43+ | Date
44+ | null
45+ | undefined
46+ | FormulaFieldValue [ ]
47+ | { [ key : string ] : FormulaFieldValue } ;
48+
2349/**
2450 * Configuration for a formula field
2551 *
@@ -52,7 +78,7 @@ export interface FormulaFieldConfig {
5278 blank_as_zero ?: boolean ;
5379
5480 /** Default value to use when referenced fields are null/undefined */
55- treat_blank_as ?: any ;
81+ treat_blank_as ?: FormulaValue ;
5682
5783 /** AI-friendly context for understanding business intent */
5884 ai_context ?: FormulaAiContext ;
@@ -95,10 +121,10 @@ export interface FormulaExample {
95121 description : string ;
96122
97123 /** Input field values */
98- inputs : Record < string , any > ;
124+ inputs : Record < string , FormulaFieldValue > ;
99125
100126 /** Expected result */
101- result : any ;
127+ result : FormulaValue ;
102128
103129 /** Optional explanation of the calculation */
104130 explanation ?: string ;
@@ -112,10 +138,10 @@ export interface FormulaTestCase {
112138 description ?: string ;
113139
114140 /** Input values for the test */
115- input : Record < string , any > ;
141+ input : Record < string , FormulaFieldValue > ;
116142
117143 /** Expected output value */
118- expected : any ;
144+ expected : FormulaValue ;
119145
120146 /** Whether this test should pass or fail */
121147 should_pass ?: boolean ;
@@ -129,7 +155,7 @@ export interface FormulaTestCase {
129155 */
130156export interface FormulaContext {
131157 /** Current record data with all field values */
132- record : Record < string , any > ;
158+ record : Record < string , FormulaFieldValue > ;
133159
134160 /** System date/time variables */
135161 system : FormulaSystemVariables ;
@@ -190,15 +216,15 @@ export interface FormulaUserContext {
190216 role ?: string ;
191217
192218 /** Additional user properties */
193- [ key : string ] : any ;
219+ [ key : string ] : unknown ;
194220}
195221
196222/**
197223 * Result of formula evaluation
198224 */
199225export interface FormulaEvaluationResult {
200226 /** Computed value */
201- value : any ;
227+ value : FormulaValue ;
202228
203229 /** Data type of the result */
204230 type : FormulaDataType ;
@@ -245,18 +271,51 @@ export enum FormulaErrorType {
245271 RUNTIME_ERROR = 'RUNTIME_ERROR' ,
246272}
247273
274+ /**
275+ * Context information for formula errors
276+ */
277+ export interface FormulaErrorContext {
278+ /** The formula expression that caused the error */
279+ expression ?: string ;
280+
281+ /** Field name if applicable */
282+ field ?: string ;
283+
284+ /** Record data at time of error */
285+ record ?: Record < string , FormulaFieldValue > ;
286+
287+ /** Additional context information */
288+ [ key : string ] : unknown ;
289+ }
290+
248291/**
249292 * Custom error for formula evaluation failures
293+ * Extends ObjectQLError to maintain consistency with ObjectQL error handling
250294 */
251- export class FormulaError extends Error {
295+ export class FormulaError extends ObjectQLError {
296+ public readonly errorType : FormulaErrorType ;
297+ public readonly expression ?: string ;
298+ public readonly errorContext ?: FormulaErrorContext ;
299+
252300 constructor (
253- public type : FormulaErrorType ,
254- public message : string ,
255- public expression ?: string ,
256- public context ?: any
301+ type : FormulaErrorType ,
302+ message : string ,
303+ expression ?: string ,
304+ context ?: FormulaErrorContext
257305 ) {
258- super ( message ) ;
306+ super ( {
307+ code : type as string ,
308+ message,
309+ details : {
310+ formula_error_type : type ,
311+ expression,
312+ ...context
313+ }
314+ } ) ;
259315 this . name = 'FormulaError' ;
316+ this . errorType = type ;
317+ this . expression = expression ;
318+ this . errorContext = context ;
260319 }
261320}
262321
@@ -347,6 +406,12 @@ export interface FormulaExecutionStats {
347406 common_errors ?: Record < FormulaErrorType , number > ;
348407}
349408
409+ /**
410+ * Type for custom formula functions
411+ * These functions can be registered in the formula engine for use in expressions
412+ */
413+ export type FormulaCustomFunction = ( ...args : FormulaFieldValue [ ] ) => FormulaValue ;
414+
350415/**
351416 * Configuration for formula engine
352417 */
@@ -364,7 +429,7 @@ export interface FormulaEngineConfig {
364429 enable_monitoring ?: boolean ;
365430
366431 /** Custom function library */
367- custom_functions ?: Record < string , Function > ;
432+ custom_functions ?: Record < string , FormulaCustomFunction > ;
368433
369434 /** Sandbox configuration */
370435 sandbox ?: {
0 commit comments