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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "form0-core",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/"
6
6
  },
@@ -8,7 +8,7 @@
8
8
  "main": "src/index.js",
9
9
  "type": "module",
10
10
  "scripts": {
11
- "test": "node tests/form0-core.test.js && node tests/security-test.js",
11
+ "test": "node tests/form0-core.test.js && node tests/builtin-metadata.test.js && node tests/calculation-editor.test.js && node tests/security-test.js",
12
12
  "postinstall": "node scripts/postinstall.cjs",
13
13
  "format": "prettier --write \"**/*.{js,jsx,json,ts,tsx,md}\"",
14
14
  "format:check": "prettier --check \"**/*.{js,jsx,json,ts,tsx,md}\""
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @typedef {'calculation' | 'event'} BuiltinContext
3
+ *
4
+ * @typedef {Object} BuiltinMetadata
5
+ * @property {string} name
6
+ * @property {string} category
7
+ * @property {string} signature
8
+ * @property {string} description
9
+ * @property {string[]} examples
10
+ * @property {BuiltinContext[]} contexts
11
+ */
12
+
13
+ export const BUILTIN_CONTEXTS = Object.freeze({
14
+ CALCULATION: 'calculation',
15
+ EVENT: 'event',
16
+ });
17
+
18
+ /**
19
+ * Create immutable metadata for a builtin implementation.
20
+ *
21
+ * @param {BuiltinMetadata} definition
22
+ * @returns {BuiltinMetadata}
23
+ */
24
+ export function defineBuiltinMetadata(definition) {
25
+ return Object.freeze({
26
+ ...definition,
27
+ examples: Object.freeze([...(definition.examples ?? [])]),
28
+ contexts: Object.freeze([...(definition.contexts ?? [])]),
29
+ });
30
+ }
31
+
32
+ /**
33
+ * Return a mutable clone of builtin metadata for external consumers.
34
+ *
35
+ * @param {BuiltinMetadata} definition
36
+ * @returns {BuiltinMetadata}
37
+ */
38
+ export function cloneBuiltinMetadata(definition) {
39
+ return {
40
+ ...definition,
41
+ examples: [...definition.examples],
42
+ contexts: [...definition.contexts],
43
+ };
44
+ }
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin CHOICELABEL
3
5
  * @description Retrieves the currently selected choice field label, preserving the type (if the label is a number preserves the number type, otherwise string). If no selection it returns null.
@@ -10,6 +12,15 @@
10
12
  * // Use in display logic
11
13
  * "You selected: " + CHOICELABEL($city)
12
14
  */
15
+ export const CHOICELABEL_METADATA = defineBuiltinMetadata({
16
+ name: 'CHOICELABEL',
17
+ category: 'choice',
18
+ signature: 'CHOICELABEL(fieldValue)',
19
+ description: 'Return the selected choice label from a choice field.',
20
+ examples: ['CHOICELABEL($city)'],
21
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
22
+ });
23
+
13
24
  export const CHOICELABEL = (choiceField) => {
14
25
  // Handle null/undefined input
15
26
  if (!choiceField || typeof choiceField !== 'object') {
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin CHOICELABELS
3
5
  * @description Retrieves an array of all selected choice field labels from a MultiChoiceField, preserving the type of each label. Returns an empty array if no selections.
@@ -10,6 +12,15 @@
10
12
  * // Display selected colors
11
13
  * "Selected colors: " + CHOICELABELS($colors).join(", ")
12
14
  */
15
+ export const CHOICELABELS_METADATA = defineBuiltinMetadata({
16
+ name: 'CHOICELABELS',
17
+ category: 'choice',
18
+ signature: 'CHOICELABELS(fieldValue)',
19
+ description: 'Return all selected labels from a MultiChoiceField.',
20
+ examples: ['CHOICELABELS($colors)'],
21
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
22
+ });
23
+
13
24
  export const CHOICELABELS = (multiChoiceField) => {
14
25
  // Handle null/undefined input
15
26
  if (!multiChoiceField || typeof multiChoiceField !== 'object') {
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin CHOICEVALUE
3
5
  * @description Retrieves the currently selected choice field value, preserving the type (if the value is a number preserves the number type, otherwise string). If no selection it returns null.
@@ -10,6 +12,15 @@
10
12
  * // Use in conditional logic
11
13
  * IF(CHOICEVALUE($city) === "bogota", "Welcome to Bogotá!", "Welcome!")
12
14
  */
15
+ export const CHOICEVALUE_METADATA = defineBuiltinMetadata({
16
+ name: 'CHOICEVALUE',
17
+ category: 'choice',
18
+ signature: 'CHOICEVALUE(fieldValue)',
19
+ description: 'Return the selected choice value from a choice field.',
20
+ examples: ['CHOICEVALUE($city)'],
21
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
22
+ });
23
+
13
24
  export const CHOICEVALUE = (choiceField) => {
14
25
  // Handle null/undefined input
15
26
  if (!choiceField || typeof choiceField !== 'object') {
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin CHOICEVALUES
3
5
  * @description Retrieves an array of all selected choice field values from a MultiChoiceField, preserving the type of each value. Returns an empty array if no selections.
@@ -10,6 +12,15 @@
10
12
  * // Check if "red" is selected
11
13
  * CHOICEVALUES($colors).includes("red")
12
14
  */
15
+ export const CHOICEVALUES_METADATA = defineBuiltinMetadata({
16
+ name: 'CHOICEVALUES',
17
+ category: 'choice',
18
+ signature: 'CHOICEVALUES(fieldValue)',
19
+ description: 'Return all selected values from a MultiChoiceField.',
20
+ examples: ['CHOICEVALUES($colors)'],
21
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
22
+ });
23
+
13
24
  export const CHOICEVALUES = (multiChoiceField) => {
14
25
  // Handle null/undefined input
15
26
  if (!multiChoiceField || typeof multiChoiceField !== 'object') {
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin HASOTHER
3
5
  * @description Returns true if user entered an other option, false otherwise. Works with both SingleChoiceField and MultiChoiceField.
@@ -13,6 +15,15 @@
13
15
  * // Use in conditional logic
14
16
  * IF(HASOTHER($city), "Custom city: " + OTHER($city), "Selected city: " + CHOICELABEL($city))
15
17
  */
18
+ export const HASOTHER_METADATA = defineBuiltinMetadata({
19
+ name: 'HASOTHER',
20
+ category: 'choice',
21
+ signature: 'HASOTHER(fieldValue)',
22
+ description: 'Return true when the field has an "other" value.',
23
+ examples: ['HASOTHER($city)'],
24
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
25
+ });
26
+
16
27
  export const HASOTHER = (choiceField) => {
17
28
  // Handle null/undefined input
18
29
  if (!choiceField || typeof choiceField !== 'object') {
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin OTHER
3
5
  * @description Retrieves the other label if user entered the other option, otherwise null. Works with both SingleChoiceField and MultiChoiceField.
@@ -13,6 +15,15 @@
13
15
  * // Use in conditional logic
14
16
  * IF(HASOTHER($city), "Custom city: " + OTHER($city), "No custom city entered")
15
17
  */
18
+ export const OTHER_METADATA = defineBuiltinMetadata({
19
+ name: 'OTHER',
20
+ category: 'choice',
21
+ signature: 'OTHER(fieldValue)',
22
+ description: 'Return the "other" label from a choice field.',
23
+ examples: ['OTHER($city)'],
24
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
25
+ });
26
+
16
27
  export const OTHER = (choiceField) => {
17
28
  // Handle null/undefined input
18
29
  if (!choiceField || typeof choiceField !== 'object') {
@@ -1,5 +1,6 @@
1
1
  import { validateExpression } from '../../security/validation.js';
2
2
  import { SAFE_SECURITY_CONFIG } from '../../security/config.js';
3
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
3
4
 
4
5
  /**
5
6
  * @builtin EVAL
@@ -16,6 +17,15 @@ import { SAFE_SECURITY_CONFIG } from '../../security/config.js';
16
17
  * // Computed field references
17
18
  * EVAL('$city' + '_suffix')
18
19
  */
20
+ export const EVAL_METADATA = defineBuiltinMetadata({
21
+ name: 'EVAL',
22
+ category: 'control',
23
+ signature: 'EVAL(expression)',
24
+ description: 'Evaluate a dynamically built expression string in a restricted context.',
25
+ examples: ['EVAL("$" + dynamicFieldName)'],
26
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
27
+ });
28
+
19
29
  // Global context for EVAL() - set during expression evaluation
20
30
  let _evalContext = null;
21
31
 
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  // Global state for result management
2
4
  let _resultSet = false;
3
5
  let _resultValue;
@@ -14,6 +16,15 @@ let _resultValue;
14
16
  * // Set a conditional result
15
17
  * SETRESULT(IF(isEligible, discount, 0))
16
18
  */
19
+ export const SETRESULT_METADATA = defineBuiltinMetadata({
20
+ name: 'SETRESULT',
21
+ category: 'control',
22
+ signature: 'SETRESULT(value)',
23
+ description: 'Set the final return value for multiline calculations.',
24
+ examples: ['SETRESULT($price * $quantity)'],
25
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
26
+ });
27
+
17
28
  export const SETRESULT = (value) => {
18
29
  _resultSet = true;
19
30
  _resultValue = value;
@@ -1,4 +1,5 @@
1
1
  import { __collectEventOperation } from '../event-operations-collector.js';
2
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../../builtin-metadata.js';
2
3
 
3
4
  /**
4
5
  * OFF builtin for form events
@@ -26,6 +27,15 @@ import { __collectEventOperation } from '../event-operations-collector.js';
26
27
  * // Remove all field event handlers
27
28
  * OFF('change', 'city');
28
29
  */
30
+ export const OFF_METADATA = defineBuiltinMetadata({
31
+ name: 'OFF',
32
+ category: 'event',
33
+ signature: 'OFF(eventType, fieldKeyOrCallback, callback)',
34
+ description: 'Remove event handlers within form event code.',
35
+ examples: ["OFF('change', 'city', specificCallback)"],
36
+ contexts: [BUILTIN_CONTEXTS.EVENT],
37
+ });
38
+
29
39
  export function OFF(eventType, fieldKeyOrCallback, callback) {
30
40
  let fieldKey = '*';
31
41
  let actualCallback = undefined;
@@ -1,4 +1,5 @@
1
1
  import { __collectEventOperation } from '../event-operations-collector.js';
2
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../../builtin-metadata.js';
2
3
 
3
4
  /**
4
5
  * ON builtin for form events
@@ -18,6 +19,15 @@ import { __collectEventOperation } from '../event-operations-collector.js';
18
19
  * // Register field-specific event handler
19
20
  * ON('change', 'city', function(event) { ALERT('City changed!'); });
20
21
  */
22
+ export const ON_METADATA = defineBuiltinMetadata({
23
+ name: 'ON',
24
+ category: 'event',
25
+ signature: 'ON(eventType, fieldKeyOrCallback, callback)',
26
+ description: 'Register an event handler within form event code.',
27
+ examples: ["ON('change', 'city', function(event) { ALERT('City changed!'); })"],
28
+ contexts: [BUILTIN_CONTEXTS.EVENT],
29
+ });
30
+
21
31
  export function ON(eventType, fieldKeyOrCallback, callback) {
22
32
  let fieldKey = '*';
23
33
  let actualCallback = fieldKeyOrCallback;
@@ -1,4 +1,5 @@
1
1
  import { __collectEventOperation } from '../event-operations-collector.js';
2
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../../builtin-metadata.js';
2
3
 
3
4
  /**
4
5
  * SETVALUE builtin for form events
@@ -30,6 +31,15 @@ import { __collectEventOperation } from '../event-operations-collector.js';
30
31
  * // Set MultiChoiceField value
31
32
  * SETVALUE('field_dataname', ['value1', 'value2', 'value3'])
32
33
  */
34
+ export const SETVALUE_METADATA = defineBuiltinMetadata({
35
+ name: 'SETVALUE',
36
+ category: 'event',
37
+ signature: 'SETVALUE(fieldDataName, valueToSet)',
38
+ description: 'Set a field value from a form event handler.',
39
+ examples: ["SETVALUE('field_dataname', 'value_to_set')"],
40
+ contexts: [BUILTIN_CONTEXTS.EVENT],
41
+ });
42
+
33
43
  export function SETVALUE(fieldDataName, valueToSet) {
34
44
  // Create operation descriptor
35
45
  const operation = {
@@ -1,4 +1,5 @@
1
1
  import { __collectEventOperation } from '../event-operations-collector.js';
2
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../../builtin-metadata.js';
2
3
 
3
4
  /**
4
5
  * ALERT builtin for form events
@@ -7,6 +8,15 @@ import { __collectEventOperation } from '../event-operations-collector.js';
7
8
  * @param {string} message - The message to display in the alert (optional)
8
9
  * @returns {Object} Operation descriptor for platform execution (for backward compatibility)
9
10
  */
11
+ export const ALERT_METADATA = defineBuiltinMetadata({
12
+ name: 'ALERT',
13
+ category: 'event',
14
+ signature: "ALERT(title, message = '')",
15
+ description: 'Display an alert from a form event handler.',
16
+ examples: ["ALERT('Saved', 'The record was saved successfully.')"],
17
+ contexts: [BUILTIN_CONTEXTS.EVENT],
18
+ });
19
+
10
20
  export function ALERT(title, message = '') {
11
21
  // Create operation descriptor
12
22
  const operation = {
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin AND
3
5
  * @description Logical AND operation that returns true only if all arguments are truthy
@@ -10,4 +12,13 @@
10
12
  * // Multiple conditions
11
13
  * AND(name.length > 0, email.includes("@"), age >= 13)
12
14
  */
15
+ export const AND_METADATA = defineBuiltinMetadata({
16
+ name: 'AND',
17
+ category: 'logical',
18
+ signature: 'AND(...conditions)',
19
+ description: 'Return true only when all arguments are truthy.',
20
+ examples: ['AND($age >= 18, $country === "it")'],
21
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
22
+ });
23
+
13
24
  export const AND = (...args) => args.every(Boolean);
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin ARRAY
3
5
  * @description Returns an array from its arguments. Can parse string representations of arrays (with single or double quotes) and comma-separated values.
@@ -28,6 +30,15 @@
28
30
  * // For complex parsing, JSON.parse() can be used:
29
31
  * // EVAL('JSON.parse("[1,2,3]")')
30
32
  */
33
+ export const ARRAY_METADATA = defineBuiltinMetadata({
34
+ name: 'ARRAY',
35
+ category: 'logical',
36
+ signature: 'ARRAY(...values)',
37
+ description: 'Build an array from individual arguments.',
38
+ examples: ['ARRAY($city, $country)'],
39
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
40
+ });
41
+
31
42
  export const ARRAY = (...args) => {
32
43
  // Handle empty arguments
33
44
  if (args.length === 0) {
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin COUNT
3
5
  * @description Returns a count of the number of numeric values in a dataset
@@ -13,6 +15,15 @@
13
15
  * // Returns 3 (mixed array)
14
16
  * COUNT([1, 'a', 2, null, 3])
15
17
  */
18
+ export const COUNT_METADATA = defineBuiltinMetadata({
19
+ name: 'COUNT',
20
+ category: 'logical',
21
+ signature: 'COUNT(values)',
22
+ description: 'Count numeric values.',
23
+ examples: ['COUNT(ARRAY($score_1, $score_2, $score_3))'],
24
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
25
+ });
26
+
16
27
  export const COUNT = (values) => {
17
28
  // Handle null/undefined input
18
29
  if (!Array.isArray(values)) {
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin COUNTA
3
5
  * @description Returns a count of values in a dataset
@@ -13,6 +15,15 @@
13
15
  * // Returns 4 (counts all items including null)
14
16
  * COUNTA([1, 'a', null, true])
15
17
  */
18
+ export const COUNTA_METADATA = defineBuiltinMetadata({
19
+ name: 'COUNTA',
20
+ category: 'logical',
21
+ signature: 'COUNTA(values)',
22
+ description: 'Count non-empty values.',
23
+ examples: ['COUNTA(ARRAY($first_name, $last_name, $email))'],
24
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
25
+ });
26
+
16
27
  export const COUNTA = (values) => {
17
28
  // Handle null/undefined input
18
29
  if (!Array.isArray(values)) {
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin COUNTBLANK
3
5
  * @description Returns the number of blank values in a dataset
@@ -13,6 +15,15 @@
13
15
  * // Returns 0 (no blank values)
14
16
  * COUNTBLANK([1, 2, 'a', true])
15
17
  */
18
+ export const COUNTBLANK_METADATA = defineBuiltinMetadata({
19
+ name: 'COUNTBLANK',
20
+ category: 'logical',
21
+ signature: 'COUNTBLANK(values)',
22
+ description: 'Count blank values.',
23
+ examples: ['COUNTBLANK(ARRAY($first_name, $last_name, $email))'],
24
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
25
+ });
26
+
16
27
  export const COUNTBLANK = (values) => {
17
28
  // Handle null/undefined input
18
29
  if (!Array.isArray(values)) {
@@ -20,7 +31,5 @@ export const COUNTBLANK = (values) => {
20
31
  }
21
32
 
22
33
  // Count null, undefined, and empty strings as blank
23
- return values.filter(
24
- (value) => value === null || value === undefined || value === ''
25
- ).length;
34
+ return values.filter((value) => value === null || value === undefined || value === '').length;
26
35
  };
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin IF
3
5
  * @description Conditional logic function that returns one of two values based on a condition
@@ -12,4 +14,13 @@
12
14
  * // Nested conditions for shipping cost
13
15
  * IF(country === "US", IF(state === "CA", 8.99, 5.99), 15.99)
14
16
  */
17
+ export const IF_METADATA = defineBuiltinMetadata({
18
+ name: 'IF',
19
+ category: 'logical',
20
+ signature: 'IF(condition, trueValue, falseValue)',
21
+ description: 'Return one of two values based on a condition.',
22
+ examples: ['IF($age >= 18, "adult", "minor")'],
23
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
24
+ });
25
+
15
26
  export const IF = (cond, a, b) => (cond ? a : b);
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin OR
3
5
  * @description Logical OR operation that returns true if at least one argument is truthy
@@ -10,4 +12,13 @@
10
12
  * // Validation - either email or phone is required
11
13
  * OR(email.length > 0, phone.length > 0)
12
14
  */
15
+ export const OR_METADATA = defineBuiltinMetadata({
16
+ name: 'OR',
17
+ category: 'logical',
18
+ signature: 'OR(...conditions)',
19
+ description: 'Return true when at least one argument is truthy.',
20
+ examples: ['OR($email, $phone)'],
21
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
22
+ });
23
+
13
24
  export const OR = (...args) => args.some(Boolean);
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin ABS
3
5
  * @description Returns the absolute value of a number
@@ -13,4 +15,13 @@
13
15
  * // Returns 3.14
14
16
  * ABS(-3.14)
15
17
  */
18
+ export const ABS_METADATA = defineBuiltinMetadata({
19
+ name: 'ABS',
20
+ category: 'math',
21
+ signature: 'ABS(value)',
22
+ description: 'Return the absolute value of a number.',
23
+ examples: ['ABS($variance)'],
24
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
25
+ });
26
+
16
27
  export const ABS = (value) => Math.abs(value);
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin CEILING
3
5
  * @description Rounds a value up to the nearest integer multiple of factor
@@ -14,6 +16,15 @@
14
16
  * // Returns 15
15
17
  * CEILING(12.3, 5)
16
18
  */
19
+ export const CEILING_METADATA = defineBuiltinMetadata({
20
+ name: 'CEILING',
21
+ category: 'math',
22
+ signature: 'CEILING(value, factor)',
23
+ description: 'Round a number up to the nearest multiple.',
24
+ examples: ['CEILING($amount, 5)'],
25
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
26
+ });
27
+
17
28
  export const CEILING = (value, factor = 1) => {
18
29
  if (factor === 0) {
19
30
  throw new Error('CEILING factor cannot be zero');
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin COS
3
5
  * @description Returns the cosine of a value, in radians
@@ -13,4 +15,13 @@
13
15
  * // Returns -1
14
16
  * COS(Math.PI)
15
17
  */
16
- export const COS = (value) => Math.cos(value);
18
+ export const COS_METADATA = defineBuiltinMetadata({
19
+ name: 'COS',
20
+ category: 'math',
21
+ signature: 'COS(value)',
22
+ description: 'Return the cosine of a value in radians.',
23
+ examples: ['COS($angle_radians)'],
24
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
25
+ });
26
+
27
+ export const COS = (value) => Math.cos(value);
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin ROUND
3
5
  * @description Rounds a number to a specified number of decimal places according to standard rounding rules
@@ -17,11 +19,20 @@
17
19
  * // Returns 3.14
18
20
  * ROUND(3.14159, 2)
19
21
  */
22
+ export const ROUND_METADATA = defineBuiltinMetadata({
23
+ name: 'ROUND',
24
+ category: 'math',
25
+ signature: 'ROUND(value, places)',
26
+ description: 'Round a number to a fixed number of decimal places.',
27
+ examples: ['ROUND($total, 2)'],
28
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
29
+ });
30
+
20
31
  export const ROUND = (value, places) => {
21
32
  if (typeof value !== 'number' || typeof places !== 'number') {
22
33
  throw new Error('ROUND requires two numeric arguments');
23
34
  }
24
-
35
+
25
36
  const multiplier = Math.pow(10, places);
26
37
  return Math.round(value * multiplier) / multiplier;
27
- };
38
+ };
@@ -1,3 +1,5 @@
1
+ import { BUILTIN_CONTEXTS, defineBuiltinMetadata } from '../builtin-metadata.js';
2
+
1
3
  /**
2
4
  * @builtin SIN
3
5
  * @description Returns the sine of a value, in radians
@@ -13,4 +15,13 @@
13
15
  * // Returns 1
14
16
  * SIN(Math.PI / 2)
15
17
  */
16
- export const SIN = (value) => Math.sin(value);
18
+ export const SIN_METADATA = defineBuiltinMetadata({
19
+ name: 'SIN',
20
+ category: 'math',
21
+ signature: 'SIN(value)',
22
+ description: 'Return the sine of a value in radians.',
23
+ examples: ['SIN($angle_radians)'],
24
+ contexts: [BUILTIN_CONTEXTS.CALCULATION, BUILTIN_CONTEXTS.EVENT],
25
+ });
26
+
27
+ export const SIN = (value) => Math.sin(value);