@itrocks/list 0.21.0 → 0.22.0

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
@@ -155,12 +155,35 @@ Any later hyphens in an interval remain part of the upper bound.
155
155
  The original text stays in the input and session; feed requests reconstruct the same criterion from session state.
156
156
  The data source converts the bounds according to the property's type.
157
157
 
158
+ ### Logical expressions
159
+
160
+ Each column accepts several criteria separated by `,` or `|` for `OR`, and `&` or `+` for `AND`.
161
+ `AND` takes precedence over `OR`; parentheses override this order and can nest.
162
+ Every leaf retains the comparison, interval, date and wildcard rules above.
163
+
164
+ - `Alice, Bob` searches either text prefix.
165
+ - `>=2000 & <2010 | =1984` means `(>=2000 AND <2010) OR =1984`.
166
+ - `(Alice | Bob) & !*test*` requires either prefix and excludes the `test` pattern.
167
+ - `2020 | (2021-2022 & !06/2021)` combines date periods and exclusions.
168
+
169
+ Double quotes or a backslash protect logical separators and parentheses: `"Rock & Roll"`, `Paris\, Texas`
170
+ and `"Alien (Director's Cut)"` are single criteria. `\"` protects a double quote and `\\` protects a backslash.
171
+ Apostrophes remain ordinary characters. Quoting protects the expression grammar; use `=` for exact comparison,
172
+ for example `="Paris, Texas"`. Spaces around operators and parentheses are ignored; spaces within a criterion remain.
173
+ When constructing query URLs manually, encode the plus operator as `%2B` because an unencoded `+` means a space.
174
+
175
+ A missing criterion, unmatched parenthesis or unclosed quote matches no rows. The complete original input remains
176
+ in the field and session, including invalid expressions; subsequent feed requests rebuild the same query.
177
+
158
178
  ### Object filters
159
179
 
160
180
  A filter on an object column searches every `representativeOf()` property of its target type with `OR`.
161
181
  This applies to singular objects and collections. For example, `Movie.genres` with `Genre` represented by `name`
162
182
  searches `genres.name`. Text representatives use the same prefix, comparison, interval and wildcard rules as direct
163
183
  text columns. Nested object representatives are expanded recursively; cyclic representations reject.
184
+ An expression applies each leaf to the target's representatives, then combines those searches with its operators.
185
+ For example, `Comédie & Drame` on `Movie.genres` requires both genres, which may be different collection elements.
186
+ `(Comédie | Drame) & Action` requires Action and at least one of the first two genres.
164
187
  Separate column filters remain combined with `AND`. Original input is retained in session.
165
188
  Logical criteria retain mandatory application scopes and authorisation checks on every expanded property path.
166
189
 
package/cjs/filter.js CHANGED
@@ -14,18 +14,54 @@ const sql_functions_8 = require("@itrocks/sql-functions");
14
14
  const sql_functions_9 = require("@itrocks/sql-functions");
15
15
  const sql_functions_10 = require("@itrocks/sql-functions");
16
16
  const sql_functions_11 = require("@itrocks/sql-functions");
17
+ const sql_functions_12 = require("@itrocks/sql-functions");
18
+ const sql_functions_13 = require("@itrocks/sql-functions");
17
19
  const date_search_1 = require("./date-search");
18
20
  const parameter_1 = require("./parameter");
21
+ const search_expression_1 = require("./search-expression");
19
22
  const operators = {
20
- '!': sql_functions_10.notEqual,
21
- '!=': sql_functions_10.notEqual,
22
- '<': sql_functions_7.less,
23
- '<=': sql_functions_8.lessOrEqual,
24
- '<>': sql_functions_10.notEqual,
25
- '=': sql_functions_4.equal,
26
- '>': sql_functions_5.greater,
27
- '>=': sql_functions_6.greaterOrEqual
23
+ '!': sql_functions_11.notEqual,
24
+ '!=': sql_functions_11.notEqual,
25
+ '<': sql_functions_8.less,
26
+ '<=': sql_functions_9.lessOrEqual,
27
+ '<>': sql_functions_11.notEqual,
28
+ '=': sql_functions_5.equal,
29
+ '>': sql_functions_6.greater,
30
+ '>=': sql_functions_7.greaterOrEqual
28
31
  };
