form0-core 0.1.2 → 0.1.3

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.
@@ -1,99 +1,137 @@
1
- // Import all builtins
2
- import { IF } from './logical/if.js';
3
- import { AND } from './logical/and.js';
4
- import { OR } from './logical/or.js';
5
- import { COUNT } from './logical/count.js';
6
- import { COUNTA } from './logical/counta.js';
7
- import { COUNTBLANK } from './logical/countblank.js';
8
- import { ARRAY } from './logical/array.js';
9
- import { SETRESULT, __consumeResult } from './control/setresult.js';
10
- import { EVAL } from './control/eval.js';
11
- import { CHOICEVALUE } from './choice/choicevalue.js';
12
- import { CHOICELABEL } from './choice/choicelabel.js';
13
- import { HASOTHER } from './choice/hasother.js';
14
- import { OTHER } from './choice/other.js';
15
- import { CHOICEVALUES } from './choice/choicevalues.js';
16
- import { CHOICELABELS } from './choice/choicelabels.js';
17
- import { FORM } from './schema/form.js';
18
- import { DATANAMES } from './schema/datanames.js';
19
- import { ABS } from './math/abs.js';
20
- import { CEILING } from './math/ceiling.js';
21
- import { COS } from './math/cos.js';
22
- import { SIN } from './math/sin.js';
23
- import { ROUND } from './math/round.js';
24
- import { UPPER } from './string/upper.js';
1
+ import { cloneBuiltinMetadata, BUILTIN_CONTEXTS } from './builtin-metadata.js';
25
2
 
26
- // Import event builtins
27
- import { ALERT } from './event/ui/alert.js';
28
- import { SETVALUE } from './event/field/setvalue.js';
29
- import { ON } from './event/control/on.js';
30
- import { OFF } from './event/control/off.js';
3
+ import { IF, IF_METADATA } from './logical/if.js';
4
+ import { AND, AND_METADATA } from './logical/and.js';
5
+ import { OR, OR_METADATA } from './logical/or.js';
6
+ import { COUNT, COUNT_METADATA } from './logical/count.js';
7
+ import { COUNTA, COUNTA_METADATA } from './logical/counta.js';
8
+ import { COUNTBLANK, COUNTBLANK_METADATA } from './logical/countblank.js';
9
+ import { ARRAY, ARRAY_METADATA } from './logical/array.js';
10
+ import { SETRESULT, SETRESULT_METADATA, __consumeResult } from './control/setresult.js';
11
+ import { EVAL, EVAL_METADATA } from './control/eval.js';
12
+ import { CHOICEVALUE, CHOICEVALUE_METADATA } from './choice/choicevalue.js';
13
+ import { CHOICELABEL, CHOICELABEL_METADATA } from './choice/choicelabel.js';
14
+ import { HASOTHER, HASOTHER_METADATA } from './choice/hasother.js';
15
+ import { OTHER, OTHER_METADATA } from './choice/other.js';
16
+ import { CHOICEVALUES, CHOICEVALUES_METADATA } from './choice/choicevalues.js';
17
+ import { CHOICELABELS, CHOICELABELS_METADATA } from './choice/choicelabels.js';
18
+ import { FORM, FORM_METADATA } from './schema/form.js';
19
+ import { DATANAMES, DATANAMES_METADATA } from './schema/datanames.js';
20
+ import { ABS, ABS_METADATA } from './math/abs.js';
21
+ import { CEILING, CEILING_METADATA } from './math/ceiling.js';
22
+ import { COS, COS_METADATA } from './math/cos.js';
23
+ import { SIN, SIN_METADATA } from './math/sin.js';
24
+ import { ROUND, ROUND_METADATA } from './math/round.js';
25
+ import { UPPER, UPPER_METADATA } from './string/upper.js';
26
+
27
+ import { ALERT, ALERT_METADATA } from './event/ui/alert.js';
28
+ import { SETVALUE, SETVALUE_METADATA } from './event/field/setvalue.js';
29
+ import { ON, ON_METADATA } from './event/control/on.js';
30
+ import { OFF, OFF_METADATA } from './event/control/off.js';
31
31
  import { __consumeEventOperations } from './event/event-operations-collector.js';
