@fogpipe/forma-core 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,258 @@
1
+ import { m as Forma, t as CalculationResult, n as VisibilityResult, o as RequiredFieldsResult, p as EnabledResult, r as ValidationResult, q as FieldError } from '../types-Bs3CG9JZ.js';
2
+
3
+ /**
4
+ * Calculation Engine
5
+ *
6
+ * Evaluates computed fields based on form data.
7
+ * Computed values are derived from form data using FEEL expressions.
8
+ */
9
+
10
+ /**
11
+ * Calculate all computed values from form data
12
+ *
13
+ * Evaluates each computed field's FEEL expression and returns the results.
14
+ * Errors are collected rather than thrown, allowing partial results.
15
+ *
16
+ * @param data - Current form data
17
+ * @param spec - Form specification with computed fields
18
+ * @returns Computed values and any calculation errors
19
+ *
20
+ * @example
21
+ * const spec = {
22
+ * computed: {
23
+ * bmi: {
24
+ * expression: "weight / (height / 100) ** 2",
25
+ * label: "BMI",
26
+ * format: "decimal(1)"
27
+ * },
28
+ * isObese: {
29
+ * expression: "$computed.bmi >= 30"
30
+ * }
31
+ * }
32
+ * };
33
+ *
34
+ * const result = calculate({ weight: 85, height: 175 }, spec);
35
+ * // => { values: { bmi: 27.76, isObese: false }, errors: [] }
36
+ */
37
+ declare function calculate(data: Record<string, unknown>, spec: Forma): Record<string, unknown>;
38
+ /**
39
+ * Calculate computed values with error reporting
40
+ *
41
+ * Same as calculate() but also returns any errors that occurred.
42
+ *
43
+ * @param data - Current form data
44
+ * @param spec - Form specification
45
+ * @returns Values and errors
46
+ */
47
+ declare function calculateWithErrors(data: Record<string, unknown>, spec: Forma): CalculationResult;
48
+ /**
49
+ * Get a computed value formatted according to its format specification
50
+ *
51
+ * @param fieldName - Name of the computed field
52
+ * @param data - Current form data
53
+ * @param spec - Form specification
54
+ * @returns Formatted string or null if not displayable
55
+ */
56
+ declare function getFormattedValue(fieldName: string, data: Record<string, unknown>, spec: Forma): string | null;
57
+ /**
58
+ * Calculate a single computed field
59
+ *
60
+ * @param fieldName - Name of the computed field
61
+ * @param data - Current form data
62
+ * @param spec - Form specification
63
+ * @returns Computed value or null if calculation failed
64
+ */
65
+ declare function calculateField(fieldName: string, data: Record<string, unknown>, spec: Forma): unknown;
66
+
67
+ /**
68
+ * Visibility Engine
69
+ *
70
+ * Determines which fields should be visible based on form data
71
+ * and Forma visibility rules.
72
+ */
73
+
74
+ interface VisibilityOptions {
75
+ /** Pre-calculated computed values (avoids recalculation) */
76
+ computed?: Record<string, unknown>;
77
+ }
78
+ /**
79
+ * Determine visibility for all fields in a form
80
+ *
81
+ * Returns a map of field paths to boolean visibility states.
82
+ * Fields without visibleWhen expressions are always visible.
83
+ *
84
+ * @param data - Current form data
85
+ * @param spec - Form specification
86
+ * @param options - Optional pre-calculated computed values
87
+ * @returns Map of field paths to visibility states
88
+ *
89
+ * @example
90
+ * const visibility = getVisibility(
91
+ * { age: 21, hasLicense: true },
92
+ * forma
93
+ * );
94
+ * // => { age: true, hasLicense: true, vehicleType: true, ... }
95
+ */
96
+ declare function getVisibility(data: Record<string, unknown>, spec: Forma, options?: VisibilityOptions): VisibilityResult;
97
+ /**
98
+ * Check if a single field is visible
99
+ *
100
+ * Useful for checking visibility of one field without computing all.
101
+ *
102
+ * @param fieldPath - Field path to check
103
+ * @param data - Current form data
104
+ * @param spec - Form specification
105
+ * @param options - Optional pre-calculated computed values
106
+ * @returns True if the field is visible
107
+ */
108
+ declare function isFieldVisible(fieldPath: string, data: Record<string, unknown>, spec: Forma, options?: VisibilityOptions): boolean;
109
+ /**
110
+ * Determine which pages are visible in a wizard form
111
+ *
112
+ * @param data - Current form data
113
+ * @param spec - Form specification with pages
114
+ * @param options - Optional pre-calculated computed values
115
+ * @returns Map of page IDs to visibility states
116
+ */
117
+ declare function getPageVisibility(data: Record<string, unknown>, spec: Forma, options?: VisibilityOptions): Record<string, boolean>;
118
+
119
+ /**
120
+ * Required Fields Engine
121
+ *
122
+ * Determines which fields are currently required based on
123
+ * conditional requiredWhen expressions and schema required array.
124
+ */
125
+
126
+ interface RequiredOptions {
127
+ /** Pre-calculated computed values */
128
+ computed?: Record<string, unknown>;
129
+ }
130
+ /**
131
+ * Determine which fields are currently required
132
+ *
133
+ * Returns a map of field paths to boolean required states.
134
+ * Evaluates requiredWhen expressions for conditional requirements.
135
+ *
136
+ * @param data - Current form data
137
+ * @param spec - Form specification
138
+ * @param options - Optional pre-calculated computed values
139
+ * @returns Map of field paths to required states
140
+ *
141
+ * @example
142
+ * const required = getRequired(
143
+ * { hasInsurance: true },
144
+ * forma
145
+ * );
146
+ * // => { hasInsurance: true, insuranceProvider: true, policyNumber: true }
147
+ */
148
+ declare function getRequired(data: Record<string, unknown>, spec: Forma, options?: RequiredOptions): RequiredFieldsResult;
149
+ /**
150
+ * Check if a single field is currently required
151
+ *
152
+ * @param fieldPath - Path to the field
153
+ * @param data - Current form data
154
+ * @param spec - Form specification
155
+ * @returns True if the field is required
156
+ */
157
+ declare function isRequired(fieldPath: string, data: Record<string, unknown>, spec: Forma): boolean;
158
+
159
+ /**
160
+ * Enabled Fields Engine
161
+ *
162
+ * Determines which fields are currently enabled (editable) based on
163
+ * conditional enabledWhen expressions.
164
+ */
165
+
166
+ interface EnabledOptions {
167
+ /** Pre-calculated computed values */
168
+ computed?: Record<string, unknown>;
169
+ }
170
+ /**
171
+ * Determine which fields are currently enabled (editable)
172
+ *
173
+ * Returns a map of field paths to boolean enabled states.
174
+ * Fields without enabledWhen expressions are always enabled.
175
+ *
176
+ * @param data - Current form data
177
+ * @param spec - Form specification
178
+ * @param options - Optional pre-calculated computed values
179
+ * @returns Map of field paths to enabled states
180
+ *
181
+ * @example
182
+ * const enabled = getEnabled(
183
+ * { isLocked: true },
184
+ * forma
185
+ * );
186
+ * // => { isLocked: true, lockedField: false, ... }
187
+ */
188
+ declare function getEnabled(data: Record<string, unknown>, spec: Forma, options?: EnabledOptions): EnabledResult;
189
+ /**
190
+ * Check if a single field is currently enabled
191
+ *
192
+ * @param fieldPath - Path to the field
193
+ * @param data - Current form data
194
+ * @param spec - Form specification
195
+ * @returns True if the field is enabled
196
+ */
197
+ declare function isEnabled(fieldPath: string, data: Record<string, unknown>, spec: Forma): boolean;
198
+
199
+ /**
200
+ * Validation Engine
201
+ *
202
+ * Validates form data against Forma rules including:
203
+ * - JSON Schema type validation
204
+ * - Required field validation (with conditional requiredWhen)
205
+ * - Custom FEEL validation rules
206
+ * - Array item validation
207
+ */
208
+
209
+ interface ValidateOptions {
210
+ /** Pre-calculated computed values */
211
+ computed?: Record<string, unknown>;
212
+ /** Pre-calculated visibility */
213
+ visibility?: Record<string, boolean>;
214
+ /** Only validate visible fields (default: true) */
215
+ onlyVisible?: boolean;
216
+ }
217
+ /**
218
+ * Validate form data against a Forma
219
+ *
220
+ * Performs comprehensive validation including:
221
+ * - Required field checks (respecting conditional requiredWhen)
222
+ * - JSON Schema type validation
223
+ * - Custom FEEL validation rules
224
+ * - Array min/max items validation
225
+ * - Array item field validation
226
+ *
227
+ * By default, only visible fields are validated.
228
+ *
229
+ * @param data - Current form data
230
+ * @param spec - Form specification
231
+ * @param options - Validation options
232
+ * @returns Validation result with valid flag and errors array
233
+ *
234
+ * @example
235
+ * const result = validate(
236
+ * { name: "", age: 15 },
237
+ * forma
238
+ * );
239
+ * // => {
240
+ * // valid: false,
241
+ * // errors: [
242
+ * // { field: "name", message: "Name is required", severity: "error" },
243
+ * // { field: "age", message: "Must be 18 or older", severity: "error" }
244
+ * // ]
245
+ * // }
246
+ */
247
+ declare function validate(data: Record<string, unknown>, spec: Forma, options?: ValidateOptions): ValidationResult;
248
+ /**
249
+ * Validate a single field
250
+ *
251
+ * @param fieldPath - Path to the field
252
+ * @param data - Current form data
253
+ * @param spec - Form specification
254
+ * @returns Array of errors for this field
255
+ */
256
+ declare function validateSingleField(fieldPath: string, data: Record<string, unknown>, spec: Forma): FieldError[];
257
+
258
+ export { type EnabledOptions, type RequiredOptions, type ValidateOptions, type VisibilityOptions, calculate, calculateField, calculateWithErrors, getEnabled, getFormattedValue, getPageVisibility, getRequired, getVisibility, isEnabled, isFieldVisible, isRequired, validate, validateSingleField };
@@ -0,0 +1,32 @@
1
+ import {
2
+ calculate,
3
+ calculateField,
4
+ calculateWithErrors,
5
+ getEnabled,
6
+ getFormattedValue,
7
+ getPageVisibility,
8
+ getRequired,
9
+ getVisibility,
10
+ isEnabled,
11
+ isFieldVisible,
12
+ isRequired,
13
+ validate,
14
+ validateSingleField
15
+ } from "../chunk-IRLYWN3R.js";
16
+ import "../chunk-QTLXVG6P.js";
17
+ export {
18
+ calculate,
19
+ calculateField,
20
+ calculateWithErrors,
21
+ getEnabled,
22
+ getFormattedValue,
23
+ getPageVisibility,
24
+ getRequired,
25
+ getVisibility,
26
+ isEnabled,
27
+ isFieldVisible,
28
+ isRequired,
29
+ validate,
30
+ validateSingleField
31
+ };
32
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/feel/index.ts
21
+ var feel_exports = {};
22
+ __export(feel_exports, {
23
+ evaluate: () => evaluate,
24
+ evaluateBoolean: () => evaluateBoolean,
25
+ evaluateBooleanBatch: () => evaluateBooleanBatch,
26
+ evaluateNumber: () => evaluateNumber,
27
+ evaluateString: () => evaluateString,
28
+ isValidExpression: () => isValidExpression,
29
+ validateExpression: () => validateExpression
30
+ });
31
+ module.exports = __toCommonJS(feel_exports);
32
+ var import_feelin = require("feelin");
33
+ function buildFeelContext(ctx) {
34
+ const feelContext = {
35
+ // Spread form data directly so fields are accessible by name
36
+ ...ctx.data
37
+ };
38
+ if (ctx.computed) {
39
+ feelContext["computed"] = ctx.computed;
40
+ }
41
+ if (ctx.referenceData) {
42
+ feelContext["ref"] = ctx.referenceData;
43
+ }
44
+ if (ctx.item !== void 0) {
45
+ feelContext["item"] = ctx.item;
46
+ }
47
+ if (ctx.itemIndex !== void 0) {
48
+ feelContext["itemIndex"] = ctx.itemIndex;
49
+ }
50
+ if (ctx.value !== void 0) {
51
+ feelContext["value"] = ctx.value;
52
+ }
53
+ return feelContext;
54
+ }
55
+ function evaluate(expression, context) {
56
+ try {
57
+ const feelContext = buildFeelContext(context);
58
+ const result = (0, import_feelin.evaluate)(expression, feelContext);
59
+ return {
60
+ success: true,
61
+ value: result
62
+ };
63
+ } catch (error) {
64
+ return {
65
+ success: false,
66
+ error: error instanceof Error ? error.message : String(error),
67
+ expression
68
+ };
69
+ }
70
+ }
71
+ function evaluateBoolean(expression, context) {
72
+ const result = evaluate(expression, context);
73
+ if (!result.success) {
74
+ console.warn(
75
+ `FEEL expression error: ${result.error}
76
+ Expression: ${result.expression}`
77
+ );
78
+ return false;
79
+ }
80
+ if (result.value === null || result.value === void 0) {
81
+ return false;
82
+ }
83
+ if (typeof result.value !== "boolean") {
84
+ console.warn(
85
+ `FEEL expression did not return boolean: ${expression}
86
+ Got: ${typeof result.value}`
87
+ );
88
+ return false;
89
+ }
90
+ return result.value;
91
+ }
92
+ function evaluateNumber(expression, context) {
93
+ const result = evaluate(expression, context);
94
+ if (!result.success) {
95
+ console.warn(
96
+ `FEEL expression error: ${result.error}
97
+ Expression: ${result.expression}`
98
+ );
99
+ return null;
100
+ }
101
+ if (typeof result.value !== "number") {
102
+ console.warn(
103
+ `FEEL expression did not return number: ${expression}
104
+ Got: ${typeof result.value}`
105
+ );
106
+ return null;
107
+ }
108
+ return result.value;
109
+ }
110
+ function evaluateString(expression, context) {
111
+ const result = evaluate(expression, context);
112
+ if (!result.success) {
113
+ console.warn(
114
+ `FEEL expression error: ${result.error}
115
+ Expression: ${result.expression}`
116
+ );
117
+ return null;
118
+ }
119
+ if (typeof result.value !== "string") {
120
+ console.warn(
121
+ `FEEL expression did not return string: ${expression}
122
+ Got: ${typeof result.value}`
123
+ );
124
+ return null;
125
+ }
126
+ return result.value;
127
+ }
128
+ function evaluateBooleanBatch(expressions, context) {
129
+ const results = {};
130
+ for (const [key, expression] of Object.entries(expressions)) {
131
+ results[key] = evaluateBoolean(expression, context);
132
+ }
133
+ return results;
134
+ }
135
+ function isValidExpression(expression) {
136
+ try {
137
+ (0, import_feelin.evaluate)(expression, {});
138
+ return true;
139
+ } catch {
140
+ return false;
141
+ }
142
+ }
143
+ function validateExpression(expression) {
144
+ try {
145
+ (0, import_feelin.evaluate)(expression, {});
146
+ return null;
147
+ } catch (error) {
148
+ const message = error instanceof Error ? error.message : String(error);
149
+ if (message.includes("parse") || message.includes("syntax")) {
150
+ return message;
151
+ }
152
+ return null;
153
+ }
154
+ }
155
+ // Annotate the CommonJS export names for ESM import in node:
156
+ 0 && (module.exports = {
157
+ evaluate,
158
+ evaluateBoolean,
159
+ evaluateBooleanBatch,
160
+ evaluateNumber,
161
+ evaluateString,
162
+ isValidExpression,
163
+ validateExpression
164
+ });
165
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/feel/index.ts"],"sourcesContent":["/**\n * FEEL Expression Evaluator\n *\n * Wraps the feelin library to provide FEEL expression evaluation\n * with Forma context conventions.\n *\n * Context variable conventions:\n * - `fieldName` - Direct field value access\n * - `computed.name` - Computed value access\n * - `ref.path` - Reference data lookup (external lookup tables)\n * - `item.fieldName` - Array item field access (within array context)\n * - `itemIndex` - Current array item index (0-based)\n * - `value` - Current field value (in validation expressions)\n */\n\nimport { evaluate as feelinEvaluate } from \"feelin\";\nimport type { EvaluationContext, FEELExpression } from \"../types.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface EvaluateResult<T = unknown> {\n success: true;\n value: T;\n}\n\nexport interface EvaluateError {\n success: false;\n error: string;\n expression: string;\n}\n\nexport type EvaluationOutcome<T = unknown> = EvaluateResult<T> | EvaluateError;\n\n// ============================================================================\n// Context Building\n// ============================================================================\n\n/**\n * Build the FEEL evaluation context from our EvaluationContext\n *\n * Maps our context conventions to feelin context format:\n * - Form data fields are spread directly\n * - computed becomes an object (accessed as computed.fieldName)\n * - ref becomes an object for reference data (accessed as ref.path.to.data)\n * - item becomes an object for array context (accessed as item.fieldName)\n * - itemIndex is a number for array context\n * - value is the current field value\n */\nfunction buildFeelContext(ctx: EvaluationContext): Record<string, unknown> {\n const feelContext: Record<string, unknown> = {\n // Spread form data directly so fields are accessible by name\n ...ctx.data,\n };\n\n // Add computed values under 'computed' (accessed as computed.fieldName)\n if (ctx.computed) {\n feelContext[\"computed\"] = ctx.computed;\n }\n\n // Add reference data under 'ref' (accessed as ref.path.to.data)\n if (ctx.referenceData) {\n feelContext[\"ref\"] = ctx.referenceData;\n }\n\n // Add array item context (accessed as item.fieldName)\n if (ctx.item !== undefined) {\n feelContext[\"item\"] = ctx.item;\n }\n\n // Add array index\n if (ctx.itemIndex !== undefined) {\n feelContext[\"itemIndex\"] = ctx.itemIndex;\n }\n\n // Add current field value for validation expressions\n if (ctx.value !== undefined) {\n feelContext[\"value\"] = ctx.value;\n }\n\n return feelContext;\n}\n\n// ============================================================================\n// Expression Evaluation\n// ============================================================================\n\n/**\n * Evaluate a FEEL expression and return the result\n *\n * @param expression - FEEL expression string\n * @param context - Evaluation context with form data, computed values, etc.\n * @returns Evaluation outcome with success/value or error\n *\n * @example\n * // Simple field comparison\n * evaluate(\"age >= 18\", { data: { age: 21 } })\n * // => { success: true, value: true }\n *\n * @example\n * // Computed value reference\n * evaluate(\"computed.bmi > 30\", { data: {}, computed: { bmi: 32.5 } })\n * // => { success: true, value: true }\n *\n * @example\n * // Array item context\n * evaluate(\"item.frequency = \\\"daily\\\"\", { data: {}, item: { frequency: \"daily\" } })\n * // => { success: true, value: true }\n */\nexport function evaluate<T = unknown>(\n expression: FEELExpression,\n context: EvaluationContext\n): EvaluationOutcome<T> {\n try {\n const feelContext = buildFeelContext(context);\n const result = feelinEvaluate(expression, feelContext);\n return {\n success: true,\n value: result as T,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n expression,\n };\n }\n}\n\n/**\n * Evaluate a FEEL expression expecting a boolean result\n *\n * Used for visibility, required, and enabled conditions.\n * Returns false on error or non-boolean result for safety.\n *\n * @param expression - FEEL expression that should return boolean\n * @param context - Evaluation context\n * @returns Boolean result (false on error)\n */\nexport function evaluateBoolean(\n expression: FEELExpression,\n context: EvaluationContext\n): boolean {\n const result = evaluate<boolean>(expression, context);\n\n if (!result.success) {\n console.warn(\n `FEEL expression error: ${result.error}\\nExpression: ${result.expression}`\n );\n return false;\n }\n\n // FEEL uses three-valued logic where comparisons with null return null.\n // For form visibility/required/enabled conditions, we treat null as false.\n if (result.value === null || result.value === undefined) {\n return false;\n }\n\n if (typeof result.value !== \"boolean\") {\n console.warn(\n `FEEL expression did not return boolean: ${expression}\\nGot: ${typeof result.value}`\n );\n return false;\n }\n\n return result.value;\n}\n\n/**\n * Evaluate a FEEL expression expecting a numeric result\n *\n * Used for computed values that return numbers.\n *\n * @param expression - FEEL expression that should return number\n * @param context - Evaluation context\n * @returns Numeric result or null on error\n */\nexport function evaluateNumber(\n expression: FEELExpression,\n context: EvaluationContext\n): number | null {\n const result = evaluate<number>(expression, context);\n\n if (!result.success) {\n console.warn(\n `FEEL expression error: ${result.error}\\nExpression: ${result.expression}`\n );\n return null;\n }\n\n if (typeof result.value !== \"number\") {\n console.warn(\n `FEEL expression did not return number: ${expression}\\nGot: ${typeof result.value}`\n );\n return null;\n }\n\n return result.value;\n}\n\n/**\n * Evaluate a FEEL expression expecting a string result\n *\n * @param expression - FEEL expression that should return string\n * @param context - Evaluation context\n * @returns String result or null on error\n */\nexport function evaluateString(\n expression: FEELExpression,\n context: EvaluationContext\n): string | null {\n const result = evaluate<string>(expression, context);\n\n if (!result.success) {\n console.warn(\n `FEEL expression error: ${result.error}\\nExpression: ${result.expression}`\n );\n return null;\n }\n\n if (typeof result.value !== \"string\") {\n console.warn(\n `FEEL expression did not return string: ${expression}\\nGot: ${typeof result.value}`\n );\n return null;\n }\n\n return result.value;\n}\n\n// ============================================================================\n// Batch Evaluation\n// ============================================================================\n\n/**\n * Evaluate multiple FEEL expressions at once\n *\n * Useful for evaluating all visibility conditions in a form.\n *\n * @param expressions - Map of field names to FEEL expressions\n * @param context - Evaluation context\n * @returns Map of field names to boolean results\n */\nexport function evaluateBooleanBatch(\n expressions: Record<string, FEELExpression>,\n context: EvaluationContext\n): Record<string, boolean> {\n const results: Record<string, boolean> = {};\n\n for (const [key, expression] of Object.entries(expressions)) {\n results[key] = evaluateBoolean(expression, context);\n }\n\n return results;\n}\n\n// ============================================================================\n// Expression Validation\n// ============================================================================\n\n/**\n * Check if a FEEL expression is syntactically valid\n *\n * @param expression - FEEL expression to validate\n * @returns True if the expression can be parsed\n */\nexport function isValidExpression(expression: FEELExpression): boolean {\n try {\n // Try to evaluate with empty context - we just want to check parsing\n feelinEvaluate(expression, {});\n return true;\n } catch {\n // Expression failed to parse or evaluate\n return false;\n }\n}\n\n/**\n * Validate a FEEL expression and return any parsing errors\n *\n * @param expression - FEEL expression to validate\n * @returns Null if valid, error message if invalid\n */\nexport function validateExpression(expression: FEELExpression): string | null {\n try {\n // Evaluate with minimal context to catch parse errors\n feelinEvaluate(expression, {});\n return null;\n } catch (error) {\n // Only return actual parsing errors, not runtime errors\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes(\"parse\") || message.includes(\"syntax\")) {\n return message;\n }\n // Runtime errors (missing variables, etc.) are OK for validation\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeA,oBAA2C;AAmC3C,SAAS,iBAAiB,KAAiD;AACzE,QAAM,cAAuC;AAAA;AAAA,IAE3C,GAAG,IAAI;AAAA,EACT;AAGA,MAAI,IAAI,UAAU;AAChB,gBAAY,UAAU,IAAI,IAAI;AAAA,EAChC;AAGA,MAAI,IAAI,eAAe;AACrB,gBAAY,KAAK,IAAI,IAAI;AAAA,EAC3B;AAGA,MAAI,IAAI,SAAS,QAAW;AAC1B,gBAAY,MAAM,IAAI,IAAI;AAAA,EAC5B;AAGA,MAAI,IAAI,cAAc,QAAW;AAC/B,gBAAY,WAAW,IAAI,IAAI;AAAA,EACjC;AAGA,MAAI,IAAI,UAAU,QAAW;AAC3B,gBAAY,OAAO,IAAI,IAAI;AAAA,EAC7B;AAEA,SAAO;AACT;AA4BO,SAAS,SACd,YACA,SACsB;AACtB,MAAI;AACF,UAAM,cAAc,iBAAiB,OAAO;AAC5C,UAAM,aAAS,cAAAA,UAAe,YAAY,WAAW;AACrD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAAA,EACF,SAAS,OAAO;AACd,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AACF;AAYO,SAAS,gBACd,YACA,SACS;AACT,QAAM,SAAS,SAAkB,YAAY,OAAO;AAEpD,MAAI,CAAC,OAAO,SAAS;AACnB,YAAQ;AAAA,MACN,0BAA0B,OAAO,KAAK;AAAA,cAAiB,OAAO,UAAU;AAAA,IAC1E;AACA,WAAO;AAAA,EACT;AAIA,MAAI,OAAO,UAAU,QAAQ,OAAO,UAAU,QAAW;AACvD,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,OAAO,UAAU,WAAW;AACrC,YAAQ;AAAA,MACN,2CAA2C,UAAU;AAAA,OAAU,OAAO,OAAO,KAAK;AAAA,IACpF;AACA,WAAO;AAAA,EACT;AAEA,SAAO,OAAO;AAChB;AAWO,SAAS,eACd,YACA,SACe;AACf,QAAM,SAAS,SAAiB,YAAY,OAAO;AAEnD,MAAI,CAAC,OAAO,SAAS;AACnB,YAAQ;AAAA,MACN,0BAA0B,OAAO,KAAK;AAAA,cAAiB,OAAO,UAAU;AAAA,IAC1E;AACA,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,OAAO,UAAU,UAAU;AACpC,YAAQ;AAAA,MACN,0CAA0C,UAAU;AAAA,OAAU,OAAO,OAAO,KAAK;AAAA,IACnF;AACA,WAAO;AAAA,EACT;AAEA,SAAO,OAAO;AAChB;AASO,SAAS,eACd,YACA,SACe;AACf,QAAM,SAAS,SAAiB,YAAY,OAAO;AAEnD,MAAI,CAAC,OAAO,SAAS;AACnB,YAAQ;AAAA,MACN,0BAA0B,OAAO,KAAK;AAAA,cAAiB,OAAO,UAAU;AAAA,IAC1E;AACA,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,OAAO,UAAU,UAAU;AACpC,YAAQ;AAAA,MACN,0CAA0C,UAAU;AAAA,OAAU,OAAO,OAAO,KAAK;AAAA,IACnF;AACA,WAAO;AAAA,EACT;AAEA,SAAO,OAAO;AAChB;AAeO,SAAS,qBACd,aACA,SACyB;AACzB,QAAM,UAAmC,CAAC;AAE1C,aAAW,CAAC,KAAK,UAAU,KAAK,OAAO,QAAQ,WAAW,GAAG;AAC3D,YAAQ,GAAG,IAAI,gBAAgB,YAAY,OAAO;AAAA,EACpD;AAEA,SAAO;AACT;AAYO,SAAS,kBAAkB,YAAqC;AACrE,MAAI;AAEF,sBAAAA,UAAe,YAAY,CAAC,CAAC;AAC7B,WAAO;AAAA,EACT,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AAQO,SAAS,mBAAmB,YAA2C;AAC5E,MAAI;AAEF,sBAAAA,UAAe,YAAY,CAAC,CAAC;AAC7B,WAAO;AAAA,EACT,SAAS,OAAO;AAEd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,QAAI,QAAQ,SAAS,OAAO,KAAK,QAAQ,SAAS,QAAQ,GAAG;AAC3D,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AACF;","names":["feelinEvaluate"]}
@@ -0,0 +1,105 @@
1
+ import { F as FEELExpression, E as EvaluationContext } from '../types-Bs3CG9JZ.cjs';
2
+
3
+ /**
4
+ * FEEL Expression Evaluator
5
+ *
6
+ * Wraps the feelin library to provide FEEL expression evaluation
7
+ * with Forma context conventions.
8
+ *
9
+ * Context variable conventions:
10
+ * - `fieldName` - Direct field value access
11
+ * - `computed.name` - Computed value access
12
+ * - `ref.path` - Reference data lookup (external lookup tables)
13
+ * - `item.fieldName` - Array item field access (within array context)
14
+ * - `itemIndex` - Current array item index (0-based)
15
+ * - `value` - Current field value (in validation expressions)
16
+ */
17
+
18
+ interface EvaluateResult<T = unknown> {
19
+ success: true;
20
+ value: T;
21
+ }
22
+ interface EvaluateError {
23
+ success: false;
24
+ error: string;
25
+ expression: string;
26
+ }
27
+ type EvaluationOutcome<T = unknown> = EvaluateResult<T> | EvaluateError;
28
+ /**
29
+ * Evaluate a FEEL expression and return the result
30
+ *
31
+ * @param expression - FEEL expression string
32
+ * @param context - Evaluation context with form data, computed values, etc.
33
+ * @returns Evaluation outcome with success/value or error
34
+ *
35
+ * @example
36
+ * // Simple field comparison
37
+ * evaluate("age >= 18", { data: { age: 21 } })
38
+ * // => { success: true, value: true }
39
+ *
40
+ * @example
41
+ * // Computed value reference
42
+ * evaluate("computed.bmi > 30", { data: {}, computed: { bmi: 32.5 } })
43
+ * // => { success: true, value: true }
44
+ *
45
+ * @example
46
+ * // Array item context
47
+ * evaluate("item.frequency = \"daily\"", { data: {}, item: { frequency: "daily" } })
48
+ * // => { success: true, value: true }
49
+ */
50
+ declare function evaluate<T = unknown>(expression: FEELExpression, context: EvaluationContext): EvaluationOutcome<T>;
51
+ /**
52
+ * Evaluate a FEEL expression expecting a boolean result
53
+ *
54
+ * Used for visibility, required, and enabled conditions.
55
+ * Returns false on error or non-boolean result for safety.
56
+ *
57
+ * @param expression - FEEL expression that should return boolean
58
+ * @param context - Evaluation context
59
+ * @returns Boolean result (false on error)
60
+ */
61
+ declare function evaluateBoolean(expression: FEELExpression, context: EvaluationContext): boolean;
62
+ /**
63
+ * Evaluate a FEEL expression expecting a numeric result
64
+ *
65
+ * Used for computed values that return numbers.
66
+ *
67
+ * @param expression - FEEL expression that should return number
68
+ * @param context - Evaluation context
69
+ * @returns Numeric result or null on error
70
+ */
71
+ declare function evaluateNumber(expression: FEELExpression, context: EvaluationContext): number | null;
72
+ /**
73
+ * Evaluate a FEEL expression expecting a string result
74
+ *
75
+ * @param expression - FEEL expression that should return string
76
+ * @param context - Evaluation context
77
+ * @returns String result or null on error
78
+ */
79
+ declare function evaluateString(expression: FEELExpression, context: EvaluationContext): string | null;
80
+ /**
81
+ * Evaluate multiple FEEL expressions at once
82
+ *
83
+ * Useful for evaluating all visibility conditions in a form.
84
+ *
85
+ * @param expressions - Map of field names to FEEL expressions
86
+ * @param context - Evaluation context
87
+ * @returns Map of field names to boolean results
88
+ */
89
+ declare function evaluateBooleanBatch(expressions: Record<string, FEELExpression>, context: EvaluationContext): Record<string, boolean>;
90
+ /**
91
+ * Check if a FEEL expression is syntactically valid
92
+ *
93
+ * @param expression - FEEL expression to validate
94
+ * @returns True if the expression can be parsed
95
+ */
96
+ declare function isValidExpression(expression: FEELExpression): boolean;
97
+ /**
98
+ * Validate a FEEL expression and return any parsing errors
99
+ *
100
+ * @param expression - FEEL expression to validate
101
+ * @returns Null if valid, error message if invalid
102
+ */
103
+ declare function validateExpression(expression: FEELExpression): string | null;
104
+
105
+ export { type EvaluateError, type EvaluateResult, type EvaluationOutcome, evaluate, evaluateBoolean, evaluateBooleanBatch, evaluateNumber, evaluateString, isValidExpression, validateExpression };
@@ -0,0 +1,105 @@
1
+ import { F as FEELExpression, E as EvaluationContext } from '../types-Bs3CG9JZ.js';
2
+
3
+ /**
4
+ * FEEL Expression Evaluator
5
+ *
6
+ * Wraps the feelin library to provide FEEL expression evaluation
7
+ * with Forma context conventions.
8
+ *
9
+ * Context variable conventions:
10
+ * - `fieldName` - Direct field value access
11
+ * - `computed.name` - Computed value access
12
+ * - `ref.path` - Reference data lookup (external lookup tables)
13
+ * - `item.fieldName` - Array item field access (within array context)
14
+ * - `itemIndex` - Current array item index (0-based)
15
+ * - `value` - Current field value (in validation expressions)
16
+ */
17
+
18
+ interface EvaluateResult<T = unknown> {
19
+ success: true;
20
+ value: T;
21
+ }
22
+ interface EvaluateError {
23
+ success: false;
24
+ error: string;
25
+ expression: string;
26
+ }
27
+ type EvaluationOutcome<T = unknown> = EvaluateResult<T> | EvaluateError;
28
+ /**
29
+ * Evaluate a FEEL expression and return the result
30
+ *
31
+ * @param expression - FEEL expression string
32
+ * @param context - Evaluation context with form data, computed values, etc.
33
+ * @returns Evaluation outcome with success/value or error
34
+ *
35
+ * @example
36
+ * // Simple field comparison
37
+ * evaluate("age >= 18", { data: { age: 21 } })
38
+ * // => { success: true, value: true }
39
+ *
40
+ * @example
41
+ * // Computed value reference
42
+ * evaluate("computed.bmi > 30", { data: {}, computed: { bmi: 32.5 } })
43
+ * // => { success: true, value: true }
44
+ *
45
+ * @example
46
+ * // Array item context
47
+ * evaluate("item.frequency = \"daily\"", { data: {}, item: { frequency: "daily" } })
48
+ * // => { success: true, value: true }
49
+ */
50
+ declare function evaluate<T = unknown>(expression: FEELExpression, context: EvaluationContext): EvaluationOutcome<T>;
51
+ /**
52
+ * Evaluate a FEEL expression expecting a boolean result
53
+ *
54
+ * Used for visibility, required, and enabled conditions.
55
+ * Returns false on error or non-boolean result for safety.
56
+ *
57
+ * @param expression - FEEL expression that should return boolean
58
+ * @param context - Evaluation context
59
+ * @returns Boolean result (false on error)
60
+ */
61
+ declare function evaluateBoolean(expression: FEELExpression, context: EvaluationContext): boolean;
62
+ /**
63
+ * Evaluate a FEEL expression expecting a numeric result
64
+ *
65
+ * Used for computed values that return numbers.
66
+ *
67
+ * @param expression - FEEL expression that should return number
68
+ * @param context - Evaluation context
69
+ * @returns Numeric result or null on error
70
+ */
71
+ declare function evaluateNumber(expression: FEELExpression, context: EvaluationContext): number | null;
72
+ /**
73
+ * Evaluate a FEEL expression expecting a string result
74
+ *
75
+ * @param expression - FEEL expression that should return string
76
+ * @param context - Evaluation context
77
+ * @returns String result or null on error
78
+ */
79
+ declare function evaluateString(expression: FEELExpression, context: EvaluationContext): string | null;
80
+ /**
81
+ * Evaluate multiple FEEL expressions at once
82
+ *
83
+ * Useful for evaluating all visibility conditions in a form.
84
+ *
85
+ * @param expressions - Map of field names to FEEL expressions
86
+ * @param context - Evaluation context
87
+ * @returns Map of field names to boolean results
88
+ */
89
+ declare function evaluateBooleanBatch(expressions: Record<string, FEELExpression>, context: EvaluationContext): Record<string, boolean>;
90
+ /**
91
+ * Check if a FEEL expression is syntactically valid
92
+ *
93
+ * @param expression - FEEL expression to validate
94
+ * @returns True if the expression can be parsed
95
+ */
96
+ declare function isValidExpression(expression: FEELExpression): boolean;
97
+ /**
98
+ * Validate a FEEL expression and return any parsing errors
99
+ *
100
+ * @param expression - FEEL expression to validate
101
+ * @returns Null if valid, error message if invalid
102
+ */
103
+ declare function validateExpression(expression: FEELExpression): string | null;
104
+
105
+ export { type EvaluateError, type EvaluateResult, type EvaluationOutcome, evaluate, evaluateBoolean, evaluateBooleanBatch, evaluateNumber, evaluateString, isValidExpression, validateExpression };