@halleyassist/rule-templater 0.0.17 → 0.0.19

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,5 +1,5 @@
1
1
  (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.RuleTemplate = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
2
- module.exports=[{"name":"statement_main","bnf":[["statement","EOF"]]},{"name":"logical_operator","bnf":[["AND"],["OR"]]},{"name":"%statement[2]","bnf":[["logical_operator","expression"]],"fragment":true},{"name":"statement","bnf":[["expression","%statement[2]*"]]},{"name":"expression","bnf":[["not_expression"],["standard_expression"],["parenthesis_expression"]]},{"name":"parenthesis_expression","bnf":[["BEGIN_PARENTHESIS","WS*","statement","WS*","END_PARENTHESIS"]]},{"name":"%not_expression[2]","bnf":[["result"],["parenthesis_expression"]],"fragment":true},{"name":"not_expression","bnf":[["NOT","%not_expression[2]"]]},{"name":"%standard_expression[2][1]","bnf":[["WS*","eq_approx"]],"fragment":true},{"name":"%standard_expression[2][2]","bnf":[["WS*","basic_rhs"]],"fragment":true},{"name":"%standard_expression[2][3][1]","bnf":[["WS+","IS"]],"fragment":true},{"name":"%standard_expression[2][3]","bnf":[["%standard_expression[2][3][1]?","WS+","between"]],"fragment":true},{"name":"%standard_expression[2][4]","bnf":[["WS+","in_expr"]],"fragment":true},{"name":"%standard_expression[2]","bnf":[["%standard_expression[2][1]"],["%standard_expression[2][2]"],["%standard_expression[2][3]"],["%standard_expression[2][4]"]],"fragment":true},{"name":"standard_expression","bnf":[["result","%standard_expression[2]?"]]},{"name":"basic_rhs","bnf":[["operator","WS*","result"]]},{"name":"eq_approx","bnf":[["eq_operator","WS*","\"~\"","WS*","result"]]},{"name":"PLUS","bnf":[["\"+\""]]},{"name":"MINUS","bnf":[["\"-\""]]},{"name":"MULTIPLY","bnf":[["\"*\""]]},{"name":"DIVIDE","bnf":[["\"/\""]]},{"name":"MODULUS","bnf":[["\"%\""]]},{"name":"DEFAULT_VAL","bnf":[["\"??\""]]},{"name":"arithmetic_operator","bnf":[["PLUS"],["MINUS"],["MULTIPLY"],["DIVIDE"],["MODULUS"],["DEFAULT_VAL"]]},{"name":"number_atom","bnf":[["number"]]},{"name":"number_time_atom","bnf":[["number_time"]]},{"name":"tod_atom","bnf":[["number_tod"]]},{"name":"dow_atom","bnf":[["dow"]]},{"name":"arithmetic_operand","bnf":[["fcall"],["number_time_atom"],["number_atom"]]},{"name":"%arithmetic_result[5]","bnf":[["arithmetic_result"],["arithmetic_operand"]],"fragment":true},{"name":"arithmetic_result","bnf":[["arithmetic_operand","WS*","arithmetic_operator","WS*","%arithmetic_result[5]"]]},{"name":"simple_result","bnf":[["fcall"],["value"]]},{"name":"result","bnf":[["arithmetic_result"],["simple_result"]]},{"name":"value_atom","bnf":[["false"],["true"],["array"],["time_period"],["number_time_atom"],["number_atom"],["tod_atom"],["string"]]},{"name":"value","bnf":[["value_atom"]]},{"name":"BEGIN_ARRAY","bnf":[["WS*",/\x5B/,"WS*"]]},{"name":"BEGIN_OBJECT","bnf":[["WS*",/\x7B/,"WS*"]]},{"name":"END_ARRAY","bnf":[["WS*",/\x5D/,"WS*"]]},{"name":"END_OBJECT","bnf":[["WS*",/\x7D/,"WS*"]]},{"name":"NAME_SEPARATOR","bnf":[["WS*",/\x3A/,"WS*"]]},{"name":"VALUE_SEPARATOR","bnf":[["WS*",/\x2C/,"WS*"]]},{"name":"WS","bnf":[[/[\x20\x09\x0A\x0D]/]]},{"name":"operator","bnf":[["GTE"],["LTE"],["GT"],["LT"],["EQ"],["NEQ"]]},{"name":"eq_operator","bnf":[["EQ"],["NEQ"]]},{"name":"BEGIN_ARGUMENT","bnf":[["\"(\""]]},{"name":"END_ARGUMENT","bnf":[["\")\""]]},{"name":"BEGIN_PARENTHESIS","bnf":[["\"(\""]]},{"name":"END_PARENTHESIS","bnf":[["\")\""]]},{"name":"BEGIN_IN","bnf":[[/[Ii]/,/[Nn]/]]},{"name":"in_expr","bnf":[["BEGIN_IN","WS*","BEGIN_PARENTHESIS","WS*","arguments","END_PARENTHESIS"]]},{"name":"argument","bnf":[["statement","WS*"]]},{"name":"%arguments[2]","bnf":[["WS*","\",\"","WS*","argument"]],"fragment":true},{"name":"arguments","bnf":[["argument","%arguments[2]*"]]},{"name":"%fname[1]","bnf":[[/[A-Za-z0-9]/]]},{"name":"fname","bnf":[["%fname[1]+"]]},{"name":"fcall","bnf":[["fname","WS*","BEGIN_ARGUMENT","WS*","arguments?","END_ARGUMENT"]]},{"name":"%between_dash_or_and[1]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_dash_or_and[2]","bnf":[["WS*",/\-/,"WS*"]],"fragment":true},{"name":"between_dash_or_and","bnf":[["%between_dash_or_and[1]"],["%between_dash_or_and[2]"]]},{"name":"between_number_inner","bnf":[["number_atom"],["number_time_atom"]]},{"name":"between_number","bnf":[["between_number_inner","between_dash_or_and","between_number_inner"]]},{"name":"between_number_time_inner","bnf":[["number_time_atom"]]},{"name":"%between_number_time[4]","bnf":[["WS+","dow_range"]],"fragment":true},{"name":"between_number_time","bnf":[["between_number_time_inner","between_dash_or_and","between_number_time_inner","%between_number_time[4]?"]]},{"name":"between_tod_inner","bnf":[["tod_atom"]]},{"name":"%between_tod[2]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_tod[4]","bnf":[["WS+","dow_range"]],"fragment":true},{"name":"between_tod","bnf":[["between_tod_inner","%between_tod[2]","between_tod_inner","%between_tod[4]?"]]},{"name":"%between[3]","bnf":[["between_number"],["between_tod"]],"fragment":true},{"name":"between","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","%between[3]"]]},{"name":"dow","bnf":[[/[Mm]/,/[Oo]/,/[Nn]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Mm]/,/[Oo]/,/[Nn]/],[/[Tt]/,/[Uu]/,/[Ee]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Tt]/,/[Uu]/,/[Ee]/],[/[Ww]/,/[Ee]/,/[Dd]/,/[Nn]/,/[Ee]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ww]/,/[Ee]/,/[Dd]/],[/[Tt]/,/[Hh]/,/[Uu]/,/[Rr]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Tt]/,/[Hh]/,/[Uu]/],[/[Tt]/,/[Hh]/,/[Uu]/,/[Rr]/],[/[Ff]/,/[Rr]/,/[Ii]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ff]/,/[Rr]/,/[Ii]/],[/[Ss]/,/[Aa]/,/[Tt]/,/[Uu]/,/[Rr]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ss]/,/[Aa]/,/[Tt]/],[/[Ss]/,/[Uu]/,/[Nn]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ss]/,/[Uu]/,/[Nn]/]]},{"name":"dow_range_inner","bnf":[["dow_atom"]]},{"name":"%dow_range[4]","bnf":[["WS+",/[Tt]/,/[Oo]/,"WS+","dow_range_inner"]],"fragment":true},{"name":"dow_range","bnf":[[/[Oo]/,/[Nn]/,"WS+","dow_range_inner","%dow_range[4]?"]]},{"name":"between_time_only","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","between_number_time"]]},{"name":"between_tod_only","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","between_tod"]]},{"name":"between_time_only_atom","bnf":[["between_time_only"]]},{"name":"between_tod_only_atom","bnf":[["between_tod_only"]]},{"name":"%AND[1]","bnf":[["WS*",/&/,/&/,"WS*"]],"fragment":true},{"name":"%AND[2]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"AND","bnf":[["%AND[1]"],["%AND[2]"]]},{"name":"%OR[1]","bnf":[["WS*",/\|/,/\|/,"WS*"]],"fragment":true},{"name":"%OR[2]","bnf":[["WS+",/[Oo]/,/[Rr]/,"WS+"]],"fragment":true},{"name":"OR","bnf":[["%OR[1]"],["%OR[2]"]]},{"name":"AGO","bnf":[[/[Aa]/,/[Gg]/,/[Oo]/]]},{"name":"GT","bnf":[["\">\""]]},{"name":"LT","bnf":[["\"<\""]]},{"name":"GTE","bnf":[["\">=\""]]},{"name":"LTE","bnf":[["\"<=\""]]},{"name":"IS","bnf":[[/[Ii]/,/[Ss]/]]},{"name":"EQ","bnf":[["\"==\""],["\"=\""]]},{"name":"NEQ","bnf":[["\"!=\""]]},{"name":"%NOT[1]","bnf":[[/!/,"WS*"]],"fragment":true},{"name":"%NOT[2]","bnf":[[/[Nn]/,/[Oo]/,/[Tt]/,"WS+"]],"fragment":true},{"name":"NOT","bnf":[["%NOT[1]"],["%NOT[2]"]]},{"name":"false","bnf":[[/[Ff]/,/[Aa]/,/[Ll]/,/[Ss]/,/[Ee]/]]},{"name":"null","bnf":[[/[Nn]/,/[Uu]/,/[Ll]/,/[Ll]/]]},{"name":"true","bnf":[[/[Tt]/,/[Rr]/,/[Uu]/,/[Ee]/]]},{"name":"%array[2][2]","bnf":[["VALUE_SEPARATOR","value"]],"fragment":true},{"name":"%array[2]","bnf":[["value","%array[2][2]*"]],"fragment":true},{"name":"array","bnf":[["BEGIN_ARRAY","%array[2]?","END_ARRAY"]]},{"name":"unit","bnf":[[/[Ss]/,/[Ee]/,/[Cc]/,/[Oo]/,/[Nn]/,/[Dd]/,/[Ss]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Uu]/,/[Tt]/,/[Ee]/,/[Ss]/],[/[Hh]/,/[Oo]/,/[Uu]/,/[Rr]/,/[Ss]/],[/[Ww]/,/[Ee]/,/[Ee]/,/[Kk]/,/[Ss]/],[/[Dd]/,/[Aa]/,/[Yy]/,/[Ss]/],[/[Ss]/,/[Ee]/,/[Cc]/,/[Oo]/,/[Nn]/,/[Dd]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Uu]/,/[Tt]/,/[Ee]/],[/[Ww]/,/[Ee]/,/[Ee]/,/[Kk]/],[/[Hh]/,/[Oo]/,/[Uu]/,/[Rr]/],[/[Dd]/,/[Aa]/,/[Yy]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Ss]/],[/[Mm]/,/[Ii]/,/[Nn]/]]},{"name":"%number[2][1]","bnf":[[/[0-9]/]]},{"name":"%number[2]","bnf":[["%number[2][1]+"]],"fragment":true},{"name":"%number[3][2]","bnf":[[/[0-9]/]]},{"name":"%number[3]","bnf":[["\".\"","%number[3][2]+"]],"fragment":true},{"name":"%number[4][2]","bnf":[["\"-\""],["\"+\""]],"fragment":true},{"name":"%number[4][3][2]","bnf":[[/[0-9]/]]},{"name":"%number[4][3]","bnf":[["\"0\""],[/[1-9]/,"%number[4][3][2]*"]],"fragment":true},{"name":"%number[4]","bnf":[["\"e\"","%number[4][2]?","%number[4][3]"]],"fragment":true},{"name":"number","bnf":[["\"-\"?","%number[2]","%number[3]?","%number[4]?"]]},{"name":"number_time","bnf":[["number","WS+","unit"]]},{"name":"%number_tod[1][1]","bnf":[[/[0-9]/]]},{"name":"%number_tod[1]","bnf":[["%number_tod[1][1]+"]],"fragment":true},{"name":"%number_tod[3][1]","bnf":[[/[0-9]/]]},{"name":"%number_tod[3]","bnf":[["%number_tod[3][1]+"]],"fragment":true},{"name":"number_tod","bnf":[["%number_tod[1]","\":\"","%number_tod[3]"]]},{"name":"%time_period_ago[2]","bnf":[["WS+","number_time_atom"]],"fragment":true},{"name":"time_period_ago","bnf":[["number_time_atom","%time_period_ago[2]*","WS+","AGO"]]},{"name":"%time_period_ago_between[2]","bnf":[["WS+","number_time_atom"]],"fragment":true},{"name":"%time_period_ago_between[6]","bnf":[["between_time_only_atom"],["between_tod_only_atom"]],"fragment":true},{"name":"time_period_ago_between","bnf":[["number_time_atom","%time_period_ago_between[2]*","WS+","AGO","WS+","%time_period_ago_between[6]"]]},{"name":"time_period_const","bnf":[[/[Tt]/,/[Oo]/,/[Dd]/,/[Aa]/,/[Yy]/],["time_period_ago"]]},{"name":"time_period","bnf":[["time_period_ago_between"],["time_period_const"],["between_tod_only"],["between_time_only"]]},{"name":"%string[2][1]","bnf":[[/[\x20-\x21]/],[/[\x23-\x5B]/],[/[\x5D-\uFFFF]/]],"fragment":true},{"name":"%string[2][2]","bnf":[[/\x22/],[/\x5C/],[/\x2F/],[/\x62/],[/\x66/],[/\x6E/],[/\x72/],[/\x74/],[/\x75/,"HEXDIG","HEXDIG","HEXDIG","HEXDIG"]],"fragment":true},{"name":"%string[2]","bnf":[["%string[2][1]"],[/\x5C/,"%string[2][2]"]],"fragment":true},{"name":"string","bnf":[["'\"'","%string[2]*","'\"'"]]},{"name":"HEXDIG","bnf":[[/[a-fA-F0-9]/]]}]
2
+ module.exports=[{"name":"statement_main","bnf":[["statement","EOF"]]},{"name":"logical_operator","bnf":[["AND"],["OR"]]},{"name":"%statement[2]","bnf":[["logical_operator","expression"]],"fragment":true},{"name":"statement","bnf":[["expression","%statement[2]*"]]},{"name":"expression","bnf":[["not_expression"],["standard_expression"],["parenthesis_expression"]]},{"name":"parenthesis_expression","bnf":[["BEGIN_PARENTHESIS","WS*","statement","WS*","END_PARENTHESIS"]]},{"name":"%not_expression[2]","bnf":[["result"],["parenthesis_expression"]],"fragment":true},{"name":"not_expression","bnf":[["NOT","%not_expression[2]"]]},{"name":"%standard_expression[2][1]","bnf":[["WS*","eq_approx"]],"fragment":true},{"name":"%standard_expression[2][2]","bnf":[["WS*","basic_rhs"]],"fragment":true},{"name":"%standard_expression[2][3][1]","bnf":[["WS+","IS"]],"fragment":true},{"name":"%standard_expression[2][3]","bnf":[["%standard_expression[2][3][1]?","WS+","between"]],"fragment":true},{"name":"%standard_expression[2][4]","bnf":[["WS+","in_expr"]],"fragment":true},{"name":"%standard_expression[2]","bnf":[["%standard_expression[2][1]"],["%standard_expression[2][2]"],["%standard_expression[2][3]"],["%standard_expression[2][4]"]],"fragment":true},{"name":"standard_expression","bnf":[["result","%standard_expression[2]?"]]},{"name":"basic_rhs","bnf":[["operator","WS*","result"]]},{"name":"eq_approx","bnf":[["eq_operator","WS*","\"~\"","WS*","result"]]},{"name":"PLUS","bnf":[["\"+\""]]},{"name":"MINUS","bnf":[["\"-\""]]},{"name":"MULTIPLY","bnf":[["\"*\""]]},{"name":"DIVIDE","bnf":[["\"/\""]]},{"name":"MODULUS","bnf":[["\"%\""]]},{"name":"DEFAULT_VAL","bnf":[["\"??\""]]},{"name":"arithmetic_operator","bnf":[["PLUS"],["MINUS"],["MULTIPLY"],["DIVIDE"],["MODULUS"],["DEFAULT_VAL"]]},{"name":"number_atom","bnf":[["number"]]},{"name":"number_time_atom","bnf":[["number_time"]]},{"name":"tod_atom","bnf":[["number_tod"]]},{"name":"dow_atom","bnf":[["dow"]]},{"name":"arithmetic_operand","bnf":[["fcall"],["parenthesis_expression"],["number_time_atom"],["number_atom"]]},{"name":"%arithmetic_result[5]","bnf":[["arithmetic_result"],["arithmetic_operand"]],"fragment":true},{"name":"arithmetic_result","bnf":[["arithmetic_operand","WS*","arithmetic_operator","WS*","%arithmetic_result[5]"]]},{"name":"simple_result","bnf":[["fcall"],["value"]]},{"name":"result","bnf":[["arithmetic_result"],["simple_result"]]},{"name":"value_atom","bnf":[["false"],["true"],["array"],["time_period"],["number_time_atom"],["number_atom"],["tod_atom"],["string"]]},{"name":"value","bnf":[["value_atom"]]},{"name":"BEGIN_ARRAY","bnf":[["WS*",/\x5B/,"WS*"]]},{"name":"BEGIN_OBJECT","bnf":[["WS*",/\x7B/,"WS*"]]},{"name":"END_ARRAY","bnf":[["WS*",/\x5D/,"WS*"]]},{"name":"END_OBJECT","bnf":[["WS*",/\x7D/,"WS*"]]},{"name":"NAME_SEPARATOR","bnf":[["WS*",/\x3A/,"WS*"]]},{"name":"VALUE_SEPARATOR","bnf":[["WS*",/\x2C/,"WS*"]]},{"name":"WS","bnf":[[/[\x20\x09\x0A\x0D]/]]},{"name":"operator","bnf":[["GTE"],["LTE"],["GT"],["LT"],["EQ"],["NEQ"]]},{"name":"eq_operator","bnf":[["EQ"],["NEQ"]]},{"name":"BEGIN_ARGUMENT","bnf":[["\"(\""]]},{"name":"END_ARGUMENT","bnf":[["\")\""]]},{"name":"BEGIN_PARENTHESIS","bnf":[["\"(\""]]},{"name":"END_PARENTHESIS","bnf":[["\")\""]]},{"name":"BEGIN_IN","bnf":[[/[Ii]/,/[Nn]/]]},{"name":"in_expr","bnf":[["BEGIN_IN","WS*","BEGIN_PARENTHESIS","WS*","arguments","END_PARENTHESIS"]]},{"name":"argument","bnf":[["statement","WS*"]]},{"name":"%arguments[2]","bnf":[["WS*","\",\"","WS*","argument"]],"fragment":true},{"name":"arguments","bnf":[["argument","%arguments[2]*"]]},{"name":"%fname[1]","bnf":[[/[A-Za-z0-9]/]]},{"name":"fname","bnf":[["%fname[1]+"]]},{"name":"fcall","bnf":[["fname","WS*","BEGIN_ARGUMENT","WS*","arguments?","END_ARGUMENT"]]},{"name":"%between_dash_or_and[1]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_dash_or_and[2]","bnf":[["WS*",/\-/,"WS*"]],"fragment":true},{"name":"between_dash_or_and","bnf":[["%between_dash_or_and[1]"],["%between_dash_or_and[2]"]]},{"name":"between_number_inner","bnf":[["number_atom"],["number_time_atom"]]},{"name":"between_number","bnf":[["between_number_inner","between_dash_or_and","between_number_inner"]]},{"name":"between_number_time_inner","bnf":[["number_time_atom"]]},{"name":"%between_number_time[4]","bnf":[["WS+","dow_range"]],"fragment":true},{"name":"between_number_time","bnf":[["between_number_time_inner","between_dash_or_and","between_number_time_inner","%between_number_time[4]?"]]},{"name":"between_tod_inner","bnf":[["tod_atom"]]},{"name":"%between_tod[2]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_tod[4]","bnf":[["WS+","dow_range"]],"fragment":true},{"name":"between_tod","bnf":[["between_tod_inner","%between_tod[2]","between_tod_inner","%between_tod[4]?"]]},{"name":"%between[3]","bnf":[["between_number"],["between_tod"]],"fragment":true},{"name":"between","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","%between[3]"]]},{"name":"dow","bnf":[[/[Mm]/,/[Oo]/,/[Nn]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Mm]/,/[Oo]/,/[Nn]/],[/[Tt]/,/[Uu]/,/[Ee]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Tt]/,/[Uu]/,/[Ee]/],[/[Ww]/,/[Ee]/,/[Dd]/,/[Nn]/,/[Ee]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ww]/,/[Ee]/,/[Dd]/],[/[Tt]/,/[Hh]/,/[Uu]/,/[Rr]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Tt]/,/[Hh]/,/[Uu]/],[/[Tt]/,/[Hh]/,/[Uu]/,/[Rr]/],[/[Ff]/,/[Rr]/,/[Ii]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ff]/,/[Rr]/,/[Ii]/],[/[Ss]/,/[Aa]/,/[Tt]/,/[Uu]/,/[Rr]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ss]/,/[Aa]/,/[Tt]/],[/[Ss]/,/[Uu]/,/[Nn]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ss]/,/[Uu]/,/[Nn]/]]},{"name":"dow_range_inner","bnf":[["dow_atom"]]},{"name":"%dow_range[4]","bnf":[["WS+",/[Tt]/,/[Oo]/,"WS+","dow_range_inner"]],"fragment":true},{"name":"dow_range","bnf":[[/[Oo]/,/[Nn]/,"WS+","dow_range_inner","%dow_range[4]?"]]},{"name":"between_time_only","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","between_number_time"]]},{"name":"between_tod_only","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","between_tod"]]},{"name":"between_time_only_atom","bnf":[["between_time_only"]]},{"name":"between_tod_only_atom","bnf":[["between_tod_only"]]},{"name":"time_period_atom","bnf":[["between_tod_only"],["between_time_only"]]},{"name":"time_period_ago_atom","bnf":[["time_period_ago_between"]]},{"name":"%AND[1]","bnf":[["WS*",/&/,/&/,"WS*"]],"fragment":true},{"name":"%AND[2]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"AND","bnf":[["%AND[1]"],["%AND[2]"]]},{"name":"%OR[1]","bnf":[["WS*",/\|/,/\|/,"WS*"]],"fragment":true},{"name":"%OR[2]","bnf":[["WS+",/[Oo]/,/[Rr]/,"WS+"]],"fragment":true},{"name":"OR","bnf":[["%OR[1]"],["%OR[2]"]]},{"name":"AGO","bnf":[[/[Aa]/,/[Gg]/,/[Oo]/]]},{"name":"GT","bnf":[["\">\""]]},{"name":"LT","bnf":[["\"<\""]]},{"name":"GTE","bnf":[["\">=\""]]},{"name":"LTE","bnf":[["\"<=\""]]},{"name":"IS","bnf":[[/[Ii]/,/[Ss]/]]},{"name":"EQ","bnf":[["\"==\""],["\"=\""]]},{"name":"NEQ","bnf":[["\"!=\""]]},{"name":"%NOT[1]","bnf":[[/!/,"WS*"]],"fragment":true},{"name":"%NOT[2]","bnf":[[/[Nn]/,/[Oo]/,/[Tt]/,"WS+"]],"fragment":true},{"name":"NOT","bnf":[["%NOT[1]"],["%NOT[2]"]]},{"name":"false","bnf":[[/[Ff]/,/[Aa]/,/[Ll]/,/[Ss]/,/[Ee]/]]},{"name":"null","bnf":[[/[Nn]/,/[Uu]/,/[Ll]/,/[Ll]/]]},{"name":"true","bnf":[[/[Tt]/,/[Rr]/,/[Uu]/,/[Ee]/]]},{"name":"%array[2][2]","bnf":[["VALUE_SEPARATOR","value"]],"fragment":true},{"name":"%array[2]","bnf":[["value","%array[2][2]*"]],"fragment":true},{"name":"array","bnf":[["BEGIN_ARRAY","%array[2]?","END_ARRAY"]]},{"name":"unit","bnf":[[/[Ss]/,/[Ee]/,/[Cc]/,/[Oo]/,/[Nn]/,/[Dd]/,/[Ss]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Uu]/,/[Tt]/,/[Ee]/,/[Ss]/],[/[Hh]/,/[Oo]/,/[Uu]/,/[Rr]/,/[Ss]/],[/[Ww]/,/[Ee]/,/[Ee]/,/[Kk]/,/[Ss]/],[/[Dd]/,/[Aa]/,/[Yy]/,/[Ss]/],[/[Ss]/,/[Ee]/,/[Cc]/,/[Oo]/,/[Nn]/,/[Dd]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Uu]/,/[Tt]/,/[Ee]/],[/[Ww]/,/[Ee]/,/[Ee]/,/[Kk]/],[/[Hh]/,/[Oo]/,/[Uu]/,/[Rr]/],[/[Dd]/,/[Aa]/,/[Yy]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Ss]/],[/[Mm]/,/[Ii]/,/[Nn]/]]},{"name":"%number[2][1]","bnf":[[/[0-9]/]]},{"name":"%number[2]","bnf":[["%number[2][1]+"]],"fragment":true},{"name":"%number[3][2]","bnf":[[/[0-9]/]]},{"name":"%number[3]","bnf":[["\".\"","%number[3][2]+"]],"fragment":true},{"name":"%number[4][2]","bnf":[["\"-\""],["\"+\""]],"fragment":true},{"name":"%number[4][3][2]","bnf":[[/[0-9]/]]},{"name":"%number[4][3]","bnf":[["\"0\""],[/[1-9]/,"%number[4][3][2]*"]],"fragment":true},{"name":"%number[4]","bnf":[["\"e\"","%number[4][2]?","%number[4][3]"]],"fragment":true},{"name":"number","bnf":[["\"-\"?","%number[2]","%number[3]?","%number[4]?"]]},{"name":"number_time","bnf":[["number","WS+","unit"]]},{"name":"%number_tod[1][1]","bnf":[[/[0-9]/]]},{"name":"%number_tod[1]","bnf":[["%number_tod[1][1]+"]],"fragment":true},{"name":"%number_tod[3][1]","bnf":[[/[0-9]/]]},{"name":"%number_tod[3]","bnf":[["%number_tod[3][1]+"]],"fragment":true},{"name":"number_tod","bnf":[["%number_tod[1]","\":\"","%number_tod[3]"]]},{"name":"%time_period_ago[2]","bnf":[["WS+","number_time_atom"]],"fragment":true},{"name":"time_period_ago","bnf":[["number_time_atom","%time_period_ago[2]*","WS+","AGO"]]},{"name":"%time_period_ago_between[2]","bnf":[["WS+","number_time_atom"]],"fragment":true},{"name":"%time_period_ago_between[6]","bnf":[["between_time_only_atom"],["between_tod_only_atom"]],"fragment":true},{"name":"time_period_ago_between","bnf":[["number_time_atom","%time_period_ago_between[2]*","WS+","AGO","WS+","%time_period_ago_between[6]"]]},{"name":"time_period_const","bnf":[[/[Tt]/,/[Oo]/,/[Dd]/,/[Aa]/,/[Yy]/],["time_period_ago"]]},{"name":"time_period","bnf":[["time_period_ago_atom"],["time_period_const"],["time_period_atom"]]},{"name":"%string[2][1]","bnf":[[/[\x20-\x21]/],[/[\x23-\x5B]/],[/[\x5D-\uFFFF]/]],"fragment":true},{"name":"%string[2][2]","bnf":[[/\x22/],[/\x5C/],[/\x2F/],[/\x62/],[/\x66/],[/\x6E/],[/\x72/],[/\x74/],[/\x75/,"HEXDIG","HEXDIG","HEXDIG","HEXDIG"]],"fragment":true},{"name":"%string[2]","bnf":[["%string[2][1]"],[/\x5C/,"%string[2][2]"]],"fragment":true},{"name":"string","bnf":[["'\"'","%string[2]*","'\"'"]]},{"name":"HEXDIG","bnf":[[/[a-fA-F0-9]/]]}]
3
3
  },{}],2:[function(require,module,exports){
4
4
  const {Parser} = require('ebnf/dist/Parser.js'), {ParsingError} = require('ebnf'), RuleParseError = require('./errors/RuleParseError');
5
5
  let ParserRules = require('./RuleParser.production.ebnf.js');
@@ -28,6 +28,31 @@ const LogicalOperators = {
28
28
  '||': 'Or',
29
29
  'OR': 'Or'
30
30
  };
31
+ const ILReservedNames = new Set([
32
+ 'Value',
33
+ 'Array',
34
+ 'ArrayIn',
35
+ 'Between',
36
+ 'Not',
37
+ 'And',
38
+ 'Or',
39
+ 'Gt',
40
+ 'Lt',
41
+ 'Gte',
42
+ 'Lte',
43
+ 'Eq',
44
+ 'Neq',
45
+ 'MathAdd',
46
+ 'MathSub',
47
+ 'MathDiv',
48
+ 'MathMul',
49
+ 'MathMod',
50
+ 'Default',
51
+ 'TimePeriodConst',
52
+ 'TimePeriodConstAgo',
53
+ 'TimePeriodBetween',
54
+ 'TimePeriodBetweenAgo'
55
+ ]);
31
56
  const DOW_MAP = {
32
57
  'MON': 'MONDAY',
33
58
  'TUE': 'TUESDAY',
@@ -122,6 +147,9 @@ class RuleParser {
122
147
  }
123
148
  static _parseTimePeriod(tp) {
124
149
  switch (tp.type) {
150
+ case 'time_period_atom':
151
+ case 'time_period_ago_atom':
152
+ return RuleParser._parseTimePeriod(tp.children[0]);
125
153
  case 'time_period_const':
126
154
  if (tp.children && tp.children.length > 0 && tp.children[0].type === 'time_period_ago') {
127
155
  const timePeriodAgo = tp.children[0];
@@ -366,7 +394,7 @@ class RuleParser {
366
394
  switch (type) {
367
395
  case 'value_atom': {
368
396
  const atomChild = child.children[0];
369
- if (atomChild.type === 'time_period') {
397
+ if (atomChild.type === 'time_period' || atomChild.type === 'time_period_atom' || atomChild.type === 'time_period_ago_atom') {
370
398
  const tp = atomChild.children[0];
371
399
  return RuleParser._parseTimePeriod(tp);
372
400
  }
@@ -379,6 +407,9 @@ class RuleParser {
379
407
  const tp = child.children[0];
380
408
  return RuleParser._parseTimePeriod(tp);
381
409
  }
410
+ case 'time_period_atom':
411
+ case 'time_period_ago_atom':
412
+ return RuleParser._parseTimePeriod(child);
382
413
  default:
383
414
  return [
384
415
  'Value',
@@ -403,6 +434,8 @@ class RuleParser {
403
434
  switch (type) {
404
435
  case 'fcall':
405
436
  return RuleParser._parseFcall(child);
437
+ case 'parenthesis_expression':
438
+ return RuleParser._parseParenthesisExpression(child);
406
439
  case 'number_atom':
407
440
  case 'number_time_atom': {
408
441
  return [
@@ -686,6 +719,29 @@ class RuleParser {
686
719
  throw new Error(`unknown type of expression ${ eInner.type }`);
687
720
  }
688
721
  }
722
+ static _collectFunctions(il, names) {
723
+ if (!Array.isArray(il) || il.length === 0) {
724
+ return;
725
+ }
726
+ const [head, ...tail] = il;
727
+ if (typeof head === 'string') {
728
+ if (!ILReservedNames.has(head)) {
729
+ names.add(head);
730
+ }
731
+ for (const child of tail) {
732
+ RuleParser._collectFunctions(child, names);
733
+ }
734
+ return;
735
+ }
736
+ for (const child of il) {
737
+ RuleParser._collectFunctions(child, names);
738
+ }
739
+ }
740
+ static getFunctions(il) {
741
+ const names = new Set();
742
+ RuleParser._collectFunctions(il, names);
743
+ return [...names];
744
+ }
689
745
  static toIL(txt) {
690
746
  try {
691
747
  const ast = RuleParser.toAst(txt);
@@ -781,10 +837,14 @@ class ErrorAnalyzer {
781
837
 
782
838
  // Get snippet (last 50 chars or the whole input if shorter)
783
839
  const snippetStart = Math.max(0, trimmedInput.length - 50);
784
- const snippet = (snippetStart > 0 ? '...' : '') + trimmedInput.substring(snippetStart);
840
+ const snippetEnd = trimmedInput.length;
841
+ let snippet = this._buildSnippet(trimmedInput, snippetStart, snippetEnd);
785
842
 
786
843
  // Analyze the error pattern
787
844
  const errorInfo = this._detectErrorPattern(trimmedInput, position, snippet);
845
+ this._enrichBadFunctionCallError(trimmedInput, position, errorInfo, (value) => {
846
+ snippet = value;
847
+ }, snippetStart, snippetEnd);
788
848
 
789
849
  return new RuleParseError(
790
850
  errorInfo.code,
@@ -810,12 +870,13 @@ class ErrorAnalyzer {
810
870
  // Get snippet around error position
811
871
  const snippetStart = Math.max(0, position.offset - 20);
812
872
  const snippetEnd = Math.min(input.length, position.offset + 30);
813
- const snippet = (snippetStart > 0 ? '...' : '') +
814
- input.substring(snippetStart, snippetEnd) +
815
- (snippetEnd < input.length ? '...' : '');
873
+ let snippet = this._buildSnippet(input, snippetStart, snippetEnd);
816
874
 
817
875
  // Analyze what was expected to determine error type using failureTree
818
876
  const errorInfo = this._detectErrorFromFailureTree(input, position, expected, found, failureTree);
877
+ this._enrichBadFunctionCallError(input, position, errorInfo, (value) => {
878
+ snippet = value;
879
+ }, snippetStart, snippetEnd);
819
880
 
820
881
  return new RuleParseError(
821
882
  errorInfo.code,
@@ -1329,6 +1390,109 @@ class ErrorAnalyzer {
1329
1390
  };
1330
1391
  }
1331
1392
 
1393
+ static _enrichBadFunctionCallError(input, position, errorInfo, setSnippet, snippetStart, snippetEnd) {
1394
+ if (!errorInfo || errorInfo.code !== "BAD_FUNCTION_CALL") {
1395
+ return;
1396
+ }
1397
+
1398
+ const functionContext = this._findFunctionContext(input, position.offset);
1399
+ errorInfo.hint = this._getBadFunctionCallHint(input, position, functionContext);
1400
+
1401
+ if (!functionContext) {
1402
+ return;
1403
+ }
1404
+
1405
+ errorInfo.message = `Invalid function call syntax for ${functionContext.name}.`;
1406
+ setSnippet(this._buildBadFunctionCallSnippet(input, functionContext, snippetStart, snippetEnd));
1407
+ }
1408
+
1409
+ static _buildSnippet(input, start, end) {
1410
+ return (start > 0 ? '...' : '') +
1411
+ input.substring(start, end) +
1412
+ (end < input.length ? '...' : '');
1413
+ }
1414
+
1415
+ static _getBadFunctionCallHint(input, position, functionContext) {
1416
+ const genericHint = "Function calls must have matching parentheses, e.g. func() or func(arg1, arg2).";
1417
+
1418
+ if (!functionContext || !this._isArgumentRelatedFunctionCallError(input, position, functionContext)) {
1419
+ return genericHint;
1420
+ }
1421
+
1422
+ return "Function calls must have matching parentheses, e.g. func() or func(arg1, arg2). Please check function arguments for invalid syntax.";
1423
+ }
1424
+
1425
+ static _isArgumentRelatedFunctionCallError(input, position, functionContext) {
1426
+ const endOffset = Math.max(functionContext.openParenIndex + 1, Math.min(position.offset, input.length));
1427
+ const argumentText = input.substring(functionContext.openParenIndex + 1, endOffset).trim();
1428
+ return argumentText.length > 0;
1429
+ }
1430
+
1431
+ static _buildBadFunctionCallSnippet(input, functionContext, snippetStart, snippetEnd) {
1432
+ if (snippetStart <= functionContext.start) {
1433
+ return this._buildSnippet(input, snippetStart, snippetEnd);
1434
+ }
1435
+
1436
+ const functionPrefix = input.substring(functionContext.start, functionContext.openParenIndex + 1);
1437
+ const suffix = input.substring(snippetStart, snippetEnd);
1438
+ return functionPrefix + '...' + suffix + (snippetEnd < input.length ? '...' : '');
1439
+ }
1440
+
1441
+ static _findFunctionContext(input, offset) {
1442
+ const scanLimit = Math.max(0, Math.min(typeof offset === 'number' ? offset : input.length, input.length));
1443
+ const stack = [];
1444
+ let inString = false;
1445
+
1446
+ for (let i = 0; i < scanLimit; i++) {
1447
+ const char = input[i];
1448
+
1449
+ if (char === '"') {
1450
+ if (!inString) {
1451
+ inString = true;
1452
+ } else {
1453
+ let backslashCount = 0;
1454
+ let j = i - 1;
1455
+ while (j >= 0 && input[j] === '\\') {
1456
+ backslashCount++;
1457
+ j--;
1458
+ }
1459
+ if (backslashCount % 2 === 0) {
1460
+ inString = false;
1461
+ }
1462
+ }
1463
+ continue;
1464
+ }
1465
+
1466
+ if (inString) {
1467
+ continue;
1468
+ }
1469
+
1470
+ if (char === '(') {
1471
+ const prefix = input.substring(0, i);
1472
+ const match = /([a-zA-Z_][a-zA-Z0-9_]*)\s*$/.exec(prefix);
1473
+ if (match) {
1474
+ stack.push({
1475
+ name: match[1],
1476
+ start: i - match[1].length,
1477
+ openParenIndex: i
1478
+ });
1479
+ } else {
1480
+ stack.push(null);
1481
+ }
1482
+ } else if (char === ')' && stack.length > 0) {
1483
+ stack.pop();
1484
+ }
1485
+ }
1486
+
1487
+ for (let i = stack.length - 1; i >= 0; i--) {
1488
+ if (stack[i]) {
1489
+ return stack[i];
1490
+ }
1491
+ }
1492
+
1493
+ return null;
1494
+ }
1495
+
1332
1496
  /**
1333
1497
  * Check if string is properly terminated
1334
1498
  * @private
@@ -1700,12 +1864,6 @@ class RuleParseError extends Error {
1700
1864
  if (this.hint) {
1701
1865
  msg += ` Hint: ${this.hint}\n`;
1702
1866
  }
1703
- if (this.found) {
1704
- msg += ` Found: ${this.found}\n`;
1705
- }
1706
- if (this.expected && this.expected.length) {
1707
- msg += ` Expected: ${this.expected.join(', ')}`;
1708
- }
1709
1867
  return msg;
1710
1868
  }
1711
1869
 
@@ -3671,18 +3829,9 @@ const grammar = `
3671
3829
 
3672
3830
  template_filter_arg ::= value | template_value
3673
3831
 
3674
- number_atom ::= number | template_value
3675
- number_time_atom ::= number_time | template_value WS+ unit | template_value
3676
- tod_atom ::= number_tod | template_value
3677
- dow_atom ::= dow | template_value
3678
- between_time_only_atom ::= between_time_only | template_value
3679
- between_tod_only_atom ::= between_tod_only | template_value
3680
-
3681
3832
  string_atom ::= string
3682
3833
  boolean_atom ::= false | true
3683
3834
  time_value_atom ::= number_tod
3684
- time_period_atom ::= time_value_atom WS* "TO" WS* time_value_atom
3685
- time_period_ago_atom ::= time_value_atom WS* "TO" WS* time_value_atom WS+ AGO WS+ number WS+ unit
3686
3835
 
3687
3836
  object_atom ::= json_object
3688
3837
  json_value ::= string | number | false | true | null | json_array | json_object
@@ -3699,7 +3848,7 @@ const grammar = `
3699
3848
  module.exports = Grammars.W3C.getRules(grammar);
3700
3849
 
3701
3850
  },{"ebnf":13}],16:[function(require,module,exports){
3702
- module.exports=[{"name":"TEMPLATE_BEGIN","bnf":[["\"${\""]]},{"name":"TEMPLATE_END","bnf":[["\"}\""]]},{"name":"PIPE","bnf":[["\"|\""]]},{"name":"%IDENT[2]","bnf":[[/[A-Za-z0-9_]/]]},{"name":"IDENT","bnf":[[/[A-Za-z_]/,"%IDENT[2]*"]]},{"name":"DOT","bnf":[["\".\""]]},{"name":"template_value","bnf":[["TEMPLATE_BEGIN","WS*","template_expr","WS*","TEMPLATE_END"]]},{"name":"%template_expr[2]","bnf":[["WS*","template_pipe","WS*","template_filter_call"]],"fragment":true},{"name":"template_expr","bnf":[["template_path","%template_expr[2]*"]]},{"name":"template_pipe","bnf":[["PIPE"]]},{"name":"%template_path[2]","bnf":[["WS*","DOT","WS*","IDENT"]],"fragment":true},{"name":"template_path","bnf":[["IDENT","%template_path[2]*"]]},{"name":"%template_filter_call[2]","bnf":[["WS*","BEGIN_ARGUMENT","WS*","template_filter_args?","WS*","END_ARGUMENT"]],"fragment":true},{"name":"template_filter_call","bnf":[["template_filter_name","%template_filter_call[2]?"]]},{"name":"template_filter_name","bnf":[["IDENT"]]},{"name":"%template_filter_args[2]","bnf":[["WS*","\",\"","WS*","template_filter_arg"]],"fragment":true},{"name":"template_filter_args","bnf":[["template_filter_arg","%template_filter_args[2]*"]]},{"name":"template_filter_arg","bnf":[["value"],["template_value"]]},{"name":"number_atom","bnf":[["number"],["template_value"]]},{"name":"number_time_atom","bnf":[["number_time"],["template_value","WS+","unit"],["template_value"]]},{"name":"tod_atom","bnf":[["number_tod"],["template_value"]]},{"name":"dow_atom","bnf":[["dow"],["template_value"]]},{"name":"between_time_only_atom","bnf":[["between_time_only"],["template_value"]]},{"name":"between_tod_only_atom","bnf":[["between_tod_only"],["template_value"]]},{"name":"string_atom","bnf":[["string"]]},{"name":"boolean_atom","bnf":[["false"],["true"]]},{"name":"time_value_atom","bnf":[["number_tod"]]},{"name":"time_period_atom","bnf":[["time_value_atom","WS*","\"TO\"","WS*","time_value_atom"]]},{"name":"time_period_ago_atom","bnf":[["time_value_atom","WS*","\"TO\"","WS*","time_value_atom","WS+","AGO","WS+","number","WS+","unit"]]},{"name":"object_atom","bnf":[["json_object"]]},{"name":"json_value","bnf":[["string"],["number"],["false"],["true"],["null"],["json_array"],["json_object"]]},{"name":"json_member","bnf":[["string","NAME_SEPARATOR","json_value"]]},{"name":"%json_object[2][2]","bnf":[["VALUE_SEPARATOR","json_member"]],"fragment":true},{"name":"%json_object[2]","bnf":[["json_member","%json_object[2][2]*"]],"fragment":true},{"name":"json_object","bnf":[["BEGIN_OBJECT","%json_object[2]?","END_OBJECT"]]},{"name":"%json_array[2][2]","bnf":[["VALUE_SEPARATOR","json_value"]],"fragment":true},{"name":"%json_array[2]","bnf":[["json_value","%json_array[2][2]*"]],"fragment":true},{"name":"json_array","bnf":[["BEGIN_ARRAY","%json_array[2]?","END_ARRAY"]]},{"name":"%string_array[2][2]","bnf":[["VALUE_SEPARATOR","string"]],"fragment":true},{"name":"%string_array[2]","bnf":[["string","%string_array[2][2]*"]],"fragment":true},{"name":"string_array","bnf":[["BEGIN_ARRAY","%string_array[2]?","END_ARRAY"]]},{"name":"%number_array[2][2]","bnf":[["VALUE_SEPARATOR","number"]],"fragment":true},{"name":"%number_array[2]","bnf":[["number","%number_array[2][2]*"]],"fragment":true},{"name":"number_array","bnf":[["BEGIN_ARRAY","%number_array[2]?","END_ARRAY"]]},{"name":"%boolean_array[2][2]","bnf":[["VALUE_SEPARATOR","boolean_atom"]],"fragment":true},{"name":"%boolean_array[2]","bnf":[["boolean_atom","%boolean_array[2][2]*"]],"fragment":true},{"name":"boolean_array","bnf":[["BEGIN_ARRAY","%boolean_array[2]?","END_ARRAY"]]},{"name":"%object_array[2][2]","bnf":[["VALUE_SEPARATOR","json_object"]],"fragment":true},{"name":"%object_array[2]","bnf":[["json_object","%object_array[2][2]*"]],"fragment":true},{"name":"object_array","bnf":[["BEGIN_ARRAY","%object_array[2]?","END_ARRAY"]]}]
3851
+ module.exports=[{"name":"TEMPLATE_BEGIN","bnf":[["\"${\""]]},{"name":"TEMPLATE_END","bnf":[["\"}\""]]},{"name":"PIPE","bnf":[["\"|\""]]},{"name":"%IDENT[2]","bnf":[[/[A-Za-z0-9_]/]]},{"name":"IDENT","bnf":[[/[A-Za-z_]/,"%IDENT[2]*"]]},{"name":"DOT","bnf":[["\".\""]]},{"name":"template_value","bnf":[["TEMPLATE_BEGIN","WS*","template_expr","WS*","TEMPLATE_END"]]},{"name":"%template_expr[2]","bnf":[["WS*","template_pipe","WS*","template_filter_call"]],"fragment":true},{"name":"template_expr","bnf":[["template_path","%template_expr[2]*"]]},{"name":"template_pipe","bnf":[["PIPE"]]},{"name":"%template_path[2]","bnf":[["WS*","DOT","WS*","IDENT"]],"fragment":true},{"name":"template_path","bnf":[["IDENT","%template_path[2]*"]]},{"name":"%template_filter_call[2]","bnf":[["WS*","BEGIN_ARGUMENT","WS*","template_filter_args?","WS*","END_ARGUMENT"]],"fragment":true},{"name":"template_filter_call","bnf":[["template_filter_name","%template_filter_call[2]?"]]},{"name":"template_filter_name","bnf":[["IDENT"]]},{"name":"%template_filter_args[2]","bnf":[["WS*","\",\"","WS*","template_filter_arg"]],"fragment":true},{"name":"template_filter_args","bnf":[["template_filter_arg","%template_filter_args[2]*"]]},{"name":"template_filter_arg","bnf":[["value"],["template_value"]]},{"name":"string_atom","bnf":[["string"]]},{"name":"boolean_atom","bnf":[["false"],["true"]]},{"name":"time_value_atom","bnf":[["number_tod"]]},{"name":"object_atom","bnf":[["json_object"]]},{"name":"json_value","bnf":[["string"],["number"],["false"],["true"],["null"],["json_array"],["json_object"]]},{"name":"json_member","bnf":[["string","NAME_SEPARATOR","json_value"]]},{"name":"%json_object[2][2]","bnf":[["VALUE_SEPARATOR","json_member"]],"fragment":true},{"name":"%json_object[2]","bnf":[["json_member","%json_object[2][2]*"]],"fragment":true},{"name":"json_object","bnf":[["BEGIN_OBJECT","%json_object[2]?","END_OBJECT"]]},{"name":"%json_array[2][2]","bnf":[["VALUE_SEPARATOR","json_value"]],"fragment":true},{"name":"%json_array[2]","bnf":[["json_value","%json_array[2][2]*"]],"fragment":true},{"name":"json_array","bnf":[["BEGIN_ARRAY","%json_array[2]?","END_ARRAY"]]},{"name":"%string_array[2][2]","bnf":[["VALUE_SEPARATOR","string"]],"fragment":true},{"name":"%string_array[2]","bnf":[["string","%string_array[2][2]*"]],"fragment":true},{"name":"string_array","bnf":[["BEGIN_ARRAY","%string_array[2]?","END_ARRAY"]]},{"name":"%number_array[2][2]","bnf":[["VALUE_SEPARATOR","number"]],"fragment":true},{"name":"%number_array[2]","bnf":[["number","%number_array[2][2]*"]],"fragment":true},{"name":"number_array","bnf":[["BEGIN_ARRAY","%number_array[2]?","END_ARRAY"]]},{"name":"%boolean_array[2][2]","bnf":[["VALUE_SEPARATOR","boolean_atom"]],"fragment":true},{"name":"%boolean_array[2]","bnf":[["boolean_atom","%boolean_array[2][2]*"]],"fragment":true},{"name":"boolean_array","bnf":[["BEGIN_ARRAY","%boolean_array[2]?","END_ARRAY"]]},{"name":"%object_array[2][2]","bnf":[["VALUE_SEPARATOR","json_object"]],"fragment":true},{"name":"%object_array[2]","bnf":[["json_object","%object_array[2][2]*"]],"fragment":true},{"name":"object_array","bnf":[["BEGIN_ARRAY","%object_array[2]?","END_ARRAY"]]}]
3703
3852
  },{}],17:[function(require,module,exports){
3704
3853
  // Note: We are coupled closely with the ebnf grammar structure of rule-parser
3705
3854
  const TemplateGrammar = require('./RuleTemplate.production.ebnf.js'),
@@ -3731,7 +3880,7 @@ const AllowedTypeMapping = {
3731
3880
  'number': ['number_atom', 'math_expr'],
3732
3881
  'boolean': ['boolean_atom', 'boolean_expr'],
3733
3882
  'time period': ['time_period_atom'],
3734
- 'time period ago': ['time_period_atom'],
3883
+ 'time period ago': ['time_period_ago_atom'],
3735
3884
  'time value': ['time_value_atom', 'tod_atom'],
3736
3885
  'number time': ['number_atom'],
3737
3886
  'string array': ['string_array'],
@@ -3752,12 +3901,71 @@ for(const rule of TemplateGrammar){
3752
3901
  }
3753
3902
  }
3754
3903
 
3755
- // Add template_value as an alternative to value_atom so templates can be parsed
3756
- const valueAtomIdx = extendedGrammar.findIndex(r => r.name === 'value_atom');
3757
- if (valueAtomIdx !== -1) {
3758
- extendedGrammar[valueAtomIdx] = Object.assign({}, extendedGrammar[valueAtomIdx]);
3759
- extendedGrammar[valueAtomIdx].bnf = extendedGrammar[valueAtomIdx].bnf.concat([['template_value']]);
3760
- }
3904
+ const cloneRule = (ruleName) => {
3905
+ const idx = extendedGrammar.findIndex(rule => rule.name === ruleName);
3906
+ if (idx === -1) {
3907
+ return null;
3908
+ }
3909
+
3910
+ extendedGrammar[idx] = Object.assign({}, extendedGrammar[idx], {
3911
+ bnf: extendedGrammar[idx].bnf.map(alt => Array.isArray(alt) ? alt.slice() : alt)
3912
+ });
3913
+
3914
+ return extendedGrammar[idx];
3915
+ };
3916
+
3917
+ const appendAlternative = (ruleName, alternative) => {
3918
+ const rule = cloneRule(ruleName);
3919
+ if (!rule) {
3920
+ return;
3921
+ }
3922
+
3923
+ const exists = rule.bnf.some(existing => JSON.stringify(existing) === JSON.stringify(alternative));
3924
+ if (!exists) {
3925
+ rule.bnf.push(alternative);
3926
+ }
3927
+ };
3928
+
3929
+ const replaceRule = (ruleName, bnf) => {
3930
+ const idx = extendedGrammar.findIndex(rule => rule.name === ruleName);
3931
+ if (idx === -1) {
3932
+ extendedGrammar.push({name: ruleName, bnf});
3933
+ return;
3934
+ }
3935
+
3936
+ extendedGrammar[idx] = Object.assign({}, extendedGrammar[idx], {
3937
+ bnf: bnf.map(alt => alt.slice())
3938
+ });
3939
+ };
3940
+
3941
+ appendAlternative('number_atom', ['template_value']);
3942
+ appendAlternative('number_time_atom', ['template_value', 'WS+', 'unit']);
3943
+ appendAlternative('number_time_atom', ['template_value']);
3944
+ appendAlternative('tod_atom', ['template_value']);
3945
+ appendAlternative('dow_atom', ['template_value']);
3946
+ appendAlternative('between_time_only_atom', ['template_value']);
3947
+ appendAlternative('between_tod_only_atom', ['template_value']);
3948
+ appendAlternative('string_atom', ['template_value']);
3949
+ appendAlternative('boolean_atom', ['template_value']);
3950
+ appendAlternative('time_value_atom', ['template_value']);
3951
+ appendAlternative('time_period_atom', ['template_value']);
3952
+ appendAlternative('time_period_ago_atom', ['template_value']);
3953
+ appendAlternative('object_atom', ['template_value']);
3954
+ appendAlternative('string_array', ['template_value']);
3955
+ appendAlternative('number_array', ['template_value']);
3956
+ appendAlternative('boolean_array', ['template_value']);
3957
+ appendAlternative('object_array', ['template_value']);
3958
+
3959
+ replaceRule('argument', [
3960
+ ['number_time_atom', 'WS*'],
3961
+ ['statement', 'WS*']
3962
+ ]);
3963
+
3964
+ replaceRule('simple_result', [
3965
+ ['fcall'],
3966
+ ['number_time_atom'],
3967
+ ['value']
3968
+ ]);
3761
3969
 
3762
3970
  // Export the parser rules for potential external use
3763
3971
  const ParserRules = extendedGrammar;
@@ -3888,11 +4096,13 @@ class RuleTemplate {
3888
4096
 
3889
4097
  // Extract filters
3890
4098
  const filters = [];
4099
+ const filterCalls = [];
3891
4100
  for (const child of templateExpr.children || []) {
3892
4101
  if (child.type === 'template_filter_call') {
3893
- const filterName = this._extractFilterName(child);
3894
- if (filterName) {
3895
- filters.push(filterName);
4102
+ const filterCall = this._extractFilterCall(child);
4103
+ if (filterCall) {
4104
+ filters.push(filterCall.name);
4105
+ filterCalls.push(filterCall);
3896
4106
  }
3897
4107
  }
3898
4108
  }
@@ -3901,18 +4111,84 @@ class RuleTemplate {
3901
4111
  const start = node.start;
3902
4112
  const end = node.end;
3903
4113
 
3904
- return { name, filters, start, end };
4114
+ return { name, filters, filterCalls, start, end };
3905
4115
  }
3906
4116
 
3907
4117
  /**
3908
- * Extract filter name from template_filter_call node
4118
+ * Extract filter call from template_filter_call node
3909
4119
  * @private
3910
4120
  */
3911
- _extractFilterName(node) {
4121
+ _extractFilterCall(node) {
3912
4122
  const filterNameNode = node.children?.find(c => c.type === 'template_filter_name');
3913
4123
  if (!filterNameNode || !filterNameNode.text) return null;
3914
-
3915
- return filterNameNode.text.trim();
4124
+
4125
+ const argsNode = node.children?.find(c => c.type === 'template_filter_args');
4126
+
4127
+ return {
4128
+ name: filterNameNode.text.trim(),
4129
+ args: this._extractFilterArgs(argsNode)
4130
+ };
4131
+ }
4132
+
4133
+ _extractFilterArgs(node) {
4134
+ if (!node || !Array.isArray(node.children)) {
4135
+ return [];
4136
+ }
4137
+
4138
+ return node.children
4139
+ .filter(child => child.type === 'template_filter_arg')
4140
+ .map(child => this._extractFilterArgValue(child));
4141
+ }
4142
+
4143
+ _extractFilterArgValue(node) {
4144
+ if (!node || !Array.isArray(node.children) || node.children.length === 0) {
4145
+ return this._normalizeFilterArgText(node?.text?.trim() || '');
4146
+ }
4147
+
4148
+ const child = node.children[0];
4149
+ if (!child) {
4150
+ return this._normalizeFilterArgText(node.text?.trim() || '');
4151
+ }
4152
+
4153
+ if (child.type === 'value' && Array.isArray(child.children) && child.children.length > 0) {
4154
+ return this._extractFilterArgValue(child);
4155
+ }
4156
+
4157
+ if (child.type === 'string') {
4158
+ try {
4159
+ return JSON.parse(child.text);
4160
+ } catch (error) {
4161
+ return this._normalizeFilterArgText(child.text);
4162
+ }
4163
+ }
4164
+
4165
+ if (child.type === 'number') {
4166
+ return Number(child.text);
4167
+ }
4168
+
4169
+ if (child.type === 'true') {
4170
+ return true;
4171
+ }
4172
+
4173
+ if (child.type === 'false') {
4174
+ return false;
4175
+ }
4176
+
4177
+ if (child.type === 'null') {
4178
+ return null;
4179
+ }
4180
+
4181
+ return this._normalizeFilterArgText(child.text?.trim() || node.text?.trim() || '');
4182
+ }
4183
+
4184
+ _normalizeFilterArgText(text) {
4185
+ const normalizedText = String(text).trim();
4186
+
4187
+ if ((normalizedText.startsWith('"') && normalizedText.endsWith('"')) || (normalizedText.startsWith("'") && normalizedText.endsWith("'"))) {
4188
+ return normalizedText.slice(1, -1);
4189
+ }
4190
+
4191
+ return normalizedText;
3916
4192
  }
3917
4193
 
3918
4194
  /**
@@ -3932,10 +4208,31 @@ class RuleTemplate {
3932
4208
 
3933
4209
  const errors = [];
3934
4210
  const warnings = [];
3935
- const extractedVars = this.extractVariables();
4211
+ const extractedVars = this._extractTemplateVariables();
4212
+ const seenVariables = new Set();
4213
+ const seenFilterErrors = new Set();
3936
4214
 
3937
4215
  for (const varInfo of extractedVars) {
3938
4216
  const varName = varInfo.name;
4217
+
4218
+ for (const filter of (varInfo.filterCalls || varInfo.filters || [])) {
4219
+ const filterName = typeof filter === 'string' ? filter : filter?.name;
4220
+ if (filterName && TemplateFilters[filterName]) {
4221
+ continue;
4222
+ }
4223
+
4224
+ const errorMessage = `Unknown filter '${filterName || filter}' for variable '${varName}'`;
4225
+ if (!seenFilterErrors.has(errorMessage)) {
4226
+ errors.push(errorMessage);
4227
+ seenFilterErrors.add(errorMessage);
4228
+ }
4229
+ }
4230
+
4231
+ if (seenVariables.has(varName)) {
4232
+ continue;
4233
+ }
4234
+
4235
+ seenVariables.add(varName);
3939
4236
 
3940
4237
  // Check if variable is provided
3941
4238
  if (!variables.hasOwnProperty(varName)) {
@@ -3965,6 +4262,23 @@ class RuleTemplate {
3965
4262
  }
3966
4263
  }
3967
4264
 
4265
+ const canValidatePreparedRule = errors.length === 0
4266
+ && Array.from(seenVariables).every(varName => {
4267
+ const varData = variables[varName];
4268
+ return varData
4269
+ && typeof varData === 'object'
4270
+ && Object.prototype.hasOwnProperty.call(varData, 'type')
4271
+ && Object.prototype.hasOwnProperty.call(varData, 'value');
4272
+ });
4273
+
4274
+ if (canValidatePreparedRule) {
4275
+ try {
4276
+ RuleParser.toAst(this.prepare(variables));
4277
+ } catch (error) {
4278
+ errors.push(`Prepared rule is invalid: ${error.message}`);
4279
+ }
4280
+ }
4281
+
3968
4282
  if (functionBlob && typeof functionBlob.validate === 'function') {
3969
4283
  for (const functionCall of this._extractFunctionCalls()) {
3970
4284
  warnings.push(...functionBlob.validate(functionCall.name, functionCall.arguments));
@@ -4008,6 +4322,30 @@ class RuleTemplate {
4008
4322
  return functionCalls;
4009
4323
  }
4010
4324
 
4325
+ _extractTemplateVariables() {
4326
+ const variables = [];
4327
+
4328
+ const traverse = (node) => {
4329
+ if (!node) return;
4330
+
4331
+ if (node.type === 'template_value') {
4332
+ const variableInfo = this._extractVariableFromNode(node);
4333
+ if (variableInfo) {
4334
+ variables.push(variableInfo);
4335
+ }
4336
+ }
4337
+
4338
+ if (node.children) {
4339
+ for (const child of node.children) {
4340
+ traverse(child);
4341
+ }
4342
+ }
4343
+ };
4344
+
4345
+ traverse(this.ast);
4346
+ return variables;
4347
+ }
4348
+
4011
4349
  /**
4012
4350
  * Prepare the template by replacing variables with their values
4013
4351
  * Rebuilds from AST by iterating through children
@@ -4110,12 +4448,15 @@ class RuleTemplate {
4110
4448
 
4111
4449
  // Apply filters if present
4112
4450
  if (templateInfo.filters && templateInfo.filters.length > 0) {
4113
- for (const filterName of templateInfo.filters) {
4114
- if (!TemplateFilters[filterName]) {
4115
- throw new Error(`Unknown filter '${filterName}'`);
4451
+ for (const filter of (templateInfo.filterCalls || templateInfo.filters)) {
4452
+ const filterName = typeof filter === 'string' ? filter : filter?.name;
4453
+ const filterArgs = typeof filter === 'string' ? [] : (Array.isArray(filter?.args) ? filter.args : []);
4454
+
4455
+ if (!filterName || !TemplateFilters[filterName]) {
4456
+ throw new Error(`Unknown filter '${filterName || filter}'`);
4116
4457
  }
4117
-
4118
- TemplateFilters[filterName](varData);
4458
+
4459
+ TemplateFilters[filterName](varData, ...filterArgs);
4119
4460
  }
4120
4461
  }
4121
4462
 
@@ -4146,12 +4487,12 @@ class RuleTemplate {
4146
4487
  return value ? 'true' : 'false';
4147
4488
  }
4148
4489
 
4149
- if (type === 'time period' || type === 'time period ago') {
4150
- let ret = `${value.from} TO ${value.to}`;
4151
- if(value.ago) {
4152
- ret += ` AGO ${value.ago[0]} ${value.ago[1]}`;
4153
- }
4154
- return ret;
4490
+ if (type === 'time period') {
4491
+ return `BETWEEN ${value.from} AND ${value.to}`;
4492
+ }
4493
+
4494
+ if (type === 'time period ago') {
4495
+ return `${value.ago[0]} ${value.ago[1]} AGO BETWEEN ${value.from} AND ${value.to}`;
4155
4496
  }
4156
4497
 
4157
4498
  if (type === 'object' || type === 'string array' || type === 'number array' || type === 'boolean array' || type === 'object array') {
@@ -4193,6 +4534,31 @@ module.exports = RuleTemplate;
4193
4534
  Template filters are functions that transform variable values.
4194
4535
  They are applied in the template syntax as ${variable|filter} or ${variable|filter1|filter2}
4195
4536
  */
4537
+ const HUMANISE_TIME_UNITS = [
4538
+ { name: 'year', seconds: 31536000, aliases: ['year', 'years', 'yr', 'yrs', 'y'] },
4539
+ { name: 'month', seconds: 2592000, aliases: ['month', 'months', 'mo', 'mos'] },
4540
+ { name: 'week', seconds: 604800, aliases: ['week', 'weeks', 'wk', 'wks', 'w'] },
4541
+ { name: 'day', seconds: 86400, aliases: ['day', 'days', 'd'] },
4542
+ { name: 'hour', seconds: 3600, aliases: ['hour', 'hours', 'hr', 'hrs', 'h'] },
4543
+ { name: 'minute', seconds: 60, aliases: ['minute', 'minutes', 'min', 'mins'] },
4544
+ { name: 'second', seconds: 1, aliases: ['second', 'seconds', 'sec', 'secs', 's'] }
4545
+ ];
4546
+
4547
+ const getHumaniseTimeUnit = minUnit => {
4548
+ if (minUnit === null || minUnit === undefined || minUnit === '') {
4549
+ return null;
4550
+ }
4551
+
4552
+ const normalizedMinUnit = String(minUnit).trim().toLowerCase();
4553
+ const unit = HUMANISE_TIME_UNITS.find(candidate => candidate.aliases.includes(normalizedMinUnit));
4554
+
4555
+ if (!unit) {
4556
+ throw new Error(`Unknown humanise_time min_unit \"${minUnit}\"`);
4557
+ }
4558
+
4559
+ return unit;
4560
+ };
4561
+
4196
4562
  const TemplateFilters = {
4197
4563
  // Convert value to JSON string representation
4198
4564
  string: varData => {
@@ -4316,6 +4682,69 @@ const TemplateFilters = {
4316
4682
 
4317
4683
  },
4318
4684
 
4685
+ humanise_list: (varData, joiner = 'and') => {
4686
+ if (typeof varData.value === 'string') {
4687
+ varData.type = 'string';
4688
+ return;
4689
+ }
4690
+
4691
+ if (!Array.isArray(varData.value)) {
4692
+ varData.value = String(varData.value);
4693
+ varData.type = 'string';
4694
+ return;
4695
+ }
4696
+
4697
+ const items = varData.value.map(item => String(item));
4698
+
4699
+ if (items.length === 0) {
4700
+ varData.value = '';
4701
+ } else if (items.length === 1) {
4702
+ [varData.value] = items;
4703
+ } else if (items.length === 2) {
4704
+ varData.value = `${items[0]} ${joiner} ${items[1]}`;
4705
+ } else {
4706
+ varData.value = `${items.slice(0, -1).join(', ')} ${joiner} ${items[items.length - 1]}`;
4707
+ }
4708
+
4709
+ varData.type = 'string';
4710
+
4711
+ },
4712
+
4713
+ humanise_time: (varData, minUnit = null) => {
4714
+ const rawSeconds = Number(varData.value);
4715
+
4716
+ if (isNaN(rawSeconds)) {
4717
+ throw new Error(`Value "${varData.value}" cannot be converted to seconds`);
4718
+ }
4719
+
4720
+ const isNegative = rawSeconds < 0;
4721
+ const absoluteSeconds = Math.abs(rawSeconds);
4722
+ const minimumUnit = getHumaniseTimeUnit(minUnit);
4723
+ const minimumUnitIndex = minimumUnit
4724
+ ? HUMANISE_TIME_UNITS.findIndex(unit => unit.name === minimumUnit.name)
4725
+ : HUMANISE_TIME_UNITS.length - 1;
4726
+ const candidateUnits = HUMANISE_TIME_UNITS.slice(0, minimumUnitIndex + 1);
4727
+ let selectedUnit = candidateUnits.find(unit => absoluteSeconds % unit.seconds === 0);
4728
+ let quantity;
4729
+
4730
+ if (selectedUnit) {
4731
+ quantity = absoluteSeconds / selectedUnit.seconds;
4732
+ } else if (minimumUnit) {
4733
+ selectedUnit = minimumUnit;
4734
+ quantity = Math.floor(absoluteSeconds / selectedUnit.seconds);
4735
+ } else {
4736
+ selectedUnit = HUMANISE_TIME_UNITS[HUMANISE_TIME_UNITS.length - 1];
4737
+ quantity = absoluteSeconds;
4738
+ }
4739
+
4740
+ const signedQuantity = isNegative ? -quantity : quantity;
4741
+ const label = Math.abs(signedQuantity) === 1 ? selectedUnit.name : `${selectedUnit.name}s`;
4742
+
4743
+ varData.value = `${signedQuantity} ${label}`;
4744
+ varData.type = 'string';
4745
+
4746
+ },
4747
+
4319
4748
  // Extract start time from time period/time period ago as time value
4320
4749
  time_start: varData => {
4321
4750
  if (varData.type === 'time period' || varData.type === 'time period ago') {
@@ -4490,12 +4919,15 @@ class VariableValidate {
4490
4919
  throw new Error('Variable data filters must be an array');
4491
4920
  }
4492
4921
 
4493
- for (const filterName of normalizedVarData.filters) {
4494
- if (!TemplateFilters[filterName]) {
4495
- throw new Error(`Unknown filter '${filterName}'`);
4922
+ for (const filter of normalizedVarData.filters) {
4923
+ const filterName = typeof filter === 'string' ? filter : filter?.name;
4924
+ const filterArgs = typeof filter === 'string' ? [] : (Array.isArray(filter?.args) ? filter.args : []);
4925
+
4926
+ if (!filterName || !TemplateFilters[filterName]) {
4927
+ throw new Error(`Unknown filter '${filterName || filter}'`);
4496
4928
  }
4497
4929
 
4498
- TemplateFilters[filterName](normalizedVarData);
4930
+ TemplateFilters[filterName](normalizedVarData, ...filterArgs);
4499
4931
  }
4500
4932
 
4501
4933
  return normalizedVarData;
@@ -4555,7 +4987,7 @@ class VariableValidate {
4555
4987
  return null;
4556
4988
  }
4557
4989
 
4558
- return `${value.from.trim()} TO ${value.to.trim()}`;
4990
+ return `BETWEEN ${value.from.trim()} AND ${value.to.trim()}`;
4559
4991
  }
4560
4992
 
4561
4993
  static _serializeTimePeriodAgo(value) {
@@ -4572,7 +5004,7 @@ class VariableValidate {
4572
5004
  return null;
4573
5005
  }
4574
5006
 
4575
- return `${value.from.trim()} TO ${value.to.trim()} AGO ${amount} ${unit.trim()}`;
5007
+ return `${amount} ${unit.trim()} AGO BETWEEN ${value.from.trim()} AND ${value.to.trim()}`;
4576
5008
  }
4577
5009
 
4578
5010
  static _serializeNumberTime(value) {
@@ -4689,7 +5121,7 @@ VariableValidate.validators = Object.freeze({
4689
5121
  'time period': (value) => VariableValidate._validateWithRule(value, 'time_period_atom', {
4690
5122
  normalize: VariableValidate._serializeTimePeriod,
4691
5123
  emptyMessage: 'Time period variables must be objects with string from/to properties',
4692
- parseMessage: 'Time period variables must serialize to FROM TO TO syntax',
5124
+ parseMessage: 'Time period variables must serialize to BETWEEN FROM AND TO syntax',
4693
5125
  semanticCheck: (rawValue) => {
4694
5126
  const fromError = VariableValidate._validateTimeOfDay(rawValue?.from);
4695
5127
  if (fromError) return `Invalid time period from value: ${fromError}`;
@@ -4703,7 +5135,7 @@ VariableValidate.validators = Object.freeze({
4703
5135
  'time period ago': (value) => VariableValidate._validateWithRule(value, 'time_period_ago_atom', {
4704
5136
  normalize: VariableValidate._serializeTimePeriodAgo,
4705
5137
  emptyMessage: 'Time period ago variables must be objects with from, to, and ago properties',
4706
- parseMessage: 'Time period ago variables must serialize to FROM TO TO AGO AMOUNT UNIT syntax',
5138
+ parseMessage: 'Time period ago variables must serialize to AMOUNT UNIT AGO BETWEEN FROM AND TO syntax',
4707
5139
  semanticCheck: (rawValue) => {
4708
5140
  const fromError = VariableValidate._validateTimeOfDay(rawValue?.from);
4709
5141
  if (fromError) return `Invalid time period ago from value: ${fromError}`;