32
32
 
33
- // Export individual builtins
34
- export { IF } from './logical/if.js';
35
- export { AND } from './logical/and.js';
36
- export { OR } from './logical/or.js';
37
- export { COUNT } from './logical/count.js';
38
- export { COUNTA } from './logical/counta.js';
39
- export { COUNTBLANK } from './logical/countblank.js';
40
- export { ARRAY } from './logical/array.js';
41
- export { SETRESULT, __consumeResult } from './control/setresult.js';
42
- export { EVAL, __setEvalContext, __clearEvalContext } from './control/eval.js';
43
- export { CHOICEVALUE } from './choice/choicevalue.js';
44
- export { CHOICELABEL } from './choice/choicelabel.js';
45
- export { HASOTHER } from './choice/hasother.js';
46
- export { OTHER } from './choice/other.js';
47
- export { CHOICEVALUES } from './choice/choicevalues.js';
48
- export { CHOICELABELS } from './choice/choicelabels.js';
49
- export { FORM } from './schema/form.js';
50
- export { DATANAMES, __setDataNamesContext, __clearDataNamesContext } from './schema/datanames.js';
51
- export { ABS } from './math/abs.js';
52
- export { CEILING } from './math/ceiling.js';
53
- export { COS } from './math/cos.js';
54
- export { SIN } from './math/sin.js';
55
- export { ROUND } from './math/round.js';
56
- export { UPPER } from './string/upper.js';
33
+ export { IF, IF_METADATA } from './logical/if.js';
34
+ export { AND, AND_METADATA } from './logical/and.js';
35
+ export { OR, OR_METADATA } from './logical/or.js';
36
+ export { COUNT, COUNT_METADATA } from './logical/count.js';
37
+ export { COUNTA, COUNTA_METADATA } from './logical/counta.js';
38
+ export { COUNTBLANK, COUNTBLANK_METADATA } from './logical/countblank.js';
39
+ export { ARRAY, ARRAY_METADATA } from './logical/array.js';
40
+ export { SETRESULT, SETRESULT_METADATA, __consumeResult } from './control/setresult.js';
41
+ export { EVAL, EVAL_METADATA, __setEvalContext, __clearEvalContext } from './control/eval.js';
42
+ export { CHOICEVALUE, CHOICEVALUE_METADATA } from './choice/choicevalue.js';
43
+ export { CHOICELABEL, CHOICELABEL_METADATA } from './choice/choicelabel.js';
44
+ export { HASOTHER, HASOTHER_METADATA } from './choice/hasother.js';
45
+ export { OTHER, OTHER_METADATA } from './choice/other.js';
46
+ export { CHOICEVALUES, CHOICEVALUES_METADATA } from './choice/choicevalues.js';
47
+ export { CHOICELABELS, CHOICELABELS_METADATA } from './choice/choicelabels.js';
48
+ export { FORM, FORM_METADATA } from './schema/form.js';
49
+ export {
50
+ DATANAMES,
51
+ DATANAMES_METADATA,
52
+ __setDataNamesContext,
53
+ __clearDataNamesContext,
54
+ } from './schema/datanames.js';
55
+ export { ABS, ABS_METADATA } from './math/abs.js';
56
+ export { CEILING, CEILING_METADATA } from './math/ceiling.js';
57
+ export { COS, COS_METADATA } from './math/cos.js';
58
+ export { SIN, SIN_METADATA } from './math/sin.js';
59
+ export { ROUND, ROUND_METADATA } from './math/round.js';
60
+ export { UPPER, UPPER_METADATA } from './string/upper.js';
57
61
 
58
- // Export event builtins
59
- export { ALERT } from './event/ui/alert.js';
60
- export { SETVALUE } from './event/field/setvalue.js';
61
- export { ON } from './event/control/on.js';
62
- export { OFF } from './event/control/off.js';
62
+ export { ALERT, ALERT_METADATA } from './event/ui/alert.js';
63
+ export { SETVALUE, SETVALUE_METADATA } from './event/field/setvalue.js';
64
+ export { ON, ON_METADATA } from './event/control/on.js';
65
+ export { OFF, OFF_METADATA } from './event/control/off.js';
63
66
  export { __consumeEventOperations } from './event/event-operations-collector.js';
