@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.
- package/README.md +16 -1
- package/dist/rule-templater.browser.js +489 -57
- package/index.d.ts +8 -1
- package/package.json +1 -1
- package/src/GeneralTemplate.js +91 -11
- package/src/RuleTemplate.ebnf.js +0 -9
- package/src/RuleTemplate.js +219 -27
- package/src/RuleTemplate.production.ebnf.js +1 -1
- package/src/RuleTemplate.production.js +219 -27
- package/src/RuleTemplater.production.js +71 -5
- package/src/TemplateFilters.js +88 -0
- package/src/VariableTemplate.js +74 -6
- package/src/VariableValidate.js +11 -8
package/index.d.ts
CHANGED
|
@@ -3,9 +3,14 @@ export interface VariablePosition {
|
|
|
3
3
|
end: number;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
+
export interface TemplateFilterCall {
|
|
7
|
+
name: string;
|
|
8
|
+
args: any[];
|
|
9
|
+
}
|
|
10
|
+
|
|
6
11
|
export interface VariableInfo {
|
|
7
12
|
name: string;
|
|
8
|
-
filters: string
|
|
13
|
+
filters: Array<string | TemplateFilterCall>;
|
|
9
14
|
positions: VariablePosition[];
|
|
10
15
|
}
|
|
11
16
|
|
|
@@ -134,6 +139,8 @@ export class GeneralTemplate {
|
|
|
134
139
|
|
|
135
140
|
extractVariables(): VariableInfo[];
|
|
136
141
|
|
|
142
|
+
validate(): ValidationResult;
|
|
143
|
+
|
|
137
144
|
prepare(variables: Variables): string;
|
|
138
145
|
}
|
|
139
146
|
|
package/package.json
CHANGED
package/src/GeneralTemplate.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const TemplateFilters = require('./TemplateFilters');
|
|
2
2
|
|
|
3
|
+
const FILTER_PATTERN = /([A-Za-z_][A-Za-z0-9_]*)(?:\((.*)\))?$/;
|
|
4
|
+
|
|
3
5
|
class GeneralTemplate {
|
|
4
6
|
constructor(templateText) {
|
|
5
7
|
this.templateText = templateText;
|
|
@@ -52,6 +54,33 @@ class GeneralTemplate {
|
|
|
52
54
|
return this.getVariables();
|
|
53
55
|
}
|
|
54
56
|
|
|
57
|
+
validate() {
|
|
58
|
+
const errors = [];
|
|
59
|
+
const warnings = [];
|
|
60
|
+
const seenFilterErrors = new Set();
|
|
61
|
+
|
|
62
|
+
for (const variableInfo of this.getVariables()) {
|
|
63
|
+
for (const filter of variableInfo.filters || []) {
|
|
64
|
+
const filterName = typeof filter === 'string' ? filter : filter?.name;
|
|
65
|
+
if (filterName && TemplateFilters[filterName]) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const errorMessage = `Unknown filter '${filterName || filter}' for variable '${variableInfo.name}'`;
|
|
70
|
+
if (!seenFilterErrors.has(errorMessage)) {
|
|
71
|
+
errors.push(errorMessage);
|
|
72
|
+
seenFilterErrors.add(errorMessage);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
valid: errors.length === 0,
|
|
79
|
+
errors,
|
|
80
|
+
warnings
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
55
84
|
prepare(variables) {
|
|
56
85
|
if (!variables || typeof variables !== 'object') {
|
|
57
86
|
throw new Error('Variables must be provided as an object');
|
|
@@ -76,12 +105,15 @@ class GeneralTemplate {
|
|
|
76
105
|
varData = Object.assign({}, varData);
|
|
77
106
|
|
|
78
107
|
if (parsedExpression.filters && parsedExpression.filters.length > 0) {
|
|
79
|
-
for (const
|
|
80
|
-
|
|
81
|
-
|
|
108
|
+
for (const filter of parsedExpression.filters) {
|
|
109
|
+
const filterName = typeof filter === 'string' ? filter : filter?.name;
|
|
110
|
+
const filterArgs = typeof filter === 'string' ? [] : (Array.isArray(filter?.args) ? filter.args : []);
|
|
111
|
+
|
|
112
|
+
if (!filterName || !TemplateFilters[filterName]) {
|
|
113
|
+
throw new Error(`Unknown filter '${filterName || filter}'`);
|
|
82
114
|
}
|
|
83
115
|
|
|
84
|
-
TemplateFilters[filterName](varData);
|
|
116
|
+
TemplateFilters[filterName](varData, ...filterArgs);
|
|
85
117
|
}
|
|
86
118
|
}
|
|
87
119
|
|
|
@@ -101,21 +133,69 @@ class GeneralTemplate {
|
|
|
101
133
|
|
|
102
134
|
return {
|
|
103
135
|
name: segments[0],
|
|
104
|
-
filters: segments.slice(1)
|
|
136
|
+
filters: segments.slice(1).map(segment => this._parseFilter(segment))
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
_parseFilter(segment) {
|
|
141
|
+
const match = segment.match(FILTER_PATTERN);
|
|
142
|
+
if (!match) {
|
|
143
|
+
return {
|
|
144
|
+
name: segment,
|
|
145
|
+
args: []
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const [, name, rawArgs] = match;
|
|
150
|
+
return {
|
|
151
|
+
name,
|
|
152
|
+
args: this._parseFilterArgs(rawArgs)
|
|
105
153
|
};
|
|
106
154
|
}
|
|
107
155
|
|
|
156
|
+
_parseFilterArgs(rawArgs) {
|
|
157
|
+
if (!rawArgs || !rawArgs.trim()) {
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return rawArgs.split(',').map(arg => this._parseFilterArgValue(arg.trim()));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
_parseFilterArgValue(rawArg) {
|
|
165
|
+
if ((rawArg.startsWith('"') && rawArg.endsWith('"')) || (rawArg.startsWith("'") && rawArg.endsWith("'"))) {
|
|
166
|
+
return rawArg.slice(1, -1);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (rawArg === 'true') {
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (rawArg === 'false') {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (rawArg === 'null') {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (rawArg !== '' && !Number.isNaN(Number(rawArg))) {
|
|
182
|
+
return Number(rawArg);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return rawArg;
|
|
186
|
+
}
|
|
187
|
+
|
|
108
188
|
_serializeVariable(varData) {
|
|
109
189
|
if (varData.value === null || varData.value === undefined) {
|
|
110
190
|
return '';
|
|
111
191
|
}
|
|
112
192
|
|
|
113
|
-
if (varData.type === 'time period'
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return
|
|
193
|
+
if (varData.type === 'time period') {
|
|
194
|
+
return `BETWEEN ${varData.value.from} AND ${varData.value.to}`;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (varData.type === 'time period ago') {
|
|
198
|
+
return `${varData.value.ago[0]} ${varData.value.ago[1]} AGO BETWEEN ${varData.value.from} AND ${varData.value.to}`;
|
|
119
199
|
}
|
|
120
200
|
|
|
121
201
|
return String(varData.value);
|
package/src/RuleTemplate.ebnf.js
CHANGED
|
@@ -23,18 +23,9 @@ const grammar = `
|
|
|
23
23
|
|
|
24
24
|
template_filter_arg ::= value | template_value
|
|
25
25
|
|
|
26
|
-
number_atom ::= number | template_value
|
|
27
|
-
number_time_atom ::= number_time | template_value WS+ unit | template_value
|
|
28
|
-
tod_atom ::= number_tod | template_value
|
|
29
|
-
dow_atom ::= dow | template_value
|
|
30
|
-
between_time_only_atom ::= between_time_only | template_value
|
|
31
|
-
between_tod_only_atom ::= between_tod_only | template_value
|
|
32
|
-
|
|
33
26
|
string_atom ::= string
|
|
34
27
|
boolean_atom ::= false | true
|
|
35
28
|
time_value_atom ::= number_tod
|
|
36
|
-
time_period_atom ::= time_value_atom WS* "TO" WS* time_value_atom
|
|
37
|
-
time_period_ago_atom ::= time_value_atom WS* "TO" WS* time_value_atom WS+ AGO WS+ number WS+ unit
|
|
38
29
|
|
|
39
30
|
object_atom ::= json_object
|
|
40
31
|
json_value ::= string | number | false | true | null | json_array | json_object
|
package/src/RuleTemplate.js
CHANGED
|
@@ -28,7 +28,7 @@ const AllowedTypeMapping = {
|
|
|
28
28
|
'number': ['number_atom', 'math_expr'],
|
|
29
29
|
'boolean': ['boolean_atom', 'boolean_expr'],
|
|
30
30
|
'time period': ['time_period_atom'],
|
|
31
|
-
'time period ago': ['
|
|
31
|
+
'time period ago': ['time_period_ago_atom'],
|
|
32
32
|
'time value': ['time_value_atom', 'tod_atom'],
|
|
33
33
|
'number time': ['number_atom'],
|
|
34
34
|
'string array': ['string_array'],
|
|
@@ -49,12 +49,71 @@ for(const rule of TemplateGrammar){
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
const cloneRule = (ruleName) => {
|
|
53
|
+
const idx = extendedGrammar.findIndex(rule => rule.name === ruleName);
|
|
54
|
+
if (idx === -1) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
extendedGrammar[idx] = Object.assign({}, extendedGrammar[idx], {
|
|
59
|
+
bnf: extendedGrammar[idx].bnf.map(alt => Array.isArray(alt) ? alt.slice() : alt)
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return extendedGrammar[idx];
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const appendAlternative = (ruleName, alternative) => {
|
|
66
|
+
const rule = cloneRule(ruleName);
|
|
67
|
+
if (!rule) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const exists = rule.bnf.some(existing => JSON.stringify(existing) === JSON.stringify(alternative));
|
|
72
|
+
if (!exists) {
|
|
73
|
+
rule.bnf.push(alternative);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const replaceRule = (ruleName, bnf) => {
|
|
78
|
+
const idx = extendedGrammar.findIndex(rule => rule.name === ruleName);
|
|
79
|
+
if (idx === -1) {
|
|
80
|
+
extendedGrammar.push({name: ruleName, bnf});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
extendedGrammar[idx] = Object.assign({}, extendedGrammar[idx], {
|
|
85
|
+
bnf: bnf.map(alt => alt.slice())
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
appendAlternative('number_atom', ['template_value']);
|
|
90
|
+
appendAlternative('number_time_atom', ['template_value', 'WS+', 'unit']);
|
|
91
|
+
appendAlternative('number_time_atom', ['template_value']);
|
|
92
|
+
appendAlternative('tod_atom', ['template_value']);
|
|
93
|
+
appendAlternative('dow_atom', ['template_value']);
|
|
94
|
+
appendAlternative('between_time_only_atom', ['template_value']);
|
|
95
|
+
appendAlternative('between_tod_only_atom', ['template_value']);
|
|
96
|
+
appendAlternative('string_atom', ['template_value']);
|
|
97
|
+
appendAlternative('boolean_atom', ['template_value']);
|
|
98
|
+
appendAlternative('time_value_atom', ['template_value']);
|
|
99
|
+
appendAlternative('time_period_atom', ['template_value']);
|
|
100
|
+
appendAlternative('time_period_ago_atom', ['template_value']);
|
|
101
|
+
appendAlternative('object_atom', ['template_value']);
|
|
102
|
+
appendAlternative('string_array', ['template_value']);
|
|
103
|
+
appendAlternative('number_array', ['template_value']);
|
|
104
|
+
appendAlternative('boolean_array', ['template_value']);
|
|
105
|
+
appendAlternative('object_array', ['template_value']);
|
|
106
|
+
|
|
107
|
+
replaceRule('argument', [
|
|
108
|
+
['number_time_atom', 'WS*'],
|
|
109
|
+
['statement', 'WS*']
|
|
110
|
+
]);
|
|
111
|
+
|
|
112
|
+
replaceRule('simple_result', [
|
|
113
|
+
['fcall'],
|
|
114
|
+
['number_time_atom'],
|
|
115
|
+
['value']
|
|
116
|
+
]);
|
|
58
117
|
|
|
59
118
|
// Export the parser rules for potential external use
|
|
60
119
|
const ParserRules = extendedGrammar;
|
|
@@ -185,11 +244,13 @@ class RuleTemplate {
|
|
|
185
244
|
|
|
186
245
|
// Extract filters
|
|
187
246
|
const filters = [];
|
|
247
|
+
const filterCalls = [];
|
|
188
248
|
for (const child of templateExpr.children || []) {
|
|
189
249
|
if (child.type === 'template_filter_call') {
|
|
190
|
-
const
|
|
191
|
-
if (
|
|
192
|
-
filters.push(
|
|
250
|
+
const filterCall = this._extractFilterCall(child);
|
|
251
|
+
if (filterCall) {
|
|
252
|
+
filters.push(filterCall.name);
|
|
253
|
+
filterCalls.push(filterCall);
|
|
193
254
|
}
|
|
194
255
|
}
|
|
195
256
|
}
|
|
@@ -198,18 +259,84 @@ class RuleTemplate {
|
|
|
198
259
|
const start = node.start;
|
|
199
260
|
const end = node.end;
|
|
200
261
|
|
|
201
|
-
return { name, filters, start, end };
|
|
262
|
+
return { name, filters, filterCalls, start, end };
|
|
202
263
|
}
|
|
203
264
|
|
|
204
265
|
/**
|
|
205
|
-
* Extract filter
|
|
266
|
+
* Extract filter call from template_filter_call node
|
|
206
267
|
* @private
|
|
207
268
|
*/
|
|
208
|
-
|
|
269
|
+
_extractFilterCall(node) {
|
|
209
270
|
const filterNameNode = node.children?.find(c => c.type === 'template_filter_name');
|
|
210
271
|
if (!filterNameNode || !filterNameNode.text) return null;
|
|
211
|
-
|
|
212
|
-
|
|
272
|
+
|
|
273
|
+
const argsNode = node.children?.find(c => c.type === 'template_filter_args');
|
|
274
|
+
|
|
275
|
+
return {
|
|
276
|
+
name: filterNameNode.text.trim(),
|
|
277
|
+
args: this._extractFilterArgs(argsNode)
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
_extractFilterArgs(node) {
|
|
282
|
+
if (!node || !Array.isArray(node.children)) {
|
|
283
|
+
return [];
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return node.children
|
|
287
|
+
.filter(child => child.type === 'template_filter_arg')
|
|
288
|
+
.map(child => this._extractFilterArgValue(child));
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
_extractFilterArgValue(node) {
|
|
292
|
+
if (!node || !Array.isArray(node.children) || node.children.length === 0) {
|
|
293
|
+
return this._normalizeFilterArgText(node?.text?.trim() || '');
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const child = node.children[0];
|
|
297
|
+
if (!child) {
|
|
298
|
+
return this._normalizeFilterArgText(node.text?.trim() || '');
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (child.type === 'value' && Array.isArray(child.children) && child.children.length > 0) {
|
|
302
|
+
return this._extractFilterArgValue(child);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (child.type === 'string') {
|
|
306
|
+
try {
|
|
307
|
+
return JSON.parse(child.text);
|
|
308
|
+
} catch (error) {
|
|
309
|
+
return this._normalizeFilterArgText(child.text);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (child.type === 'number') {
|
|
314
|
+
return Number(child.text);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (child.type === 'true') {
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (child.type === 'false') {
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (child.type === 'null') {
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return this._normalizeFilterArgText(child.text?.trim() || node.text?.trim() || '');
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
_normalizeFilterArgText(text) {
|
|
333
|
+
const normalizedText = String(text).trim();
|
|
334
|
+
|
|
335
|
+
if ((normalizedText.startsWith('"') && normalizedText.endsWith('"')) || (normalizedText.startsWith("'") && normalizedText.endsWith("'"))) {
|
|
336
|
+
return normalizedText.slice(1, -1);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return normalizedText;
|
|
213
340
|
}
|
|
214
341
|
|
|
215
342
|
/**
|
|
@@ -229,10 +356,31 @@ class RuleTemplate {
|
|
|
229
356
|
|
|
230
357
|
const errors = [];
|
|
231
358
|
const warnings = [];
|
|
232
|
-
const extractedVars = this.
|
|
359
|
+
const extractedVars = this._extractTemplateVariables();
|
|
360
|
+
const seenVariables = new Set();
|
|
361
|
+
const seenFilterErrors = new Set();
|
|
233
362
|
|
|
234
363
|
for (const varInfo of extractedVars) {
|
|
235
364
|
const varName = varInfo.name;
|
|
365
|
+
|
|
366
|
+
for (const filter of (varInfo.filterCalls || varInfo.filters || [])) {
|
|
367
|
+
const filterName = typeof filter === 'string' ? filter : filter?.name;
|
|
368
|
+
if (filterName && TemplateFilters[filterName]) {
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const errorMessage = `Unknown filter '${filterName || filter}' for variable '${varName}'`;
|
|
373
|
+
if (!seenFilterErrors.has(errorMessage)) {
|
|
374
|
+
errors.push(errorMessage);
|
|
375
|
+
seenFilterErrors.add(errorMessage);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (seenVariables.has(varName)) {
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
seenVariables.add(varName);
|
|
236
384
|
|
|
237
385
|
// Check if variable is provided
|
|
238
386
|
if (!variables.hasOwnProperty(varName)) {
|
|
@@ -262,6 +410,23 @@ class RuleTemplate {
|
|
|
262
410
|
}
|
|
263
411
|
}
|
|
264
412
|
|
|
413
|
+
const canValidatePreparedRule = errors.length === 0
|
|
414
|
+
&& Array.from(seenVariables).every(varName => {
|
|
415
|
+
const varData = variables[varName];
|
|
416
|
+
return varData
|
|
417
|
+
&& typeof varData === 'object'
|
|
418
|
+
&& Object.prototype.hasOwnProperty.call(varData, 'type')
|
|
419
|
+
&& Object.prototype.hasOwnProperty.call(varData, 'value');
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
if (canValidatePreparedRule) {
|
|
423
|
+
try {
|
|
424
|
+
RuleParser.toAst(this.prepare(variables));
|
|
425
|
+
} catch (error) {
|
|
426
|
+
errors.push(`Prepared rule is invalid: ${error.message}`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
265
430
|
if (functionBlob && typeof functionBlob.validate === 'function') {
|
|
266
431
|
for (const functionCall of this._extractFunctionCalls()) {
|
|
267
432
|
warnings.push(...functionBlob.validate(functionCall.name, functionCall.arguments));
|
|
@@ -305,6 +470,30 @@ class RuleTemplate {
|
|
|
305
470
|
return functionCalls;
|
|
306
471
|
}
|
|
307
472
|
|
|
473
|
+
_extractTemplateVariables() {
|
|
474
|
+
const variables = [];
|
|
475
|
+
|
|
476
|
+
const traverse = (node) => {
|
|
477
|
+
if (!node) return;
|
|
478
|
+
|
|
479
|
+
if (node.type === 'template_value') {
|
|
480
|
+
const variableInfo = this._extractVariableFromNode(node);
|
|
481
|
+
if (variableInfo) {
|
|
482
|
+
variables.push(variableInfo);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (node.children) {
|
|
487
|
+
for (const child of node.children) {
|
|
488
|
+
traverse(child);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
traverse(this.ast);
|
|
494
|
+
return variables;
|
|
495
|
+
}
|
|
496
|
+
|
|
308
497
|
/**
|
|
309
498
|
* Prepare the template by replacing variables with their values
|
|
310
499
|
* Rebuilds from AST by iterating through children
|
|
@@ -407,12 +596,15 @@ class RuleTemplate {
|
|
|
407
596
|
|
|
408
597
|
// Apply filters if present
|
|
409
598
|
if (templateInfo.filters && templateInfo.filters.length > 0) {
|
|
410
|
-
for (const
|
|
411
|
-
|
|
412
|
-
|
|
599
|
+
for (const filter of (templateInfo.filterCalls || templateInfo.filters)) {
|
|
600
|
+
const filterName = typeof filter === 'string' ? filter : filter?.name;
|
|
601
|
+
const filterArgs = typeof filter === 'string' ? [] : (Array.isArray(filter?.args) ? filter.args : []);
|
|
602
|
+
|
|
603
|
+
if (!filterName || !TemplateFilters[filterName]) {
|
|
604
|
+
throw new Error(`Unknown filter '${filterName || filter}'`);
|
|
413
605
|
}
|
|
414
|
-
|
|
415
|
-
TemplateFilters[filterName](varData);
|
|
606
|
+
|
|
607
|
+
TemplateFilters[filterName](varData, ...filterArgs);
|
|
416
608
|
}
|
|
417
609
|
}
|
|
418
610
|
|
|
@@ -443,12 +635,12 @@ class RuleTemplate {
|
|
|
443
635
|
return value ? 'true' : 'false';
|
|
444
636
|
}
|
|
445
637
|
|
|
446
|
-
if (type === 'time period'
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
return
|
|
638
|
+
if (type === 'time period') {
|
|
639
|
+
return `BETWEEN ${value.from} AND ${value.to}`;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
if (type === 'time period ago') {
|
|
643
|
+
return `${value.ago[0]} ${value.ago[1]} AGO BETWEEN ${value.from} AND ${value.to}`;
|
|
452
644
|
}
|
|
453
645
|
|
|
454
646
|
if (type === 'object' || type === 'string array' || type === 'number array' || type === 'boolean array' || type === 'object array') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
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":"
|
|
1
|
+
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"]]}]
|