@fogpipe/forma-core 0.12.0 → 0.13.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.
Files changed (40) hide show
  1. package/README.md +12 -12
  2. package/dist/{chunk-U2OXXFEH.js → chunk-BDICNCE2.js} +1 -1
  3. package/dist/chunk-BDICNCE2.js.map +1 -0
  4. package/dist/{chunk-ZSW7NIMY.js → chunk-NKA3L2LJ.js} +64 -15
  5. package/dist/chunk-NKA3L2LJ.js.map +1 -0
  6. package/dist/engine/calculate.d.ts.map +1 -1
  7. package/dist/engine/enabled.d.ts.map +1 -1
  8. package/dist/engine/index.cjs +62 -13
  9. package/dist/engine/index.cjs.map +1 -1
  10. package/dist/engine/index.d.ts +8 -8
  11. package/dist/engine/index.d.ts.map +1 -1
  12. package/dist/engine/index.js +2 -2
  13. package/dist/engine/readonly.d.ts.map +1 -1
  14. package/dist/engine/required.d.ts.map +1 -1
  15. package/dist/engine/validate.d.ts.map +1 -1
  16. package/dist/engine/visibility.d.ts.map +1 -1
  17. package/dist/feel/index.cjs.map +1 -1
  18. package/dist/feel/index.js +1 -1
  19. package/dist/index.cjs +62 -13
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.js +2 -2
  22. package/dist/types.d.ts +16 -0
  23. package/dist/types.d.ts.map +1 -1
  24. package/package.json +1 -1
  25. package/src/__tests__/feel.test.ts +67 -76
  26. package/src/__tests__/format.test.ts +19 -6
  27. package/src/__tests__/validate.test.ts +62 -20
  28. package/src/__tests__/visibility.test.ts +217 -85
  29. package/src/engine/calculate.ts +13 -10
  30. package/src/engine/enabled.ts +16 -6
  31. package/src/engine/index.ts +8 -28
  32. package/src/engine/readonly.ts +16 -6
  33. package/src/engine/required.ts +7 -5
  34. package/src/engine/validate.ts +43 -22
  35. package/src/engine/visibility.ts +40 -16
  36. package/src/feel/index.ts +12 -12
  37. package/src/format/index.ts +1 -1
  38. package/src/types.ts +46 -7
  39. package/dist/chunk-U2OXXFEH.js.map +0 -1
  40. package/dist/chunk-ZSW7NIMY.js.map +0 -1
package/dist/types.d.ts CHANGED
@@ -53,6 +53,7 @@ export interface JSONSchemaString extends JSONSchemaBase {
53
53
  pattern?: string;
54
54
  format?: "date" | "date-time" | "email" | "uri" | "uuid";
55
55
  enum?: string[];
56
+ default?: string;
56
57
  }