64
67
 
65
- // Main builtins object for backward compatibility
66
- export const builtins = {
67
- IF,
68
- AND,
69
- OR,
70
- COUNT,
71
- COUNTA,
72
- COUNTBLANK,
73
- ARRAY,
74
- SETRESULT,
75
- EVAL,
76
- CHOICEVALUE,
77
- CHOICELABEL,
78
- HASOTHER,
79
- OTHER,
80
- CHOICEVALUES,
81
- CHOICELABELS,
82
- FORM, // Available in both calculations and events
83
- DATANAMES,
84
- ABS,
85
- CEILING,
86
- COS,
87
- SIN,
88
- ROUND,
89
- UPPER,
90
- };
68
+ const CALCULATION_AND_EVENT_ENTRIES = Object.freeze([
69
+ { implementation: IF, definition: IF_METADATA },
70
+ { implementation: AND, definition: AND_METADATA },
71
+ { implementation: OR, definition: OR_METADATA },
72
+ { implementation: COUNT, definition: COUNT_METADATA },
73
+ { implementation: COUNTA, definition: COUNTA_METADATA },
74
+ { implementation: COUNTBLANK, definition: COUNTBLANK_METADATA },
75
+ { implementation: ARRAY, definition: ARRAY_METADATA },
76
+ { implementation: SETRESULT, definition: SETRESULT_METADATA },
77
+ { implementation: EVAL, definition: EVAL_METADATA },
78
+ { implementation: CHOICEVALUE, definition: CHOICEVALUE_METADATA },
79
+ { implementation: CHOICELABEL, definition: CHOICELABEL_METADATA },
80
+ { implementation: HASOTHER, definition: HASOTHER_METADATA },
81
+ { implementation: OTHER, definition: OTHER_METADATA },
82
+ { implementation: CHOICEVALUES, definition: CHOICEVALUES_METADATA },
83
+ { implementation: CHOICELABELS, definition: CHOICELABELS_METADATA },
84
+ { implementation: FORM, definition: FORM_METADATA },
85
+ { implementation: DATANAMES, definition: DATANAMES_METADATA },
86
+ { implementation: ABS, definition: ABS_METADATA },
87
+ { implementation: CEILING, definition: CEILING_METADATA },
88
+ { implementation: COS, definition: COS_METADATA },
89
+ { implementation: SIN, definition: SIN_METADATA },
90
+ { implementation: ROUND, definition: ROUND_METADATA },
91
+ { implementation: UPPER, definition: UPPER_METADATA },
92
+ ]);
93
+
94
+ const EVENT_ONLY_ENTRIES = Object.freeze([
95
+ { implementation: ALERT, definition: ALERT_METADATA },
96
+ { implementation: SETVALUE, definition: SETVALUE_METADATA },
97
+ { implementation: ON, definition: ON_METADATA },
98
+ { implementation: OFF, definition: OFF_METADATA },
99
+ ]);
100
+
101
+ function buildBuiltinObject(entries) {
102
+ return Object.freeze(
103
+ Object.fromEntries(
104
+ entries.map(({ implementation, definition }) => [definition.name, implementation])
105
+ )
106
+ );
107
+ }
108
+
109
+ function filterDefinitionsByContext(definitions, context) {
110
+ return Object.freeze(definitions.filter((definition) => definition.contexts.includes(context)));
111
+ }
112
+
113
+ export const builtins = buildBuiltinObject(CALCULATION_AND_EVENT_ENTRIES);
114
+
115
+ export const eventBuiltins = buildBuiltinObject(EVENT_ONLY_ENTRIES);
116
+
117
+ export const BUILTIN_DEFINITIONS = Object.freeze(
118
+ [...CALCULATION_AND_EVENT_ENTRIES, ...EVENT_ONLY_ENTRIES].map(({ definition }) => definition)
119
+ );
120
+
121
+ export const CALCULATION_BUILTIN_DEFINITIONS = filterDefinitionsByContext(
122
+ BUILTIN_DEFINITIONS,
123
+ BUILTIN_CONTEXTS.CALCULATION
124
+ );
125
+
126
+ export const EVENT_BUILTIN_DEFINITIONS = filterDefinitionsByContext(
127
+ BUILTIN_DEFINITIONS,
128
+ BUILTIN_CONTEXTS.EVENT
129
+ );
130
+
131
+ export const BUILTIN_DEFINITION_BY_NAME = new Map(
132
+ BUILTIN_DEFINITIONS.map((definition) => [definition.name, definition])
133
+ );
91
134
 