32
+ function searchValue(propertyType, expression) {
33
+ if (!('value' in expression)) {
34
+ const combine = (expression.operator === 'AND') ? sql_functions_3.and : sql_functions_13.or;
35
+ return combine(...expression.operands.map(operand => searchValue(propertyType, operand) ?? (0, sql_functions_13.or)()));
36
+ }
37
+ const value = expression.value;
38
+ const comparison = value.match(/^(>=|<=|<>|!=|>|<|=|!)(.*)$/s);
39
+ const operator = comparison ? operators[comparison[1]] : undefined;
40
+ const operand = comparison ? comparison[2].trim() : value;
41
+ if (propertyType === Date) {
42
+ return (0, date_search_1.dateSearch)(operand, comparison?.[1]);
43
+ }
44
+ if (/[*?]/.test(operand) && (!operator || operator === sql_functions_11.notEqual)) {
45
+ const compare = operator ? sql_functions_12.notLike : sql_functions_10.like;
46
+ return compare(operand.replaceAll('*', '%').replaceAll('?', '_'));
47
+ }
48
+ if (operator) {
49
+ return operator(operand);
50
+ }
51
+ const separator = value.indexOf('-');
52
+ if (separator < 0) {
53
+ const text = (propertyType === String);
54
+ return (text ? (0, sql_functions_10.like)(value + '%') : value);
55
+ }
56
+ const lower = value.slice(0, separator).trim();
57
+ const upper = value.slice(separator + 1).trim();
58
+ if (lower && upper)
59
+ return (0, sql_functions_4.between)(lower, upper);
60
+ if (lower)
61
+ return (0, sql_functions_7.greaterOrEqual)(lower);
62
+ if (upper)
63
+ return (0, sql_functions_9.lessOrEqual)(upper);
64
+ }
29
65
  class Filter extends parameter_1.Parameter {
30
66
  columns;
31
67
  search = {};
@@ -68,62 +104,47 @@ class Filter extends parameter_1.Parameter {
68
104
  searchObject(type) {
69
105
  const search = {};
70
106
  const groups = [];
71
- const expand = (property, value, ancestors = []) => {
107
+ const expand = (property, expression, ancestors = []) => {
72
108
  const resolved = (0, reflect_path_1.resolvePropertyPath)(type, property);
73
109
  if (!resolved.target) {
74
- const filter = new Filter(this.columns);
75
- filter.search = { [property]: value };
76
- return filter.searchObject(type);
110
+ const value = searchValue(resolved.property.type.type, expression);
111
+ return { [property]: value ?? (0, sql_functions_13.or)() };
112
+ }
113
+ if (!('value' in expression)) {
114
+ const operator = (expression.operator === 'AND') ? sql_functions_1.AND : sql_functions_2.OR;
115
+ return { [operator]: expression.operands.map(operand => expand(property, operand, ancestors)) };
77
116
  }
78
117
  if (ancestors.includes(resolved.target))
79
118
  throw new Error(`Cyclic search representation: ${property}`);
80
119
  const branch = [...ancestors, resolved.target];
81
120
  return {
82
- [sql_functions_2.OR]: (0, class_view_1.representativeOf)(resolved.target).map(name => expand(`${property}.${String(name)}`, value, branch))
121
+ [sql_functions_2.OR]: (0, class_view_1.representativeOf)(resolved.target).map(name => expand(`${property}.${String(name)}`, expression, branch))
83
122
  };
84
123
  };
85
124
  for (const [property, value] of Object.entries(this.search)) {
86
125
  if (value === '')
87
126
  continue;
88
- if ((0, reflect_path_1.resolvePropertyPath)(type, property).target) {
89
- groups.push(expand(property, value));
90
- continue;
127
+ let expression;
128
+ try {
129
+ expression = (0, search_expression_1.searchExpression)(value);
91
130
  }
92
- const comparison = value.match(/^(>=|<=|<>|!=|>|<|=|!)(.*)$/s);
93
- const operator = comparison ? operators[comparison[1]] : undefined;
94
- const operand = comparison ? comparison[2].trim() : value;
95
- const propertyType = (0, reflect_path_1.resolvePropertyPath)(type, property).property.type.type;
96
- if (propertyType === Date) {
97
- search[property] = (0, date_search_1.dateSearch)(operand, comparison?.[1]);
131
+ catch (error) {
132
+ if (!(error instanceof SyntaxError))
133
+ throw error;
134
+ search[property] = (0, sql_functions_13.or)();
98
135
  continue;
99
136
  }
100
- if (/[*?]/.test(operand) && (!operator || operator === sql_functions_10.notEqual)) {
101
- const compare = operator ? sql_functions_11.notLike : sql_functions_9.like;
102
- search[property] = compare(operand.replaceAll('*', '%').replaceAll('?', '_'));
103
- continue;
104
- }
105
- if (operator) {
106
- search[property] = operator(operand);
107
- continue;
108
- }
109
- const separator = value.indexOf('-');
110
- if (separator < 0) {
111
- const text = propertyType === String;
112
- search[property] = (text ? (0, sql_functions_9.like)(value + '%') : value);
113
- continue;
137
+ const resolved = (0, reflect_path_1.resolvePropertyPath)(type, property);
138
+ if (resolved.target)
139
+ groups.push(expand(property, expression));
140
+ else {
141
+ const criterion = searchValue(resolved.property.type.type, expression);
142
+ if (criterion !== undefined)
143
+ search[property] = criterion;
114
144
  }
115
- const lower = value.slice(0, separator).trim();
116
- const upper = value.slice(separator + 1).trim();
117
- if (lower && upper)
118
- search[property] = (0, sql_functions_3.between)(lower, upper);
119
- else if (lower)
120
- search[property] = (0, sql_functions_6.greaterOrEqual)(lower);
121
- else if (upper)
122
- search[property] = (0, sql_functions_8.lessOrEqual)(upper);
123
145
  }
124
- if (groups.length) {
146
+ if (groups.length)
125
147
  search[sql_functions_1.AND] = groups;
126
- }
127
148
  return Object.setPrototypeOf(search, type.prototype);
128
149
  }
129
150
  serialize() {
package/cjs/filter.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"filter.js","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"filter.js","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":";;;AACA,oDAAyD;AACzD,wDAA2D;AAE3D,0DAA4D;AAC5D,0DAA4D;AAC5D,0DAA4D;AAC5D,0DAA4D;AAC5D,0DAA4D;AAC5D,0DAA4D;AAC5D,0DAA4D;AAC5D,0DAA4D;AAC5D,0DAA4D;AAC5D,2DAA4D;AAC5D,2DAA4D;AAC5D,2DAA4D;AAC5D,2DAA4D;AAI5D,+CAAmD;AACnD,2CAAiD;AAEjD,2DAAyD;AAIzD,MAAM,SAAS,GAAG;IACjB,GAAG,EAAG,yBAAQ;IACd,IAAI,EAAE,yBAAQ;IACd,GAAG,EAAG,oBAAI;IACV,IAAI,EAAE,2BAAW;IACjB,IAAI,EAAE,yBAAQ;IACd,GAAG,EAAG,qBAAK;IACX,GAAG,EAAG,uBAAO;IACb,IAAI,EAAE,8BAAc;CACpB,CAAA;AAED,SAAS,WAAW,CAAC,YAAqB,EAAE,UAA4B;IAEvE,IAAI,CAAC,CAAC,OAAO,IAAI,UAAU,CAAC,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,CAAC,UAAU,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,mBAAG,CAAC,CAAC,CAAC,mBAAE,CAAA;QAC1D,OAAO,OAAO,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,IAAA,mBAAE,GAAE,CAAC,CAAC,CAAA;IAClG,CAAC;IACD,MAAM,KAAK,GAAQ,UAAU,CAAC,KAAK,CAAA;IACnC,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAA;IAC9D,MAAM,QAAQ,GAAK,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAA2B,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAC9F,MAAM,OAAO,GAAM,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAA;IAC5D,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,IAAA,wBAAU,EAAC,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IAC5C,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,IAAI,QAAQ,KAAK,yBAAQ,CAAC,EAAE,CAAC;QAClE,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,wBAAO,CAAC,CAAC,CAAC,qBAAI,CAAA;QACzC,OAAO,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;IAClE,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACd,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAA;IACzB,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACpC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QACnB,MAAM,IAAI,GAAG,CAAC,YAAY,KAAK,MAAM,CAAC,CAAA;QACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAA,qBAAI,EAAC,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IAC1C,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,IAAI,EAAE,CAAA;IAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAC/C,IAAI,KAAK,IAAI,KAAK;QAAE,OAAO,IAAA,uBAAO,EAAC,KAAK,EAAE,KAAK,CAAC,CAAA;IAChD,IAAI,KAAK;QAAW,OAAO,IAAA,8BAAc,EAAC,KAAK,CAAC,CAAA;IAChD,IAAI,KAAK;QAAW,OAAO,IAAA,2BAAW,EAAC,KAAK,CAAC,CAAA;AAC9C,CAAC;AAED,MAAa,MAAyB,SAAQ,qBAAS;IAKnC;IAFnB,MAAM,GAAW,EAAE,CAAA;IAEnB,YAAmB,OAAmB;QAErC,KAAK,EAAE,CAAA;QAFW,YAAO,GAAP,OAAO,CAAY;IAGtC,CAAC;IAED,SAAS,CAAC,OAAgB;QAEzB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACpE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAA;QAC7B,CAAC;QACD,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI;YAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAA;QAC/G,MAAM,KAAK,GAAG,CAAC,KAAc,EAAE,MAAM,GAAG,EAAE,EAAE,EAAE;YAC7C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBAAE,OAAM;YACvE,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACnD,IAAI,OAAe,CAAA;gBACnB,IAAI,CAAC;oBAAC,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAA;gBAAC,CAAC;gBAC1C,MAAM,CAAC;oBAAC,SAAQ;gBAAC,CAAC;gBAClB,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAA;gBACtD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;oBAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAA;;oBACvF,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;YACxB,CAAC;QACF,CAAC,CAAA;QACD,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC1B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;YACvD,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;IAChG,CAAC;IAED,WAAW,CAAC,UAAU,IAAI,KAAa;QAEtC,OAAO,OAAO,CAAA;IACf,CAAC;IAED,YAAY,CAAC,IAAU;QAEtB,MAAM,MAAM,GAAiB,EAAE,CAAA;QAC/B,MAAM,MAAM,GAAiB,EAAE,CAAA;QAC/B,MAAM,MAAM,GAAG,CAAC,QAAgB,EAAE,UAA4B,EAAE,YAA6B,EAAE,EAAc,EAAE;YAC9G,MAAM,QAAQ,GAAG,IAAA,kCAAmB,EAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;YACpD,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACtB,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;gBAClE,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,IAAI,IAAA,mBAAE,GAAE,EAAE,CAAA;YACrC,CAAC;YACD,IAAI,CAAC,CAAC,OAAO,IAAI,UAAU,CAAC,EAAE,CAAC;gBAC9B,MAAM,QAAQ,GAAG,CAAC,UAAU,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,mBAAG,CAAC,CAAC,CAAC,kBAAE,CAAA;gBAC3D,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,EAAE,CAAA;YAChG,CAAC;YACD,IAAI,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,EAAE,CAAC,CAAA;YACrG,MAAM,MAAM,GAAG,CAAC,GAAG,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;YAC9C,OAAO;gBACN,CAAC,kBAAE,CAAC,EAAE,IAAA,6BAAgB,EAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;aAC9G,CAAA;QACF,CAAC,CAAA;QACD,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7D,IAAI,KAAK,KAAK,EAAE;gBAAE,SAAQ;YAC1B,IAAI,UAA4B,CAAA;YAChC,IAAI,CAAC;gBAAC,UAAU,GAAG,IAAA,oCAAgB,EAAC,KAAK,CAAC,CAAA;YAAC,CAAC;YAC5C,OAAO,KAAK,EAAE,CAAC;gBACd,IAAI,CAAC,CAAC,KAAK,YAAY,WAAW,CAAC;oBAAE,MAAM,KAAK,CAAA;gBAChD,MAAM,CAAC,QAAQ,CAAC,GAAG,IAAA,mBAAE,GAAE,CAAA;gBACvB,SAAQ;YACT,CAAC;YACD,MAAM,QAAQ,GAAG,IAAA,kCAAmB,EAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;YACpD,IAAI,QAAQ,CAAC,MAAM;gBAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAA;iBACzD,CAAC;gBACL,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;gBACtE,IAAI,SAAS,KAAK,SAAS;oBAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAA;YAC1D,CAAC;QACF,CAAC;QACD,IAAI,MAAM,CAAC,MAAM;YAAE,MAAM,CAAC,mBAAG,CAAC,GAAG,MAAM,CAAA;QACvC,OAAO,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;IACrD,CAAC;IAED,SAAS;QAER,OAAO,IAAI,CAAC,MAAM,CAAA;IACnB,CAAC;IAED,WAAW,CAAC,IAAY;QAEvB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;IACnB,CAAC;CAED;AAvFD,wBAuFC"}
@@ -0,0 +1,7 @@
1
+ export type SearchExpression = {
2
+ value: string;
3
+ } | {
4
+ operator: 'AND' | 'OR';
5
+ operands: SearchExpression[];
6
+ };
7
+ export declare function searchExpression(input: string): SearchExpression;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.searchExpression = searchExpression;
4
+ function searchExpression(input) {
5
+ // Preserve ordinary input exactly, including spaces used by existing scalar criteria.
6
+ if (!/[,|&+()"\\]/.test(input))
7
+ return { value: input };
8
+ return new SearchParser(input).parse();
9
+ }
10
+ class SearchParser {
11
+ input;
12
+ position = 0;
13
+ constructor(input) {
14
+ this.input = input;
15
+ }
16
+ and() {
17
+ const operands = [this.primary()];
18
+ while (this.take('&+'))
19
+ operands.push(this.primary());
20
+ return (operands.length === 1) ? operands[0] : { operator: 'AND', operands };
21
+ }
22
+ fail(message) {
23
+ throw new SyntaxError(`${message} at position ${this.position + 1}`);
24
+ }
25
+ or() {
26
+ const operands = [this.and()];
27
+ while (this.take(',|'))
28
+ operands.push(this.and());
29
+ return (operands.length === 1) ? operands[0] : { operator: 'OR', operands };
30
+ }
31
+ parse() {
32
+ const expression = this.or();
33
+ this.space();
34
+ if (this.position !== this.input.length)
35
+ this.fail('Unexpected character');
36
+ return expression;
37
+ }
38
+ primary() {
39
+ if (this.take('(')) {
40
+ const expression = this.or();
41
+ if (!this.take(')')) {
42
+ this.fail('Missing closing parenthesis');
43
+ }
44
+ return expression;
45
+ }
46
+ let value = '';
47
+ let length = 0;
48
+ let quoted = false;
49
+ let seen = false;
50
+ while (this.position < this.input.length) {
51
+ const character = this.input[this.position];
52
+ if (!quoted && ',|&+()'.includes(character))
53
+ break;
54
+ this.position++;
55
+ if ((character === '\\')
56
+ && (this.position < this.input.length)
57
+ && ',|&+()"\\'.includes(this.input[this.position])) {
58
+ value += this.input[this.position++];
59
+ length = value.length;
60
+ seen = true;
61
+ }
62
+ else if (character === '"') {
63
+ quoted = !quoted;
64
+ seen = true;
65
+ }
66
+ else {
67
+ value += character;
68
+ if (quoted || character.trim())
69
+ length = value.length;
70
+ seen ||= !!character.trim();
71
+ }
72
+ }
73
+ if (quoted)
74
+ this.fail('Unclosed quote');
75
+ if (!seen)
76
+ this.fail('Missing criterion');
77
+ return { value: value.slice(0, length) };
78
+ }
79
+ space() {
80
+ while ((this.position < this.input.length) && /\s/.test(this.input[this.position])) {
81
+ this.position++;
82
+ }
83
+ }
84
+ take(characters) {
85
+ this.space();
86
+ if ((this.position === this.input.length) || !characters.includes(this.input[this.position])) {
87
+ return false;
88
+ }
89
+ this.position++;
90
+ return true;
91
+ }
92
+ }
93
+ //# sourceMappingURL=search-expression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-expression.js","sourceRoot":"","sources":["../src/search-expression.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -94,5 +94,5 @@
94
94
  "build:front": "tsc -p src/front/tsconfig.json",
95
95
  "test": "npm run build:cjs && node --test \"test/**/*.test.mjs\""
96
96
  },
97
- "version": "0.21.0"
97
+ "version": "0.22.0"
98
98
  }