57
58
  export interface JSONSchemaNumber extends JSONSchemaBase {
58
59
  type: "number";
@@ -61,15 +62,18 @@ export interface JSONSchemaNumber extends JSONSchemaBase {
61
62
  exclusiveMinimum?: number;
62
63
  exclusiveMaximum?: number;
63
64
  multipleOf?: number;
65
+ default?: number;
64
66
  }
65
67
  export interface JSONSchemaInteger extends JSONSchemaBase {
66
68
  type: "integer";
67
69
  minimum?: number;
68
70
  maximum?: number;
69
71
  multipleOf?: number;
72
+ default?: number;
70
73
  }
71
74
  export interface JSONSchemaBoolean extends JSONSchemaBase {
72
75
  type: "boolean";
76
+ default?: boolean;
73
77
  }
74
78
  export interface JSONSchemaArray extends JSONSchemaBase {
75
79
  type: "array";
@@ -85,6 +89,7 @@ export interface JSONSchemaObject extends JSONSchemaBase {
85
89
  export interface JSONSchemaEnum extends JSONSchemaBase {
86
90
  type: "string";
87
91
  enum: string[];
92
+ default?: string;
88
93
  }
89
94
  /**
90
95
  * Field type enumeration - maps to UI component types
@@ -142,6 +147,17 @@ export interface FieldDefinitionBase {
142
147
  variant?: string;
143
148
  /** Variant-specific configuration */
144
149
  variantConfig?: Record<string, unknown>;
150
+ /**
151
+ * Default value for this field when the form initializes.
152
+ * Applied by the renderer during state initialization.
153
+ * Ignored on display fields (enforced by Zod validation layer).
154
+ *
155
+ * Resolution order (highest to lowest priority):
156
+ * 1. initialData prop (runtime)
157
+ * 2. defaultValue (from spec)
158
+ * 3. Implicit type defaults (boolean → false, etc.)
159
+ */
160
+ defaultValue?: unknown;
145
161
  }
146
162
  /**
147
163
  * Text-like and numeric input fields that support prefix/suffix adorners.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fogpipe/forma-core",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Forma core runtime: Types and evaluation engines for dynamic forms with FEEL expressions",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -26,7 +26,7 @@ import type { EvaluationContext } from "../types.js";
26
26
  * Create a minimal evaluation context for testing
27
27
  */
28
28
  function createContext(
29
- overrides: Partial<EvaluationContext> = {}
29
+ overrides: Partial<EvaluationContext> = {},
30
30
  ): EvaluationContext {
31
31
  return {
32
32
  data: {},
@@ -51,7 +51,7 @@ describe("evaluate", () => {
51
51
  it("evaluates field references from data", () => {
52
52
  const result = evaluate(
53
53
  "age >= 18",
54
- createContext({ data: { age: 21 } })
54
+ createContext({ data: { age: 21 } }),
55
55
  );
56
56
  expect(result.success).toBe(true);
57
57
  if (result.success) {
@@ -62,7 +62,7 @@ describe("evaluate", () => {
62
62
  it("evaluates computed field references", () => {
63
63
  const result = evaluate(
64
64
  "computed.total > 100",
65
- createContext({ data: {}, computed: { total: 150 } })
65
+ createContext({ data: {}, computed: { total: 150 } }),
66
66
  );
67
67
  expect(result.success).toBe(true);
68
68
  if (result.success) {
@@ -73,7 +73,7 @@ describe("evaluate", () => {
73
73
  it("evaluates item field references in array context", () => {
74
74
  const result = evaluate(
75
75
  "item.quantity > 5",
76
- createContext({ data: {}, item: { quantity: 10 } })
76
+ createContext({ data: {}, item: { quantity: 10 } }),
77
77
  );
78
78
  expect(result.success).toBe(true);
79
79
  if (result.success) {
@@ -82,7 +82,10 @@ describe("evaluate", () => {
82
82
  });
83
83
 
84
84
  it("evaluates value reference for validation", () => {
85
- const result = evaluate("value >= 0", createContext({ data: {}, value: 5 }));
85
+ const result = evaluate(
86
+ "value >= 0",
87
+ createContext({ data: {}, value: 5 }),
88
+ );
86
89
  expect(result.success).toBe(true);
87
90
  if (result.success) {
88
91
  expect(result.value).toBe(true);
@@ -106,7 +109,7 @@ describe("evaluate", () => {
106
109
  // This differs from strict FEEL three-valued logic
107
110
  const result = evaluate(
108
111
  "undefinedField = true",
109
- createContext({ data: {} })
112
+ createContext({ data: {} }),
110
113
  );
111
114
  expect(result.success).toBe(true);
112
115
  if (result.success) {
@@ -118,7 +121,7 @@ describe("evaluate", () => {
118
121
  // In feelin, undefined != null returns false
119
122
  const result = evaluate(
120
123
  "undefinedField != null",
121
- createContext({ data: {} })
124
+ createContext({ data: {} }),
122
125
  );
123
126
  expect(result.success).toBe(true);
124
127
  if (result.success) {
@@ -130,7 +133,7 @@ describe("evaluate", () => {
130
133
  // Numeric comparisons DO return null when field is undefined
131
134
  const result = evaluate(
132
135
  "undefinedField > 5",
133
- createContext({ data: {} })
136
+ createContext({ data: {} }),
134
137
  );
135
138
  expect(result.success).toBe(true);
136
139
  if (result.success) {
@@ -141,7 +144,7 @@ describe("evaluate", () => {
141
144
  it("returns null for string length of undefined field", () => {
142
145
  const result = evaluate(
143
146
  "string length(undefinedField)",
144
- createContext({ data: {} })
147
+ createContext({ data: {} }),
145
148
  );
146
149
  expect(result.success).toBe(true);
147
150
  if (result.success) {
@@ -152,7 +155,7 @@ describe("evaluate", () => {
152
155
  it("returns null for string length comparison with undefined field", () => {
153
156
  const result = evaluate(
154
157
  "string length(undefinedField) > 0",
155
- createContext({ data: {} })
158
+ createContext({ data: {} }),
156
159
  );
157
160
  expect(result.success).toBe(true);
158
161
  if (result.success) {
@@ -163,7 +166,7 @@ describe("evaluate", () => {
163
166
  it("returns null for count of undefined field", () => {
164
167
  const result = evaluate(
165
168
  "count(undefinedField) > 0",
166
- createContext({ data: {} })
169
+ createContext({ data: {} }),
167
170
  );
168
171
  expect(result.success).toBe(true);
169
172
  if (result.success) {
@@ -173,10 +176,7 @@ describe("evaluate", () => {
173
176
 
174
177
  it("propagates null through logical AND with null operand", () => {
175
178
  // null and true = null
176
- const result = evaluate(
177
- "null and true",
178
- createContext({ data: {} })
179
- );
179
+ const result = evaluate("null and true", createContext({ data: {} }));
180
180
  expect(result.success).toBe(true);
181
181
  if (result.success) {
182
182
  expect(result.value).toBeNull();
@@ -188,7 +188,7 @@ describe("evaluate", () => {
188
188
  // null propagates through AND
189
189
  const result = evaluate(
190
190
  "computed.eligible and x = true",
191
- createContext({ data: { x: true }, computed: { eligible: null } })
191
+ createContext({ data: { x: true }, computed: { eligible: null } }),
192
192
  );
193
193
  expect(result.success).toBe(true);
194
194
  if (result.success) {
@@ -201,7 +201,7 @@ describe("evaluate", () => {
201
201
  // false and null = false (short-circuit)
202
202
  const result = evaluate(
203
203
  "computed.eligible and x = true",
204
- createContext({ data: {}, computed: { eligible: null } })
204
+ createContext({ data: {}, computed: { eligible: null } }),
205
205
  );
206
206
  expect(result.success).toBe(true);
207
207
  if (result.success) {
@@ -240,7 +240,7 @@ describe("evaluateBoolean", () => {
240
240
  it("returns true for true expression", () => {
241
241
  const result = evaluateBoolean(
242
242
  "age >= 18",
243
- createContext({ data: { age: 21 } })
243
+ createContext({ data: { age: 21 } }),
244
244
  );
245
245
  expect(result).toBe(true);
246
246
  expect(consoleWarnSpy).not.toHaveBeenCalled();
@@ -249,7 +249,7 @@ describe("evaluateBoolean", () => {
249
249
  it("returns false for false expression", () => {
250
250
  const result = evaluateBoolean(
251
251
  "age >= 18",
252
- createContext({ data: { age: 15 } })
252
+ createContext({ data: { age: 15 } }),
253
253
  );
254
254
  expect(result).toBe(false);
255
255
  expect(consoleWarnSpy).not.toHaveBeenCalled();
@@ -258,7 +258,7 @@ describe("evaluateBoolean", () => {
258
258
  it("returns true for explicitly true boolean field", () => {
259
259
  const result = evaluateBoolean(
260
260
  "hasConsent = true",
261
- createContext({ data: { hasConsent: true } })
261
+ createContext({ data: { hasConsent: true } }),
262
262
  );
263
263
  expect(result).toBe(true);
264
264
  expect(consoleWarnSpy).not.toHaveBeenCalled();
@@ -267,7 +267,7 @@ describe("evaluateBoolean", () => {
267
267
  it("returns false for explicitly false boolean field", () => {
268
268
  const result = evaluateBoolean(
269
269
  "hasConsent = true",
270
- createContext({ data: { hasConsent: false } })
270
+ createContext({ data: { hasConsent: false } }),
271
271
  );
272
272
  expect(result).toBe(false);
273
273
  expect(consoleWarnSpy).not.toHaveBeenCalled();
@@ -289,7 +289,7 @@ describe("evaluateBoolean", () => {
289
289
  // feelin returns false for undefined = true, so no warning
290
290
  const result = evaluateBoolean(
291
291
  "undefinedField = true",
292
- createContext({ data: {} })
292
+ createContext({ data: {} }),
293
293
  );
294
294
 
295
295
  expect(result).toBe(false);
@@ -300,39 +300,39 @@ describe("evaluateBoolean", () => {
300
300
  // undefinedField > 5 returns null, triggering warning
301
301
  const result = evaluateBoolean(
302
302
  "undefinedField > 5",
303
- createContext({ data: {} })
303
+ createContext({ data: {} }),
304
304
  );
305
305
 
306
306
  expect(result).toBe(false);
307
307
  expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
308
308
  expect(consoleWarnSpy).toHaveBeenCalledWith(
309
- expect.stringContaining("returned null")
309
+ expect.stringContaining("returned null"),
310
310
  );
311
311
  });
312
312
 
313
313
  it("logs warning for string length comparison on undefined field", () => {
314
314
  const result = evaluateBoolean(
315
315
  "string length(undefinedField) > 0",
316
- createContext({ data: {} })
316
+ createContext({ data: {} }),
317
317
  );
318
318
 
319
319
  expect(result).toBe(false);
320
320
  expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
321
321
  expect(consoleWarnSpy).toHaveBeenCalledWith(
322
- expect.stringContaining("returned null")
322
+ expect.stringContaining("returned null"),
323
323
  );
324
324
  });
325
325
 
326
326
  it("logs warning for count comparison on undefined field", () => {
327
327
  const result = evaluateBoolean(
328
328
  "count(undefinedField) > 0",
329
- createContext({ data: {} })
329
+ createContext({ data: {} }),
330
330
  );
331
331
 
332
332
  expect(result).toBe(false);
333
333
  expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
334
334
  expect(consoleWarnSpy).toHaveBeenCalledWith(
335
- expect.stringContaining("returned null")
335
+ expect.stringContaining("returned null"),
336
336
  );
337
337
  });
338
338
 
@@ -340,13 +340,13 @@ describe("evaluateBoolean", () => {
340
340
  // computed.eligible is null, AND propagates null when other operand is defined
341
341
  const result = evaluateBoolean(
342
342
  "computed.eligible and x = true",
343
- createContext({ data: { x: true }, computed: { eligible: null } })
343
+ createContext({ data: { x: true }, computed: { eligible: null } }),
344
344
  );
345
345
 
346
346
  expect(result).toBe(false);
347
347
  expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
348
348
  expect(consoleWarnSpy).toHaveBeenCalledWith(
349
- expect.stringContaining("returned null")
349
+ expect.stringContaining("returned null"),
350
350
  );
351
351
  });
352
352
 
@@ -355,7 +355,7 @@ describe("evaluateBoolean", () => {
355
355
  // feelin may short-circuit: false and null = false (no null in result)
356
356
  const result = evaluateBoolean(
357
357
  "computed.eligible and x = true",
358
- createContext({ data: {}, computed: { eligible: null } })
358
+ createContext({ data: {}, computed: { eligible: null } }),
359
359
  );
360
360
 
361
361
  expect(result).toBe(false);
@@ -365,7 +365,7 @@ describe("evaluateBoolean", () => {
365
365
  it("logs warning for explicit null and true expression", () => {
366
366
  const result = evaluateBoolean(
367
367
  "null and true",
368
- createContext({ data: {} })
368
+ createContext({ data: {} }),
369
369
  );
370
370
 
371
371
  expect(result).toBe(false);
@@ -373,52 +373,40 @@ describe("evaluateBoolean", () => {
373
373
  });
374
374
 
375
375
  it("warning message includes expression that caused it", () => {
376
- evaluateBoolean(
377
- "undefinedField > 5",
378
- createContext({ data: {} })
379
- );
376
+ evaluateBoolean("undefinedField > 5", createContext({ data: {} }));
380
377
 
381
378
  expect(consoleWarnSpy).toHaveBeenCalledWith(
382
- expect.stringContaining("undefinedField > 5")
379
+ expect.stringContaining("undefinedField > 5"),
383
380
  );
384
381
  });
385
382
 
386
383
  it("warning message includes null-safe pattern guidance", () => {
387
- evaluateBoolean(
388
- "undefinedField > 5",
389
- createContext({ data: {} })
390
- );
384
+ evaluateBoolean("undefinedField > 5", createContext({ data: {} }));
391
385
 
392
386
  expect(consoleWarnSpy).toHaveBeenCalledWith(
393
- expect.stringContaining("null-safe patterns")
387
+ expect.stringContaining("null-safe patterns"),
394
388
  );
395
389
  });
396
390
  });
397
391
 
398
392
  describe("non-boolean result handling", () => {
399
393
  it("logs warning and returns false for numeric result", () => {
400
- const result = evaluateBoolean(
401
- "2 + 3",
402
- createContext({ data: {} })
403
- );
394
+ const result = evaluateBoolean("2 + 3", createContext({ data: {} }));
404
395
 
405
396
  expect(result).toBe(false);
406
397
  expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
407
398
  expect(consoleWarnSpy).toHaveBeenCalledWith(
408
- expect.stringContaining("did not return boolean")
399
+ expect.stringContaining("did not return boolean"),
409
400
  );
410
401
  });
411
402
 
412
403
  it("logs warning and returns false for string result", () => {
413
- const result = evaluateBoolean(
414
- '"hello"',
415
- createContext({ data: {} })
416
- );
404
+ const result = evaluateBoolean('"hello"', createContext({ data: {} }));
417
405
 
418
406
  expect(result).toBe(false);
419
407
  expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
420
408
  expect(consoleWarnSpy).toHaveBeenCalledWith(
421
- expect.stringContaining("did not return boolean")
409
+ expect.stringContaining("did not return boolean"),
422
410
  );
423
411
  });
424
412
  });
@@ -428,7 +416,7 @@ describe("evaluateBoolean", () => {
428
416
  // Force an error by using invalid function
429
417
  const result = evaluateBoolean(
430
418
  "nonExistentFunction(x)",
431
- createContext({ data: {} })
419
+ createContext({ data: {} }),
432
420
  );
433
421
 
434
422
  expect(result).toBe(false);
@@ -454,9 +442,12 @@ describe("evaluateNumber", () => {
454
442
  });
455
443
 
456
444
  it("returns number for valid arithmetic", () => {
457
- const result = evaluateNumber("quantity * price", createContext({
458
- data: { quantity: 5, price: 10 }
459
- }));
445
+ const result = evaluateNumber(
446
+ "quantity * price",
447
+ createContext({
448
+ data: { quantity: 5, price: 10 },
449
+ }),
450
+ );
460
451
  expect(result).toBe(50);
461
452
  });
462
453
 
@@ -464,7 +455,7 @@ describe("evaluateNumber", () => {
464
455
  const result = evaluateNumber('"hello"', createContext());
465
456
  expect(result).toBeNull();
466
457
  expect(consoleWarnSpy).toHaveBeenCalledWith(
467
- expect.stringContaining("did not return number")
458
+ expect.stringContaining("did not return number"),
468
459
  );
469
460
  });
470
461
 
@@ -493,7 +484,7 @@ describe("evaluateString", () => {
493
484
  it("returns string for valid string expression", () => {
494
485
  const result = evaluateString(
495
486
  'if age >= 18 then "adult" else "minor"',
496
- createContext({ data: { age: 21 } })
487
+ createContext({ data: { age: 21 } }),
497
488
  );
498
489
  expect(result).toBe("adult");
499
490
  });
@@ -502,7 +493,7 @@ describe("evaluateString", () => {
502
493
  const result = evaluateString("2 + 3", createContext());
503
494
  expect(result).toBeNull();
504
495
  expect(consoleWarnSpy).toHaveBeenCalledWith(
505
- expect.stringContaining("did not return string")
496
+ expect.stringContaining("did not return string"),
506
497
  );
507
498
  });
508
499
  });
@@ -529,7 +520,7 @@ describe("evaluateBooleanBatch", () => {
529
520
  canDrive: "age >= 16",
530
521
  canDrink: "age >= 21",
531
522
  },
532
- createContext({ data: { age: 20 } })
523
+ createContext({ data: { age: 20 } }),
533
524
  );
534
525
 
535
526
  expect(results.canVote).toBe(true);
@@ -544,7 +535,7 @@ describe("evaluateBooleanBatch", () => {
544
535
  visible: "undefinedField = true",
545
536
  enabled: "anotherUndefined = false",
546
537
  },
547
- createContext({ data: {} })
538
+ createContext({ data: {} }),
548
539
  );
549
540
 
550
541
  expect(results.visible).toBe(false);
@@ -559,7 +550,7 @@ describe("evaluateBooleanBatch", () => {
559
550
  hasEnoughItems: "count(items) > 5",
560
551
  hasLongName: "string length(name) > 10",
561
552
  },
562
- createContext({ data: {} })
553
+ createContext({ data: {} }),
563
554
  );
564
555
 
565
556
  expect(results.hasEnoughItems).toBe(false);
@@ -643,7 +634,7 @@ describe("real-world scenarios", () => {
643
634
  inclusionDiagnosis: true,
644
635
  inclusionHbA1c: true,
645
636
  },
646
- })
637
+ }),
647
638
  );
648
639
 
649
640
  expect(result).toBe(true);
@@ -659,7 +650,7 @@ describe("real-world scenarios", () => {
659
650
  inclusionDiagnosis: false,
660
651
  inclusionHbA1c: true,
661
652
  },
662
- })
653
+ }),
663
654
  );
664
655
 
665
656
  expect(result).toBe(false);
@@ -677,7 +668,7 @@ describe("real-world scenarios", () => {
677
668
  // inclusionDiagnosis not yet answered
678
669
  inclusionHbA1c: true,
679
670
  },
680
- })
671
+ }),
681
672
  );
682
673
 
683
674
  expect(result).toBe(false);
@@ -695,7 +686,7 @@ describe("real-world scenarios", () => {
695
686
  inclusionAge: true,
696
687
  // inclusionDiagnosis not yet answered
697
688
  },
698
- })
689
+ }),
699
690
  );
700
691
 
701
692
  expect(allAnswered).toBe(false);
@@ -712,7 +703,7 @@ describe("real-world scenarios", () => {
712
703
  data: {
713
704
  // signingOnBehalf not yet answered
714
705
  },
715
- })
706
+ }),
716
707
  );
717
708
 
718
709
  // feelin returns true for undefined != true
@@ -728,7 +719,7 @@ describe("real-world scenarios", () => {
728
719
  createContext({
729
720
  data: {},
730
721
  computed: { eligible: true },
731
- })
722
+ }),
732
723
  );
733
724
 
734
725
  expect(result).toBe(true);
@@ -741,7 +732,7 @@ describe("real-world scenarios", () => {
741
732
  createContext({
742
733
  data: {},
743
734
  computed: { eligible: false },
744
- })
735
+ }),
745
736
  );
746
737
 
747
738
  expect(result).toBe(false);
@@ -755,7 +746,7 @@ describe("real-world scenarios", () => {
755
746
  createContext({
756
747
  data: {},
757
748
  computed: { eligible: null },
758
- })
749
+ }),
759
750
  );
760
751
 
761
752
  expect(result).toBe(false);
@@ -771,13 +762,13 @@ describe("real-world scenarios", () => {
771
762
  createContext({
772
763
  data: { otherCondition: true },
773
764
  computed: { eligible: null },
774
- })
765
+ }),
775
766
  );
776
767
 
777
768
  expect(result).toBe(false);
778
769
  expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
779
770
  expect(consoleWarnSpy).toHaveBeenCalledWith(
780
- expect.stringContaining("returned null")
771
+ expect.stringContaining("returned null"),
781
772
  );
782
773
  });
783
774
 
@@ -788,7 +779,7 @@ describe("real-world scenarios", () => {
788
779
  createContext({
789
780
  data: {},
790
781
  computed: { eligible: null },
791
- })
782
+ }),
792
783
  );
793
784
 
794
785
  expect(result).toBe(false);
@@ -801,7 +792,7 @@ describe("real-world scenarios", () => {
801
792
  // This is a common pattern that triggers warnings
802
793
  const result = evaluateBoolean(
803
794
  "string length(signature) > 0",
804
- createContext({ data: {} })
795
+ createContext({ data: {} }),
805
796
  );
806
797
 
807
798
  expect(result).toBe(false);
@@ -811,7 +802,7 @@ describe("real-world scenarios", () => {
811
802
  it("no warning when field has value", () => {
812
803
  const result = evaluateBoolean(
813
804
  "string length(signature) > 0",
814
- createContext({ data: { signature: "John Doe" } })
805
+ createContext({ data: { signature: "John Doe" } }),
815
806
  );
816
807
 
817
808
  expect(result).toBe(true);
@@ -822,7 +813,7 @@ describe("real-world scenarios", () => {
822
813
  // Proper null-safe pattern: check != null first
823
814
  const result = evaluateBoolean(
824
815
  "signature != null and string length(signature) > 0",
825
- createContext({ data: {} })
816
+ createContext({ data: {} }),
826
817
  );
827
818
 
828
819
  expect(result).toBe(false);
@@ -157,7 +157,9 @@ describe("format module", () => {
157
157
 
158
158
  it("formats date strings", () => {
159
159
  const result = formatValue("2024-03-15", "date");
160
- expect(result).toMatch(/3\/15\/2024|15\/3\/2024|3\/14\/2024|14\/3\/2024/);
160
+ expect(result).toMatch(
161
+ /3\/15\/2024|15\/3\/2024|3\/14\/2024|14\/3\/2024/,
162
+ );
161
163
  });
162
164
 
163
165
  it("falls back to string for invalid dates", () => {
@@ -189,23 +191,34 @@ describe("format module", () => {
189
191
  describe("nullDisplay option", () => {
190
192
  it("uses nullDisplay for null values", () => {
191
193
  expect(formatValue(null, undefined, { nullDisplay: "—" })).toBe("—");
192
- expect(formatValue(null, "decimal(2)", { nullDisplay: "N/A" })).toBe("N/A");
194
+ expect(formatValue(null, "decimal(2)", { nullDisplay: "N/A" })).toBe(
195
+ "N/A",
196
+ );
193
197
  });
194
198
 
195
199
  it("uses nullDisplay for undefined values", () => {
196
- expect(formatValue(undefined, undefined, { nullDisplay: "—" })).toBe("—");
197
- expect(formatValue(undefined, "currency", { nullDisplay: "-" })).toBe("-");
200
+ expect(formatValue(undefined, undefined, { nullDisplay: "—" })).toBe(
201
+ "",
202
+ );
203
+ expect(formatValue(undefined, "currency", { nullDisplay: "-" })).toBe(
204
+ "-",
205
+ );
198
206
  });
199
207
 
200
208
  it("does not affect non-null values", () => {
201
- expect(formatValue(123, "decimal(2)", { nullDisplay: "—" })).toBe("123.00");
209
+ expect(formatValue(123, "decimal(2)", { nullDisplay: "—" })).toBe(
210
+ "123.00",
211
+ );
202
212
  expect(formatValue(0, "decimal(2)", { nullDisplay: "—" })).toBe("0.00");
203
213
  });
204
214
  });
205
215
 
206
216
  describe("locale option", () => {
207
217
  it("respects locale for currency formatting", () => {
208
- const result = formatValue(1234.56, "currency", { locale: "de-DE", currency: "EUR" });
218
+ const result = formatValue(1234.56, "currency", {
219
+ locale: "de-DE",
220
+ currency: "EUR",
221
+ });
209
222
  // German locale uses comma for decimals
210
223
  expect(result).toContain("1.234,56");
211
224
  });