92
- // Event-specific builtins (only available in event context)
93
- export const eventBuiltins = {
94
- ALERT,
95
- SETVALUE,
96
- ON,
97
- OFF,
98
- // Future: CONFIRM, NOTIFY, etc.
99
- };
135
+ export function getBuiltinDefinitions() {
136
+ return BUILTIN_DEFINITIONS.map(cloneBuiltinMetadata);
137
+ }
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin DATANAMES
3
5
  * @description Returns the data names of form fields, optionally filtered by field type
@@ -13,6 +15,14 @@
13
15
  * // Get only TextField data names
14
16
  * DATANAMES('TextField')
15
17
  */
18
+ export const DATANAMES_METADATA = defineBuiltinMetadata({
19
+ name: 'DATANAMES',
20
+ category: 'schema',
21
+ signature: "DATANAMES(type = 'any')",
22
+ description: 'Return form field data names, optionally filtered by field type.',
23
+ examples: ["DATANAMES('NumericField')"],
24
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
25
+ });
16
26
 
17
27
  // Global schema context for DATANAMES() - set during expression evaluation
18
28
  let _dataNamesSchema = null;
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin FORM
3
5
  * @description Access to the nested JSON form definition (future implementation)
@@ -12,6 +14,15 @@
12
14
  * // Check if form has RepeatableSections
13
15
  * FORM().elements.some(el => el.type === 'RepeatableSection')
14
16
  */
17
+ export const FORM_METADATA = defineBuiltinMetadata({
18
+ name: 'FORM',
19
+ category: 'schema',
20
+ signature: 'FORM()',
21
+ description: 'Access the form definition. Reserved for a future implementation.',
22
+ examples: ['FORM()'],
23
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
24
+ });
25
+
15
26
  export function FORM() {
16
27
  // Placeholder for future implementation
17
28
  // Will provide access to nested JSON form definition
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin UPPER
3
5
  * @description Returns the uppercase version of a string
@@ -13,9 +15,18 @@
13
15
  * // Returns "ABC123"
14
16
  * UPPER("abc123")
15
17
  */
18
+ export const UPPER_METADATA = defineBuiltinMetadata({
19
+ name: 'UPPER',
20
+ category: 'string',
21
+ signature: 'UPPER(value)',
22
+ description: 'Convert a string to uppercase.',
23
+ examples: ['UPPER($city_name)'],
24
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
25
+ });
26
+
16
27
  export const UPPER = (value) => {
17
28
  if (value == null) {
18
29
  return '';
19
30
  }
20
31
  return String(value).toUpperCase();
21
- };
32
+ };
package/src/index.js CHANGED
@@ -30,6 +30,12 @@ export {
30
30
  } from './utilities/form-link-helpers.js';
31
31
  export { expandBuildingPlanSchema } from './schema/building-plan-expander.js';
32
32
  export { FIELD_SPECS } from './schema/field-specs.js';
33
+ export { getBuiltinDefinitions } from './builtins/registry.js';
34
+ export {
35
+ getCalculationBuiltinCatalog,
36
+ getCalculationReferenceCatalog,
37
+ analyzeCalculationExpression,
38
+ } from './utilities/calculation-editor.js';
33
39
  export {
34
40
  getFormAIMetadata,
35
41
  getFormAIContext,