@halleyassist/rule-templater 0.0.11 → 0.0.12

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 CHANGED
@@ -144,6 +144,29 @@ const prepared = parsed.prepare({
144
144
  '${window|time_start}' with window={from:'08:00',to:'12:00'} → 08:00
145
145
  ```
146
146
 
147
+ ### General String Templating
148
+
149
+ For non-rule text templates, use `GeneralTemplate`:
150
+
151
+ ```javascript
152
+ const RuleTemplate = require('@halleyassist/rule-templater');
153
+ const { GeneralTemplate } = RuleTemplate;
154
+
155
+ const template = 'If a door is opened between ${ALERT_PERIOD | time_start} AND ${ALERT_PERIOD | time_end}';
156
+
157
+ const variables = GeneralTemplate.getVariables(template);
158
+ // [{ name: 'ALERT_PERIOD', filters: ['time_start', 'time_end'], positions: [...] }]
159
+
160
+ const parsed = GeneralTemplate.parse(template);
161
+ const prepared = parsed.prepare({
162
+ ALERT_PERIOD: {
163
+ value: { from: '08:00', to: '12:00' },
164
+ type: 'time period'
165
+ }
166
+ });
167
+ // If a door is opened between 08:00 AND 12:00
168
+ ```
169
+
147
170
  ## API
148
171
 
149
172
  ### `RuleTemplate.parse(ruleTemplate)`
@@ -213,6 +236,22 @@ Prepares the template by replacing variables with their values and applying any
213
236
 
214
237
  **Returns:** The prepared rule string with variables replaced and filters applied
215
238
 
239
+ ### `GeneralTemplate.parse(templateText)`
240
+
241
+ Parses a general string template and returns a `GeneralTemplate` instance.
242
+
243
+ ### `GeneralTemplate.getVariables(templateText)` (Static)
244
+
245
+ Extracts variables from a general string template without creating an instance manually.
246
+
247
+ ### `generalTemplate.getVariables()`
248
+
249
+ Extracts variables from a general string template.
250
+
251
+ ### `generalTemplate.prepare(variables)`
252
+
253
+ Prepares a general string template by replacing `${...}` placeholders with values and applying filters.
254
+
216
255
  ### `RuleTemplate.validateVariableNode(astNode, variableType)` (Static)
217
256
 
218
257
  Helper method to validate that an AST node matches the expected variable type.
@@ -255,6 +294,7 @@ The following variable types are supported:
255
294
  - `boolean`
256
295
  - `object`
257
296
  - `time period`
297
+ - `time period ago`
258
298
  - `time value`
259
299
  - `string array`
260
300
  - `number array`
@@ -4068,11 +4068,12 @@ class RuleTemplate {
4068
4068
  }
4069
4069
  }
4070
4070
 
4071
- // Export the class and parser rules
4071
+ RuleTemplate.ParserRules = ParserRules;
4072
+ RuleTemplate.VariableTypes = VariableTypes;
4073
+ RuleTemplate.TemplateFilters = TemplateFilters;
4074
+
4072
4075
  module.exports = RuleTemplate;
4073
- module.exports.ParserRules = ParserRules;
4074
- module.exports.VariableTypes = VariableTypes;
4075
- module.exports.TemplateFilters = TemplateFilters;
4076
+
4076
4077
  },{"./RuleTemplate.production.ebnf.js":14,"./TemplateFilters":17,"@halleyassist/rule-parser":2,"ebnf":13}],17:[function(require,module,exports){
4077
4078
  /*
4078
4079
  Template filters are functions that transform variable values.
package/index.d.ts CHANGED
@@ -10,8 +10,12 @@ export interface VariableInfo {
10
10
  }
11
11
 
12
12
  export interface VariableValue {
13
- value: string | number | boolean;
14
- type?: 'string' | 'number' | 'boolean' | 'object' | 'time period' | 'time value' | 'string array' | 'number array' | 'boolean array' | 'object array';
13
+ value: string | number | boolean | {
14
+ from: string;
15
+ to: string;
16
+ ago?: [number, string];
17
+ };
18
+ type?: 'string' | 'number' | 'boolean' | 'object' | 'time period' | 'time period ago' | 'time value' | 'string array' | 'number array' | 'boolean array' | 'object array';
15
19
  }
16
20
 
17
21
  export interface Variables {
@@ -50,7 +54,7 @@ export interface TemplateFiltersType {
50
54
  [key: string]: FilterFunction;
51
55
  }
52
56
 
53
- export default class RuleTemplate {
57
+ export class RuleTemplate {
54
58
  ruleTemplateText: string;
55
59
  ast: ASTNode;
56
60
 
@@ -99,6 +103,22 @@ export default class RuleTemplate {
99
103
  static validateVariableNode(astNode: ASTNode | null | undefined, variableType: string): boolean;
100
104
  }
101
105
 
106
+ export class GeneralTemplate {
107
+ templateText: string;
108
+
109
+ constructor(templateText: string);
110
+
111
+ static parse(templateText: string): GeneralTemplate;
112
+
113
+ static getVariables(templateText: string): VariableInfo[];
114
+
115
+ getVariables(): VariableInfo[];
116
+
117
+ extractVariables(): VariableInfo[];
118
+
119
+ prepare(variables: Variables): string;
120
+ }
121
+
102
122
  export const ParserRules: any[];
103
123
  export const VariableTypes: string[];
104
124
  export const TemplateFilters: TemplateFiltersType;
package/index.js CHANGED
@@ -1 +1,8 @@
1
- module.exports = require('./src/RuleTemplater')
1
+ const RuleTemplate = require('./src/RuleTemplater');
2
+ const GeneralTemplate = require('./src/GeneralTemplate');
3
+
4
+ module.exports.RuleTemplate = RuleTemplate;
5
+ module.exports.ParserRules = RuleTemplate.ParserRules;
6
+ module.exports.VariableTypes = RuleTemplate.VariableTypes;
7
+ module.exports.TemplateFilters = RuleTemplate.TemplateFilters;
8
+ module.exports.GeneralTemplate = GeneralTemplate;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@halleyassist/rule-templater",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "The grammar for HalleyAssist rules",
5
5
  "main": "src/RuleTemplater.production.js",
6
6
  "browser": "./dist/rule-templater.browser.js",
@@ -0,0 +1,125 @@
1
+ const TemplateFilters = require('./TemplateFilters');
2
+
3
+ class GeneralTemplate {
4
+ constructor(templateText) {
5
+ this.templateText = templateText;
6
+ }
7
+
8
+ static parse(templateText) {
9
+ return new GeneralTemplate(templateText);
10
+ }
11
+
12
+ static getVariables(templateText) {
13
+ return GeneralTemplate.parse(templateText).getVariables();
14
+ }
15
+
16
+ getVariables() {
17
+ const variables = [];
18
+ const variableMap = new Map();
19
+ const pattern = /\$\{([^}]*)\}/g;
20
+
21
+ for (const match of this.templateText.matchAll(pattern)) {
22
+ const parsedExpression = this._parseTemplateExpression(match[1]);
23
+ if (parsedExpression) {
24
+ if (variableMap.has(parsedExpression.name)) {
25
+ const existing = variableMap.get(parsedExpression.name);
26
+ existing.positions.push({
27
+ start: match.index,
28
+ end: match.index + match[0].length
29
+ });
30
+ existing.filters = Array.from(new Set(existing.filters.concat(parsedExpression.filters)));
31
+ } else {
32
+ variableMap.set(parsedExpression.name, {
33
+ name: parsedExpression.name,
34
+ filters: parsedExpression.filters,
35
+ positions: [{
36
+ start: match.index,
37
+ end: match.index + match[0].length
38
+ }]
39
+ });
40
+ }
41
+ }
42
+ }
43
+
44
+ for (const variable of variableMap.values()) {
45
+ variables.push(variable);
46
+ }
47
+
48
+ return variables;
49
+ }
50
+
51
+ extractVariables() {
52
+ return this.getVariables();
53
+ }
54
+
55
+ prepare(variables) {
56
+ if (!variables || typeof variables !== 'object') {
57
+ throw new Error('Variables must be provided as an object');
58
+ }
59
+
60
+ return this.templateText.replace(/\$\{([^}]*)\}/g, (matchText, expression) => {
61
+ const parsedExpression = this._parseTemplateExpression(expression);
62
+ if (!parsedExpression) {
63
+ return matchText;
64
+ }
65
+
66
+ const varName = parsedExpression.name;
67
+ if (!Object.prototype.hasOwnProperty.call(variables, varName)) {
68
+ throw new Error(`Variable '${varName}' not provided in variables object`);
69
+ }
70
+
71
+ let varData = variables[varName];
72
+ if (typeof varData !== 'object' || !Object.prototype.hasOwnProperty.call(varData, 'value')) {
73
+ throw new Error(`Variable '${varName}' must be an object with 'value' property`);
74
+ }
75
+
76
+ varData = Object.assign({}, varData);
77
+
78
+ if (parsedExpression.filters && parsedExpression.filters.length > 0) {
79
+ for (const filterName of parsedExpression.filters) {
80
+ if (!TemplateFilters[filterName]) {
81
+ throw new Error(`Unknown filter '${filterName}'`);
82
+ }
83
+
84
+ TemplateFilters[filterName](varData);
85
+ }
86
+ }
87
+
88
+ return this._serializeVariable(varData);
89
+ });
90
+ }
91
+
92
+ _parseTemplateExpression(expression) {
93
+ if (!expression) {
94
+ return null;
95
+ }
96
+
97
+ const segments = expression.split('|').map(s => s.trim()).filter(Boolean);
98
+ if (segments.length === 0) {
99
+ return null;
100
+ }
101
+
102
+ return {
103
+ name: segments[0],
104
+ filters: segments.slice(1)
105
+ };
106
+ }
107
+
108
+ _serializeVariable(varData) {
109
+ if (varData.value === null || varData.value === undefined) {
110
+ return '';
111
+ }
112
+
113
+ if (varData.type === 'time period' || varData.type === 'time period ago') {
114
+ let ret = `${varData.value.from} TO ${varData.value.to}`;
115
+ if (varData.value.ago) {
116
+ ret += ` AGO ${varData.value.ago[0]} ${varData.value.ago[1]}`;
117
+ }
118
+ return ret;
119
+ }
120
+
121
+ return String(varData.value);
122
+ }
123
+ }
124
+
125
+ module.exports = GeneralTemplate;
@@ -418,8 +418,8 @@ class RuleTemplate {
418
418
  }
419
419
  }
420
420
 
421
- // Export the class and parser rules
421
+ RuleTemplate.ParserRules = ParserRules;
422
+ RuleTemplate.VariableTypes = VariableTypes;
423
+ RuleTemplate.TemplateFilters = TemplateFilters;
424
+
422
425
  module.exports = RuleTemplate;
423
- module.exports.ParserRules = ParserRules;
424
- module.exports.VariableTypes = VariableTypes;
425
- module.exports.TemplateFilters = TemplateFilters;
@@ -418,8 +418,8 @@ class RuleTemplate {
418
418
  }
419
419
  }
420
420
 
421
- // Export the class and parser rules
421
+ RuleTemplate.ParserRules = ParserRules;
422
+ RuleTemplate.VariableTypes = VariableTypes;
423
+ RuleTemplate.TemplateFilters = TemplateFilters;
424
+
422
425
  module.exports = RuleTemplate;
423
- module.exports.ParserRules = ParserRules;
424
- module.exports.VariableTypes = VariableTypes;
425
- module.exports.TemplateFilters = TemplateFilters;