@halleyassist/rule-templater 0.0.1 → 0.0.4
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 +231 -231
- package/dist/rule-templater.browser.js +2453 -0
- package/index.d.ts +91 -91
- package/index.js +0 -0
- package/package.json +47 -47
- package/src/RuleTemplate.ebnf.js +34 -27
- package/src/RuleTemplate.production.ebnf.js +1 -0
- package/src/RuleTemplater.browser.js +0 -0
- package/src/RuleTemplater.js +348 -339
- package/src/RuleTemplater.production.js +349 -0
- package/src/TemplateFilters.js +62 -62
package/README.md
CHANGED
|
@@ -1,231 +1,231 @@
|
|
|
1
|
-
# rule-templater
|
|
2
|
-
|
|
3
|
-
Parsing and preparation of rule templates for HalleyAssist rules.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install @halleyassist/rule-templater
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Usage
|
|
12
|
-
|
|
13
|
-
The `rule-templater` package provides utilities for working with rule templates that contain variable placeholders.
|
|
14
|
-
|
|
15
|
-
### Basic Example
|
|
16
|
-
|
|
17
|
-
```javascript
|
|
18
|
-
const RuleTemplate = require('@halleyassist/rule-templater');
|
|
19
|
-
|
|
20
|
-
// Define a template with variables
|
|
21
|
-
const template = 'EventIs(${EVENT_TYPE}) && Value() > ${THRESHOLD}';
|
|
22
|
-
|
|
23
|
-
// Parse the template to get a RuleTemplate instance
|
|
24
|
-
const parsed = RuleTemplate.parse(template);
|
|
25
|
-
|
|
26
|
-
// Extract variables from the template (uses AST)
|
|
27
|
-
const variables = parsed.extractVariables();
|
|
28
|
-
console.log(variables);
|
|
29
|
-
// [
|
|
30
|
-
// { name: 'EVENT_TYPE', filters: [] },
|
|
31
|
-
// { name: 'THRESHOLD', filters: [] }
|
|
32
|
-
// ]
|
|
33
|
-
|
|
34
|
-
// Validate that variables are provided correctly
|
|
35
|
-
const validation = parsed.validate({
|
|
36
|
-
EVENT_TYPE: { value: 'sensor-update', type: 'string' },
|
|
37
|
-
THRESHOLD: { value: 42, type: 'number' }
|
|
38
|
-
});
|
|
39
|
-
console.log(validation.valid); // true
|
|
40
|
-
|
|
41
|
-
// Prepare the template with actual values
|
|
42
|
-
const prepared = parsed.prepare({
|
|
43
|
-
EVENT_TYPE: { value: 'sensor-update', type: 'string' },
|
|
44
|
-
THRESHOLD: { value: 42, type: 'number' }
|
|
45
|
-
});
|
|
46
|
-
console.log(prepared);
|
|
47
|
-
// 'EventIs("sensor-update") && Value() > 42'
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### Complex Example
|
|
51
|
-
|
|
52
|
-
```javascript
|
|
53
|
-
const template = '!(EventIs(StrConcat("DeviceEvent:measurement:", ${ACTION})) && TimeLastTrueSet("last_measurement") || TimeLastTrueCheck("last_measurement") < ${TIME})';
|
|
54
|
-
|
|
55
|
-
const parsed = RuleTemplate.parse(template);
|
|
56
|
-
|
|
57
|
-
// Extract variables
|
|
58
|
-
const variables = parsed.extractVariables();
|
|
59
|
-
// [
|
|
60
|
-
// { name: 'ACTION', filters: [] },
|
|
61
|
-
// { name: 'TIME', filters: [] }
|
|
62
|
-
// ]
|
|
63
|
-
|
|
64
|
-
// Prepare with values
|
|
65
|
-
const prepared = parsed.prepare({
|
|
66
|
-
ACTION: { value: 'temperature', type: 'string' },
|
|
67
|
-
TIME: { value: 60, type: 'number' }
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
// Result: !(EventIs(StrConcat("DeviceEvent:measurement:", "temperature")) && TimeLastTrueSet("last_measurement") || TimeLastTrueCheck("last_measurement") < 60)
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### Template Filters
|
|
74
|
-
|
|
75
|
-
Variables can have filters applied to transform their values. Filters are applied using the pipe (`|`) syntax:
|
|
76
|
-
|
|
77
|
-
```javascript
|
|
78
|
-
const template = 'EventIs(${EVENT_TYPE|upper})';
|
|
79
|
-
|
|
80
|
-
const parsed = RuleTemplate.parse(template);
|
|
81
|
-
const variables = parsed.extractVariables();
|
|
82
|
-
// [{ name: 'EVENT_TYPE', filters: ['upper'] }]
|
|
83
|
-
|
|
84
|
-
// Prepare with filters applied
|
|
85
|
-
const prepared = parsed.prepare({
|
|
86
|
-
EVENT_TYPE: { value: 'sensor-update' }
|
|
87
|
-
});
|
|
88
|
-
// Result: EventIs(SENSOR-UPDATE)
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
#### Multiple Filters
|
|
92
|
-
|
|
93
|
-
Filters can be chained together and are applied in sequence:
|
|
94
|
-
|
|
95
|
-
```javascript
|
|
96
|
-
const template = 'EventIs(${EVENT|trim|upper|string})';
|
|
97
|
-
|
|
98
|
-
const parsed = RuleTemplate.parse(template);
|
|
99
|
-
const prepared = parsed.prepare({
|
|
100
|
-
EVENT: { value: ' test ' }
|
|
101
|
-
});
|
|
102
|
-
// Result: EventIs("TEST")
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
#### Available Filters
|
|
106
|
-
|
|
107
|
-
- **string**: Convert to JSON string representation (adds quotes and escapes)
|
|
108
|
-
- **upper**: Convert to uppercase
|
|
109
|
-
- **lower**: Convert to lowercase
|
|
110
|
-
- **capitalize**: Capitalize first letter
|
|
111
|
-
- **title**: Convert to title case (capitalize each word)
|
|
112
|
-
- **trim**: Remove leading/trailing whitespace
|
|
113
|
-
- **number**: Convert to number
|
|
114
|
-
- **boolean**: Convert to boolean
|
|
115
|
-
- **abs**: Absolute value (for numbers)
|
|
116
|
-
- **round**: Round number to nearest integer
|
|
117
|
-
- **floor**: Round number down
|
|
118
|
-
- **ceil**: Round number up
|
|
119
|
-
|
|
120
|
-
#### Filter Examples
|
|
121
|
-
|
|
122
|
-
```javascript
|
|
123
|
-
// String transformation
|
|
124
|
-
'${name|upper}' with name='john' → JOHN
|
|
125
|
-
'${name|capitalize}' with name='john doe' → John doe
|
|
126
|
-
'${name|title}' with name='john doe' → John Doe
|
|
127
|
-
|
|
128
|
-
// Number operations
|
|
129
|
-
'${value|abs}' with value=-42 → 42
|
|
130
|
-
'${value|round}' with value=3.7 → 4
|
|
131
|
-
'${value|floor}' with value=3.9 → 3
|
|
132
|
-
|
|
133
|
-
// Chaining filters
|
|
134
|
-
'${text|trim|upper}' with text=' hello ' → HELLO
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
## API
|
|
138
|
-
|
|
139
|
-
### `RuleTemplate.parse(ruleTemplate)`
|
|
140
|
-
|
|
141
|
-
Parses a rule template string and returns a RuleTemplate instance.
|
|
142
|
-
|
|
143
|
-
**Parameters:**
|
|
144
|
-
- `ruleTemplate` (string): The template string containing `${VARIABLE}` placeholders
|
|
145
|
-
|
|
146
|
-
**Returns:** A `RuleTemplate` instance with:
|
|
147
|
-
- `ruleTemplateText`: The original template string
|
|
148
|
-
- `ast`: The parsed Abstract Syntax Tree
|
|
149
|
-
|
|
150
|
-
### `ruleTemplate.extractVariables()`
|
|
151
|
-
|
|
152
|
-
Extracts all variables from the template using the AST.
|
|
153
|
-
|
|
154
|
-
**Returns:** Array of objects with:
|
|
155
|
-
- `name` (string): The variable name
|
|
156
|
-
- `filters` (array): Array of filter names applied to the variable
|
|
157
|
-
|
|
158
|
-
### `ruleTemplate.validate(variables)`
|
|
159
|
-
|
|
160
|
-
Validates that all required variables are provided and have valid types.
|
|
161
|
-
|
|
162
|
-
**Parameters:**
|
|
163
|
-
- `variables` (object): Object mapping variable names to their values and types
|
|
164
|
-
- Each variable should be an object with:
|
|
165
|
-
- `value`: The value to substitute (string, number, or boolean)
|
|
166
|
-
- `type` (optional): The variable type ('string', 'number', 'boolean', etc.)
|
|
167
|
-
|
|
168
|
-
**Returns:** Object with:
|
|
169
|
-
- `valid` (boolean): Whether validation passed
|
|
170
|
-
- `errors` (array): Array of error messages (empty if valid)
|
|
171
|
-
|
|
172
|
-
### `ruleTemplate.prepare(variables)`
|
|
173
|
-
|
|
174
|
-
Prepares the template by replacing variables with their values and applying any filters.
|
|
175
|
-
|
|
176
|
-
**Parameters:**
|
|
177
|
-
- `variables` (object): Object mapping variable names to their values and types
|
|
178
|
-
- Each variable should be an object with:
|
|
179
|
-
- `value`: The value to substitute (string, number, or boolean)
|
|
180
|
-
- `type` (optional): The variable type ('string', 'number', 'boolean', etc.)
|
|
181
|
-
|
|
182
|
-
**Returns:** The prepared rule string with variables replaced and filters applied
|
|
183
|
-
|
|
184
|
-
### `RuleTemplate.validateVariableNode(astNode, variableType)` (Static)
|
|
185
|
-
|
|
186
|
-
Helper method to validate that an AST node matches the expected variable type.
|
|
187
|
-
|
|
188
|
-
**Parameters:**
|
|
189
|
-
- `astNode`: The AST node to validate
|
|
190
|
-
- `variableType` (string): The expected variable type
|
|
191
|
-
|
|
192
|
-
**Returns:** `true` if the node is valid for the given type, `false` otherwise
|
|
193
|
-
|
|
194
|
-
### `RuleTemplate.TemplateFilters` (Static)
|
|
195
|
-
|
|
196
|
-
Access to the filter functions used by the template engine. Can be extended with custom filters.
|
|
197
|
-
|
|
198
|
-
**Example:**
|
|
199
|
-
```javascript
|
|
200
|
-
const RuleTemplate = require('@halleyassist/rule-templater');
|
|
201
|
-
|
|
202
|
-
// Add a custom filter
|
|
203
|
-
RuleTemplate.TemplateFilters.reverse = (value) => {
|
|
204
|
-
return String(value).split('').reverse().join('');
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
// Use the custom filter
|
|
208
|
-
const template = 'EventIs(${EVENT|reverse})';
|
|
209
|
-
const parsed = RuleTemplate.parse(template);
|
|
210
|
-
const result = parsed.prepare({ EVENT: { value: 'test' } });
|
|
211
|
-
// Result: EventIs(tset)
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
## Variable Types
|
|
215
|
-
|
|
216
|
-
The following variable types are supported:
|
|
217
|
-
|
|
218
|
-
- `string`
|
|
219
|
-
- `number`
|
|
220
|
-
- `boolean`
|
|
221
|
-
- `object`
|
|
222
|
-
- `time period`
|
|
223
|
-
- `time value`
|
|
224
|
-
- `string array`
|
|
225
|
-
- `number array`
|
|
226
|
-
- `boolean array`
|
|
227
|
-
- `object array`
|
|
228
|
-
|
|
229
|
-
## License
|
|
230
|
-
|
|
231
|
-
ISC
|
|
1
|
+
# rule-templater
|
|
2
|
+
|
|
3
|
+
Parsing and preparation of rule templates for HalleyAssist rules.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @halleyassist/rule-templater
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
The `rule-templater` package provides utilities for working with rule templates that contain variable placeholders.
|
|
14
|
+
|
|
15
|
+
### Basic Example
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
const RuleTemplate = require('@halleyassist/rule-templater');
|
|
19
|
+
|
|
20
|
+
// Define a template with variables
|
|
21
|
+
const template = 'EventIs(${EVENT_TYPE}) && Value() > ${THRESHOLD}';
|
|
22
|
+
|
|
23
|
+
// Parse the template to get a RuleTemplate instance
|
|
24
|
+
const parsed = RuleTemplate.parse(template);
|
|
25
|
+
|
|
26
|
+
// Extract variables from the template (uses AST)
|
|
27
|
+
const variables = parsed.extractVariables();
|
|
28
|
+
console.log(variables);
|
|
29
|
+
// [
|
|
30
|
+
// { name: 'EVENT_TYPE', filters: [] },
|
|
31
|
+
// { name: 'THRESHOLD', filters: [] }
|
|
32
|
+
// ]
|
|
33
|
+
|
|
34
|
+
// Validate that variables are provided correctly
|
|
35
|
+
const validation = parsed.validate({
|
|
36
|
+
EVENT_TYPE: { value: 'sensor-update', type: 'string' },
|
|
37
|
+
THRESHOLD: { value: 42, type: 'number' }
|
|
38
|
+
});
|
|
39
|
+
console.log(validation.valid); // true
|
|
40
|
+
|
|
41
|
+
// Prepare the template with actual values
|
|
42
|
+
const prepared = parsed.prepare({
|
|
43
|
+
EVENT_TYPE: { value: 'sensor-update', type: 'string' },
|
|
44
|
+
THRESHOLD: { value: 42, type: 'number' }
|
|
45
|
+
});
|
|
46
|
+
console.log(prepared);
|
|
47
|
+
// 'EventIs("sensor-update") && Value() > 42'
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Complex Example
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
const template = '!(EventIs(StrConcat("DeviceEvent:measurement:", ${ACTION})) && TimeLastTrueSet("last_measurement") || TimeLastTrueCheck("last_measurement") < ${TIME})';
|
|
54
|
+
|
|
55
|
+
const parsed = RuleTemplate.parse(template);
|
|
56
|
+
|
|
57
|
+
// Extract variables
|
|
58
|
+
const variables = parsed.extractVariables();
|
|
59
|
+
// [
|
|
60
|
+
// { name: 'ACTION', filters: [] },
|
|
61
|
+
// { name: 'TIME', filters: [] }
|
|
62
|
+
// ]
|
|
63
|
+
|
|
64
|
+
// Prepare with values
|
|
65
|
+
const prepared = parsed.prepare({
|
|
66
|
+
ACTION: { value: 'temperature', type: 'string' },
|
|
67
|
+
TIME: { value: 60, type: 'number' }
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Result: !(EventIs(StrConcat("DeviceEvent:measurement:", "temperature")) && TimeLastTrueSet("last_measurement") || TimeLastTrueCheck("last_measurement") < 60)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Template Filters
|
|
74
|
+
|
|
75
|
+
Variables can have filters applied to transform their values. Filters are applied using the pipe (`|`) syntax:
|
|
76
|
+
|
|
77
|
+
```javascript
|
|
78
|
+
const template = 'EventIs(${EVENT_TYPE|upper})';
|
|
79
|
+
|
|
80
|
+
const parsed = RuleTemplate.parse(template);
|
|
81
|
+
const variables = parsed.extractVariables();
|
|
82
|
+
// [{ name: 'EVENT_TYPE', filters: ['upper'] }]
|
|
83
|
+
|
|
84
|
+
// Prepare with filters applied
|
|
85
|
+
const prepared = parsed.prepare({
|
|
86
|
+
EVENT_TYPE: { value: 'sensor-update' }
|
|
87
|
+
});
|
|
88
|
+
// Result: EventIs(SENSOR-UPDATE)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### Multiple Filters
|
|
92
|
+
|
|
93
|
+
Filters can be chained together and are applied in sequence:
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
const template = 'EventIs(${EVENT|trim|upper|string})';
|
|
97
|
+
|
|
98
|
+
const parsed = RuleTemplate.parse(template);
|
|
99
|
+
const prepared = parsed.prepare({
|
|
100
|
+
EVENT: { value: ' test ' }
|
|
101
|
+
});
|
|
102
|
+
// Result: EventIs("TEST")
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### Available Filters
|
|
106
|
+
|
|
107
|
+
- **string**: Convert to JSON string representation (adds quotes and escapes)
|
|
108
|
+
- **upper**: Convert to uppercase
|
|
109
|
+
- **lower**: Convert to lowercase
|
|
110
|
+
- **capitalize**: Capitalize first letter
|
|
111
|
+
- **title**: Convert to title case (capitalize each word)
|
|
112
|
+
- **trim**: Remove leading/trailing whitespace
|
|
113
|
+
- **number**: Convert to number
|
|
114
|
+
- **boolean**: Convert to boolean
|
|
115
|
+
- **abs**: Absolute value (for numbers)
|
|
116
|
+
- **round**: Round number to nearest integer
|
|
117
|
+
- **floor**: Round number down
|
|
118
|
+
- **ceil**: Round number up
|
|
119
|
+
|
|
120
|
+
#### Filter Examples
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
// String transformation
|
|
124
|
+
'${name|upper}' with name='john' → JOHN
|
|
125
|
+
'${name|capitalize}' with name='john doe' → John doe
|
|
126
|
+
'${name|title}' with name='john doe' → John Doe
|
|
127
|
+
|
|
128
|
+
// Number operations
|
|
129
|
+
'${value|abs}' with value=-42 → 42
|
|
130
|
+
'${value|round}' with value=3.7 → 4
|
|
131
|
+
'${value|floor}' with value=3.9 → 3
|
|
132
|
+
|
|
133
|
+
// Chaining filters
|
|
134
|
+
'${text|trim|upper}' with text=' hello ' → HELLO
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## API
|
|
138
|
+
|
|
139
|
+
### `RuleTemplate.parse(ruleTemplate)`
|
|
140
|
+
|
|
141
|
+
Parses a rule template string and returns a RuleTemplate instance.
|
|
142
|
+
|
|
143
|
+
**Parameters:**
|
|
144
|
+
- `ruleTemplate` (string): The template string containing `${VARIABLE}` placeholders
|
|
145
|
+
|
|
146
|
+
**Returns:** A `RuleTemplate` instance with:
|
|
147
|
+
- `ruleTemplateText`: The original template string
|
|
148
|
+
- `ast`: The parsed Abstract Syntax Tree
|
|
149
|
+
|
|
150
|
+
### `ruleTemplate.extractVariables()`
|
|
151
|
+
|
|
152
|
+
Extracts all variables from the template using the AST.
|
|
153
|
+
|
|
154
|
+
**Returns:** Array of objects with:
|
|
155
|
+
- `name` (string): The variable name
|
|
156
|
+
- `filters` (array): Array of filter names applied to the variable
|
|
157
|
+
|
|
158
|
+
### `ruleTemplate.validate(variables)`
|
|
159
|
+
|
|
160
|
+
Validates that all required variables are provided and have valid types.
|
|
161
|
+
|
|
162
|
+
**Parameters:**
|
|
163
|
+
- `variables` (object): Object mapping variable names to their values and types
|
|
164
|
+
- Each variable should be an object with:
|
|
165
|
+
- `value`: The value to substitute (string, number, or boolean)
|
|
166
|
+
- `type` (optional): The variable type ('string', 'number', 'boolean', etc.)
|
|
167
|
+
|
|
168
|
+
**Returns:** Object with:
|
|
169
|
+
- `valid` (boolean): Whether validation passed
|
|
170
|
+
- `errors` (array): Array of error messages (empty if valid)
|
|
171
|
+
|
|
172
|
+
### `ruleTemplate.prepare(variables)`
|
|
173
|
+
|
|
174
|
+
Prepares the template by replacing variables with their values and applying any filters.
|
|
175
|
+
|
|
176
|
+
**Parameters:**
|
|
177
|
+
- `variables` (object): Object mapping variable names to their values and types
|
|
178
|
+
- Each variable should be an object with:
|
|
179
|
+
- `value`: The value to substitute (string, number, or boolean)
|
|
180
|
+
- `type` (optional): The variable type ('string', 'number', 'boolean', etc.)
|
|
181
|
+
|
|
182
|
+
**Returns:** The prepared rule string with variables replaced and filters applied
|
|
183
|
+
|
|
184
|
+
### `RuleTemplate.validateVariableNode(astNode, variableType)` (Static)
|
|
185
|
+
|
|
186
|
+
Helper method to validate that an AST node matches the expected variable type.
|
|
187
|
+
|
|
188
|
+
**Parameters:**
|
|
189
|
+
- `astNode`: The AST node to validate
|
|
190
|
+
- `variableType` (string): The expected variable type
|
|
191
|
+
|
|
192
|
+
**Returns:** `true` if the node is valid for the given type, `false` otherwise
|
|
193
|
+
|
|
194
|
+
### `RuleTemplate.TemplateFilters` (Static)
|
|
195
|
+
|
|
196
|
+
Access to the filter functions used by the template engine. Can be extended with custom filters.
|
|
197
|
+
|
|
198
|
+
**Example:**
|
|
199
|
+
```javascript
|
|
200
|
+
const RuleTemplate = require('@halleyassist/rule-templater');
|
|
201
|
+
|
|
202
|
+
// Add a custom filter
|
|
203
|
+
RuleTemplate.TemplateFilters.reverse = (value) => {
|
|
204
|
+
return String(value).split('').reverse().join('');
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// Use the custom filter
|
|
208
|
+
const template = 'EventIs(${EVENT|reverse})';
|
|
209
|
+
const parsed = RuleTemplate.parse(template);
|
|
210
|
+
const result = parsed.prepare({ EVENT: { value: 'test' } });
|
|
211
|
+
// Result: EventIs(tset)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Variable Types
|
|
215
|
+
|
|
216
|
+
The following variable types are supported:
|
|
217
|
+
|
|
218
|
+
- `string`
|
|
219
|
+
- `number`
|
|
220
|
+
- `boolean`
|
|
221
|
+
- `object`
|
|
222
|
+
- `time period`
|
|
223
|
+
- `time value`
|
|
224
|
+
- `string array`
|
|
225
|
+
- `number array`
|
|
226
|
+
- `boolean array`
|
|
227
|
+
- `object array`
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
ISC
|