@nymphjs/query-parser 1.0.0-beta.122 → 1.0.0-beta.124
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/CHANGELOG.md +12 -0
- package/README.md +48 -46
- package/dist/queryParser.js +285 -120
- package/dist/queryParser.js.map +1 -1
- package/dist/queryParser.test.js +511 -29
- package/dist/queryParser.test.js.map +1 -1
- package/package.json +3 -3
- package/src/queryParser.test.ts +578 -29
- package/src/queryParser.ts +300 -120
package/dist/queryParser.js
CHANGED
|
@@ -116,13 +116,13 @@ function selectorsParser({ query, entityClass, type, defaultFields, qrefMap, opt
|
|
|
116
116
|
bareHandler,
|
|
117
117
|
});
|
|
118
118
|
if (options) {
|
|
119
|
-
const limitRegex = /(
|
|
119
|
+
const limitRegex = /(?:\s|^)limit:(\d+)(?=\s|$)/;
|
|
120
120
|
const limitMatch = curQuery.match(limitRegex);
|
|
121
121
|
if (limitMatch) {
|
|
122
122
|
options.limit = Number(limitMatch[1]);
|
|
123
123
|
}
|
|
124
124
|
curQuery = curQuery.replace(limitRegex, '');
|
|
125
|
-
const offsetRegex = /(
|
|
125
|
+
const offsetRegex = /(?:\s|^)offset:(\d+)(?=\s|$)/;
|
|
126
126
|
const offsetMatch = curQuery.match(offsetRegex);
|
|
127
127
|
if (offsetMatch) {
|
|
128
128
|
options.offset = Number(offsetMatch[1]);
|
|
@@ -130,13 +130,13 @@ function selectorsParser({ query, entityClass, type, defaultFields, qrefMap, opt
|
|
|
130
130
|
curQuery = curQuery.replace(offsetRegex, '');
|
|
131
131
|
// JavaScript variable names are ridiculously infeasable to check
|
|
132
132
|
// thoroughly, so this is a "best attempt".
|
|
133
|
-
const sortRegex = /(
|
|
133
|
+
const sortRegex = /(?:\s|^)sort:(-|[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)(?=\s|$)/;
|
|
134
134
|
const sortMatch = curQuery.match(sortRegex);
|
|
135
135
|
if (sortMatch) {
|
|
136
136
|
options.sort = sortMatch[1] === '-' ? null : sortMatch[1];
|
|
137
137
|
}
|
|
138
138
|
curQuery = curQuery.replace(sortRegex, '');
|
|
139
|
-
const reverseRegex = /(
|
|
139
|
+
const reverseRegex = /(?:\s|^)reverse:(true|false|1|0)(?=\s|$)/;
|
|
140
140
|
const reverseMatch = curQuery.match(reverseRegex);
|
|
141
141
|
if (reverseMatch) {
|
|
142
142
|
options.reverse = reverseMatch[1] === 'true' || reverseMatch[1] === '1';
|
|
@@ -168,8 +168,86 @@ function selectorsParser({ query, entityClass, type, defaultFields, qrefMap, opt
|
|
|
168
168
|
}
|
|
169
169
|
function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
170
170
|
let curQuery = query;
|
|
171
|
-
//
|
|
172
|
-
|
|
171
|
+
// This one needs to happen first, because it has entire queries in it.
|
|
172
|
+
// eg. user<{User name="Hunter"}> or -user<{User name="Hunter"}>
|
|
173
|
+
const qrefRegex = /(?:\s|^)-?([^-\s=\[\]<>{}()][^\s=\[\]<>{}()]*?)<\{(\w+)(?=\s)/;
|
|
174
|
+
// This is used to bypass badly formatted things that match the above regex.
|
|
175
|
+
let offsetIndex = 0;
|
|
176
|
+
let qrefMatch = curQuery.match(qrefRegex);
|
|
177
|
+
while (qrefMatch) {
|
|
178
|
+
let endIndex = (qrefMatch.index ?? 0) + offsetIndex + qrefMatch[0].length;
|
|
179
|
+
let curOpen = 1;
|
|
180
|
+
while (curOpen) {
|
|
181
|
+
const indexOfNextOpen = curQuery.indexOf('<{', endIndex);
|
|
182
|
+
const indexOfNextClose = curQuery.slice(endIndex).search(/(?<!\\)\}>/);
|
|
183
|
+
if (indexOfNextClose < 0) {
|
|
184
|
+
endIndex = curQuery.length;
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
if (indexOfNextOpen > -1 &&
|
|
188
|
+
indexOfNextOpen < endIndex + indexOfNextClose) {
|
|
189
|
+
endIndex = indexOfNextOpen + 2;
|
|
190
|
+
curOpen++;
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
endIndex += indexOfNextClose + 2;
|
|
194
|
+
curOpen--;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (!('qref' in selector)) {
|
|
198
|
+
selector.qref = [];
|
|
199
|
+
}
|
|
200
|
+
if (!('!qref' in selector)) {
|
|
201
|
+
selector['!qref'] = [];
|
|
202
|
+
}
|
|
203
|
+
const match = curQuery.slice((qrefMatch.index ?? 0) + offsetIndex, endIndex);
|
|
204
|
+
try {
|
|
205
|
+
let [name, value] = splitn(match.trim().slice(0, -1), '<', 2);
|
|
206
|
+
value = unQuoteCurlies(value.slice(1, -1));
|
|
207
|
+
let [className, qrefQuery] = splitn(value, ' ', 2);
|
|
208
|
+
const EntityClass = qrefMap[className].class;
|
|
209
|
+
if (EntityClass == null) {
|
|
210
|
+
throw new Error();
|
|
211
|
+
}
|
|
212
|
+
const qref = queryParser({
|
|
213
|
+
query: qrefQuery,
|
|
214
|
+
entityClass: EntityClass,
|
|
215
|
+
defaultFields: qrefMap[className].defaultFields,
|
|
216
|
+
qrefMap,
|
|
217
|
+
bareHandler,
|
|
218
|
+
});
|
|
219
|
+
if (name.startsWith('-')) {
|
|
220
|
+
selector['!qref'].push([name.slice(1), qref]);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
selector.qref.push([name, qref]);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
catch (e) {
|
|
227
|
+
offsetIndex = endIndex;
|
|
228
|
+
qrefMatch = curQuery.slice(offsetIndex).match(qrefRegex);
|
|
229
|
+
if (!selector.qref?.length) {
|
|
230
|
+
delete selector.qref;
|
|
231
|
+
}
|
|
232
|
+
if (!selector['!qref']?.length) {
|
|
233
|
+
delete selector['!qref'];
|
|
234
|
+
}
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (!selector.qref?.length) {
|
|
238
|
+
delete selector.qref;
|
|
239
|
+
}
|
|
240
|
+
if (!selector['!qref']?.length) {
|
|
241
|
+
delete selector['!qref'];
|
|
242
|
+
}
|
|
243
|
+
curQuery =
|
|
244
|
+
curQuery.slice(0, (qrefMatch.index ?? 0) + offsetIndex) +
|
|
245
|
+
' ' +
|
|
246
|
+
curQuery.slice(endIndex);
|
|
247
|
+
qrefMatch = curQuery.slice(offsetIndex).match(qrefRegex);
|
|
248
|
+
}
|
|
249
|
+
// eg. prop(some search string) or -prop(some search string)
|
|
250
|
+
const searchRegex = /(?:\s|^)-?([^-\s=\[\]<>{}()][^\s=\[\]<>{}()]*?)\([^\)]+\)(?=\s|\)|\}>|$)/g;
|
|
173
251
|
const searchMatch = curQuery.match(searchRegex);
|
|
174
252
|
if (searchMatch) {
|
|
175
253
|
selector.search = [];
|
|
@@ -177,8 +255,8 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
177
255
|
for (let match of searchMatch) {
|
|
178
256
|
try {
|
|
179
257
|
let [name, value] = splitn(match.trim().slice(0, -1), '(', 2);
|
|
180
|
-
if (name.
|
|
181
|
-
selector['!search'].push([name.slice(
|
|
258
|
+
if (name.startsWith('-')) {
|
|
259
|
+
selector['!search'].push([name.slice(1), value]);
|
|
182
260
|
}
|
|
183
261
|
else {
|
|
184
262
|
selector.search.push([name, value]);
|
|
@@ -196,49 +274,43 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
196
274
|
}
|
|
197
275
|
}
|
|
198
276
|
curQuery = curQuery.replace(searchRegex, '');
|
|
199
|
-
// eg.
|
|
200
|
-
const
|
|
201
|
-
const
|
|
202
|
-
if (
|
|
203
|
-
selector
|
|
204
|
-
|
|
205
|
-
|
|
277
|
+
// eg. name:Marty or name:"Marty McFly" or -name:'Marty McFly'
|
|
278
|
+
const searchColonRegex = /(?:\s|^)(?!(limit|offset|sort|reverse):)-?([^-\s=\[\]<>{}()][^\s=\[\]<>{}()]*?):("[^"]*?"|'[^']*?'|[^\s]+)(?=\s|\)|\}>|$)/g;
|
|
279
|
+
const searchColonMatch = curQuery.match(searchColonRegex);
|
|
280
|
+
if (searchColonMatch) {
|
|
281
|
+
if (!('search' in selector)) {
|
|
282
|
+
selector.search = [];
|
|
283
|
+
}
|
|
284
|
+
if (!('!search' in selector)) {
|
|
285
|
+
selector['!search'] = [];
|
|
286
|
+
}
|
|
287
|
+
for (let match of searchColonMatch) {
|
|
206
288
|
try {
|
|
207
|
-
let [name, value] = splitn(match.trim()
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
const qref = queryParser({
|
|
215
|
-
query: qrefQuery,
|
|
216
|
-
entityClass: EntityClass,
|
|
217
|
-
defaultFields: qrefMap[className].defaultFields,
|
|
218
|
-
qrefMap,
|
|
219
|
-
bareHandler,
|
|
220
|
-
});
|
|
221
|
-
if (name.endsWith('!')) {
|
|
222
|
-
selector['!qref'].push([name.slice(0, -1), qref]);
|
|
289
|
+
let [name, value] = splitn(match.trim(), ':', 2);
|
|
290
|
+
if (name.startsWith('-')) {
|
|
291
|
+
selector['!search'].push([
|
|
292
|
+
name.slice(1),
|
|
293
|
+
value,
|
|
294
|
+
]);
|
|
223
295
|
}
|
|
224
296
|
else {
|
|
225
|
-
selector.
|
|
297
|
+
selector.search.push([name, value]);
|
|
226
298
|
}
|
|
227
299
|
}
|
|
228
300
|
catch (e) {
|
|
229
301
|
continue;
|
|
230
302
|
}
|
|
231
303
|
}
|
|
232
|
-
if (!selector.
|
|
233
|
-
delete selector.
|
|
304
|
+
if (selector.search == null || !selector.search.length) {
|
|
305
|
+
delete selector.search;
|
|
234
306
|
}
|
|
235
|
-
if (!selector['!
|
|
236
|
-
delete selector['!
|
|
307
|
+
if (selector['!search'] == null || !selector['!search'].length) {
|
|
308
|
+
delete selector['!search'];
|
|
237
309
|
}
|
|
238
310
|
}
|
|
239
|
-
curQuery = curQuery.replace(
|
|
311
|
+
curQuery = curQuery.replace(searchColonRegex, '');
|
|
240
312
|
// eg. someArray=[1,2] or someObject={"prop":"some value"}
|
|
241
|
-
const equalJsonRegex = /(
|
|
313
|
+
const equalJsonRegex = /(?:\s|^)-?([^-\s=\[\]<>{}()][^\s=\[\]<>{}()]*?)=(\{|\[)/g;
|
|
242
314
|
const equalJsonMatch = [...curQuery.matchAll(equalJsonRegex)];
|
|
243
315
|
if (equalJsonMatch) {
|
|
244
316
|
if (!('equal' in selector)) {
|
|
@@ -255,9 +327,9 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
255
327
|
let nextEndToken = curQuery.indexOf(opener === '{' ? '}' : ']', start);
|
|
256
328
|
while (nextEndToken !== -1) {
|
|
257
329
|
try {
|
|
258
|
-
if (name.
|
|
330
|
+
if (name.startsWith('-')) {
|
|
259
331
|
selector['!equal'].unshift([
|
|
260
|
-
name.slice(
|
|
332
|
+
name.slice(1),
|
|
261
333
|
JSON.parse(curQuery.substring(start, nextEndToken + 1)),
|
|
262
334
|
]);
|
|
263
335
|
}
|
|
@@ -285,7 +357,7 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
285
357
|
}
|
|
286
358
|
}
|
|
287
359
|
// eg. name=Marty or name="Marty McFly" or enabled=true
|
|
288
|
-
const equalRegex = /(
|
|
360
|
+
const equalRegex = /(?:\s|^)-?([^-\s=\[\]<>{}()][^\s=\[\]<>{}()]*?)=(""|".*?[^\\]"|[^\s]+)(?=\s|\)|\}>|$)/g;
|
|
289
361
|
const equalMatch = curQuery.match(equalRegex);
|
|
290
362
|
if (equalMatch) {
|
|
291
363
|
if (!('equal' in selector)) {
|
|
@@ -298,9 +370,9 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
298
370
|
try {
|
|
299
371
|
let [name, value] = splitn(match.trim(), '=', 2);
|
|
300
372
|
try {
|
|
301
|
-
if (name.
|
|
373
|
+
if (name.startsWith('-')) {
|
|
302
374
|
selector['!equal'].push([
|
|
303
|
-
name.slice(
|
|
375
|
+
name.slice(1),
|
|
304
376
|
JSON.parse(value),
|
|
305
377
|
]);
|
|
306
378
|
}
|
|
@@ -309,9 +381,9 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
309
381
|
}
|
|
310
382
|
}
|
|
311
383
|
catch (e) {
|
|
312
|
-
if (name.
|
|
384
|
+
if (name.startsWith('-')) {
|
|
313
385
|
selector['!equal'].push([
|
|
314
|
-
name.slice(
|
|
386
|
+
name.slice(1),
|
|
315
387
|
unQuoteString(value),
|
|
316
388
|
]);
|
|
317
389
|
}
|
|
@@ -335,8 +407,8 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
335
407
|
}
|
|
336
408
|
}
|
|
337
409
|
curQuery = curQuery.replace(equalRegex, '');
|
|
338
|
-
// eg. user<{790274347f9b3a018c2cedee}> or user
|
|
339
|
-
const refRegex = /(
|
|
410
|
+
// eg. user<{790274347f9b3a018c2cedee}> or -user<{790274347f9b3a018c2cedee}>
|
|
411
|
+
const refRegex = /(?:\s|^)-?([^-\s=\[\]<>{}()][^\s=\[\]<>{}()]*?)<\{([0-9a-f]{24})\}>(?=\s|\)|\}>|$)/g;
|
|
340
412
|
const refMatch = curQuery.match(refRegex);
|
|
341
413
|
if (refMatch) {
|
|
342
414
|
selector.ref = [];
|
|
@@ -344,8 +416,8 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
344
416
|
for (let match of refMatch) {
|
|
345
417
|
try {
|
|
346
418
|
let [name, value] = splitn(match.trim().slice(0, -1), '<', 2);
|
|
347
|
-
if (name.
|
|
348
|
-
selector['!ref'].push([name.slice(
|
|
419
|
+
if (name.startsWith('-')) {
|
|
420
|
+
selector['!ref'].push([name.slice(1), value.slice(1, -1)]);
|
|
349
421
|
}
|
|
350
422
|
else {
|
|
351
423
|
selector.ref.push([name, value.slice(1, -1)]);
|
|
@@ -363,8 +435,8 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
363
435
|
}
|
|
364
436
|
}
|
|
365
437
|
curQuery = curQuery.replace(refRegex, '');
|
|
366
|
-
// eg. someArrayOfNumbers<10> or someObject
|
|
367
|
-
const containRegex = /(
|
|
438
|
+
// eg. someArrayOfNumbers<10> or -someObject<"some string">
|
|
439
|
+
const containRegex = /(?:\s|^)-?([^-\s=\[\]<>{}()][^\s=\[\]<>{}()]*?)(<(?:[^"][^>]*?|".*?[^\\]"))>(?=\s|\)|\}>|$)/g;
|
|
368
440
|
const containMatch = curQuery.match(containRegex);
|
|
369
441
|
if (containMatch) {
|
|
370
442
|
selector.contain = [];
|
|
@@ -373,9 +445,9 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
373
445
|
try {
|
|
374
446
|
let [name, value] = splitn(match.trim().slice(0, -1), '<', 2);
|
|
375
447
|
try {
|
|
376
|
-
if (name.
|
|
448
|
+
if (name.startsWith('-')) {
|
|
377
449
|
selector['!contain'].push([
|
|
378
|
-
name.slice(
|
|
450
|
+
name.slice(1),
|
|
379
451
|
JSON.parse(unQuoteString(value)),
|
|
380
452
|
]);
|
|
381
453
|
}
|
|
@@ -384,11 +456,8 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
384
456
|
}
|
|
385
457
|
}
|
|
386
458
|
catch (e) {
|
|
387
|
-
if (name.
|
|
388
|
-
selector['!contain'].push([
|
|
389
|
-
name.slice(0, -1),
|
|
390
|
-
unQuoteString(value),
|
|
391
|
-
]);
|
|
459
|
+
if (name.startsWith('-')) {
|
|
460
|
+
selector['!contain'].push([name.slice(1), unQuoteString(value)]);
|
|
392
461
|
}
|
|
393
462
|
else {
|
|
394
463
|
selector.contain.push([name, unQuoteString(value)]);
|
|
@@ -407,8 +476,8 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
407
476
|
}
|
|
408
477
|
}
|
|
409
478
|
curQuery = curQuery.replace(containRegex, '');
|
|
410
|
-
// eg. name~/Hunter/ or name
|
|
411
|
-
const posixRegex = /(
|
|
479
|
+
// eg. name~/Hunter/ or -name~/hunter/i
|
|
480
|
+
const posixRegex = /(?:\s|^)-?([^-\s=\[\]<>{}()][^\s=\[\]<>{}()]*?)~(\/\/|\/.*?[^\\]\/)i?(?=\s|\)|\}>|$)/g;
|
|
412
481
|
const posixMatch = curQuery.match(posixRegex);
|
|
413
482
|
if (posixMatch) {
|
|
414
483
|
selector.match = [];
|
|
@@ -418,16 +487,16 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
418
487
|
for (let match of posixMatch) {
|
|
419
488
|
try {
|
|
420
489
|
let [name, value] = splitn(match.trim(), '~', 2);
|
|
421
|
-
if (name.
|
|
490
|
+
if (name.startsWith('-')) {
|
|
422
491
|
if (value.endsWith('i')) {
|
|
423
492
|
selector['!imatch'].push([
|
|
424
|
-
name.slice(
|
|
493
|
+
name.slice(1),
|
|
425
494
|
value.replace(/^\/|\/i$/g, ''),
|
|
426
495
|
]);
|
|
427
496
|
}
|
|
428
497
|
else {
|
|
429
498
|
selector['!match'].push([
|
|
430
|
-
name.slice(
|
|
499
|
+
name.slice(1),
|
|
431
500
|
value.replace(/^\/|\/$/g, ''),
|
|
432
501
|
]);
|
|
433
502
|
}
|
|
@@ -459,8 +528,8 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
459
528
|
}
|
|
460
529
|
}
|
|
461
530
|
curQuery = curQuery.replace(posixRegex, '');
|
|
462
|
-
// eg. name~Hunter or name
|
|
463
|
-
const likeRegex = /(
|
|
531
|
+
// eg. name~Hunter or -name~"hunter"i
|
|
532
|
+
const likeRegex = /(?:\s|^)-?([^-\s=\[\]<>{}()][^\s=\[\]<>{}()]*?)~(""i?|".*?[^\\]"i?|[^\s]+)(?=\s|\)|\}>|$)/g;
|
|
464
533
|
const likeMatch = curQuery.match(likeRegex);
|
|
465
534
|
if (likeMatch) {
|
|
466
535
|
selector.like = [];
|
|
@@ -470,15 +539,15 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
470
539
|
for (let match of likeMatch) {
|
|
471
540
|
try {
|
|
472
541
|
let [name, value] = splitn(match.trim(), '~', 2);
|
|
473
|
-
if (name.
|
|
542
|
+
if (name.startsWith('-')) {
|
|
474
543
|
if (value.endsWith('"i')) {
|
|
475
544
|
selector['!ilike'].push([
|
|
476
|
-
name.slice(
|
|
545
|
+
name.slice(1),
|
|
477
546
|
unQuoteString(value.slice(0, -1)),
|
|
478
547
|
]);
|
|
479
548
|
}
|
|
480
549
|
else {
|
|
481
|
-
selector['!like'].push([name.slice(
|
|
550
|
+
selector['!like'].push([name.slice(1), unQuoteString(value)]);
|
|
482
551
|
}
|
|
483
552
|
}
|
|
484
553
|
else {
|
|
@@ -508,16 +577,16 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
508
577
|
}
|
|
509
578
|
}
|
|
510
579
|
curQuery = curQuery.replace(likeRegex, '');
|
|
511
|
-
// eg. {790274347f9b3a018c2cedee} or {
|
|
512
|
-
const guidRegex = /(
|
|
580
|
+
// eg. {790274347f9b3a018c2cedee} or -{790274347f9b3a018c2cedee}
|
|
581
|
+
const guidRegex = /(?:\s|^)-?\{([0-9a-f]{24})\}(?=\s|\)|\}>|$)/g;
|
|
513
582
|
const guidMatch = curQuery.match(guidRegex);
|
|
514
583
|
if (guidMatch) {
|
|
515
584
|
selector.guid = [];
|
|
516
585
|
selector['!guid'] = [];
|
|
517
586
|
for (let match of guidMatch) {
|
|
518
587
|
try {
|
|
519
|
-
let guid = match.trim().replace(
|
|
520
|
-
if (guid.startsWith('
|
|
588
|
+
let guid = match.trim().replace(/^(-?)\{|\}$/g, '$1');
|
|
589
|
+
if (guid.startsWith('-')) {
|
|
521
590
|
selector['!guid'].push(guid.slice(1));
|
|
522
591
|
}
|
|
523
592
|
else {
|
|
@@ -536,16 +605,16 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
536
605
|
}
|
|
537
606
|
}
|
|
538
607
|
curQuery = curQuery.replace(guidRegex, '');
|
|
539
|
-
// eg. [enabled] or [
|
|
540
|
-
const truthyRegex = /(
|
|
608
|
+
// eg. [enabled] or -[defaultPrimaryGroup]
|
|
609
|
+
const truthyRegex = /(?:\s|^)-?\[([^\s=\[\]<>{}]+?)\](?=\s|\)|\}>|$)/g;
|
|
541
610
|
const truthyMatch = curQuery.match(truthyRegex);
|
|
542
611
|
if (truthyMatch) {
|
|
543
612
|
selector.truthy = [];
|
|
544
613
|
selector['!truthy'] = [];
|
|
545
614
|
for (let match of truthyMatch) {
|
|
546
615
|
try {
|
|
547
|
-
let name = match.trim().replace(
|
|
548
|
-
if (name.startsWith('
|
|
616
|
+
let name = match.trim().replace(/^(-?)\[|\]$/g, '$1');
|
|
617
|
+
if (name.startsWith('-')) {
|
|
549
618
|
selector['!truthy'].push(name.slice(1));
|
|
550
619
|
}
|
|
551
620
|
else {
|
|
@@ -564,16 +633,16 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
564
633
|
}
|
|
565
634
|
}
|
|
566
635
|
curQuery = curQuery.replace(truthyRegex, '');
|
|
567
|
-
// eg. <archived> or
|
|
568
|
-
const tagRegex = /(
|
|
636
|
+
// eg. <archived> or -<archived>
|
|
637
|
+
const tagRegex = /(?:\s|^)-?<(\w+)>(?=\s|\)|\}>|$)/g;
|
|
569
638
|
const tagMatch = curQuery.match(tagRegex);
|
|
570
639
|
if (tagMatch) {
|
|
571
640
|
selector.tag = [];
|
|
572
641
|
selector['!tag'] = [];
|
|
573
642
|
for (let match of tagMatch) {
|
|
574
643
|
try {
|
|
575
|
-
let name = match.trim().replace(
|
|
576
|
-
if (name.startsWith('
|
|
644
|
+
let name = match.trim().replace(/^(-?)<|>$/g, '$1');
|
|
645
|
+
if (name.startsWith('-')) {
|
|
577
646
|
selector['!tag'].push(name.slice(1));
|
|
578
647
|
}
|
|
579
648
|
else {
|
|
@@ -592,15 +661,21 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
592
661
|
}
|
|
593
662
|
}
|
|
594
663
|
curQuery = curQuery.replace(tagRegex, '');
|
|
595
|
-
// eg. cdate>15
|
|
596
|
-
const gtRegex = /(
|
|
664
|
+
// eg. cdate>15 or -cdate>15
|
|
665
|
+
const gtRegex = /(?:\s|^)-?([^\s=\[\]<>{}]+?)>(-?\d+(?:\.\d+)?)(?=\s|\)|\}>|$)/g;
|
|
597
666
|
const gtMatch = curQuery.match(gtRegex);
|
|
598
667
|
if (gtMatch) {
|
|
599
668
|
selector.gt = [];
|
|
669
|
+
selector['!gt'] = [];
|
|
600
670
|
for (let match of gtMatch) {
|
|
601
671
|
try {
|
|
602
672
|
let [name, value] = splitn(match.trim(), '>', 2);
|
|
603
|
-
|
|
673
|
+
if (name.startsWith('-')) {
|
|
674
|
+
selector['!gt'].push([name.slice(1), Number(value)]);
|
|
675
|
+
}
|
|
676
|
+
else {
|
|
677
|
+
selector.gt.push([name, Number(value)]);
|
|
678
|
+
}
|
|
604
679
|
}
|
|
605
680
|
catch (e) {
|
|
606
681
|
continue;
|
|
@@ -609,23 +684,38 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
609
684
|
if (!selector.gt.length) {
|
|
610
685
|
delete selector.gt;
|
|
611
686
|
}
|
|
687
|
+
if (!selector['!gt'].length) {
|
|
688
|
+
delete selector['!gt'];
|
|
689
|
+
}
|
|
612
690
|
}
|
|
613
691
|
curQuery = curQuery.replace(gtRegex, '');
|
|
614
|
-
// eg. cdate>yesterday or cdate>"2 days ago"
|
|
615
|
-
const gtRelativeRegex = /(
|
|
692
|
+
// eg. cdate>yesterday or -cdate>"2 days ago"
|
|
693
|
+
const gtRelativeRegex = /(?:\s|^)-?([^\s=\[\]<>{}]+?)>(\w+|"[^"]+")(?=\s|\)|\}>|$)/g;
|
|
616
694
|
const gtRelativeMatch = curQuery.match(gtRelativeRegex);
|
|
617
695
|
if (gtRelativeMatch) {
|
|
618
696
|
if (selector.gt == null) {
|
|
619
697
|
selector.gt = [];
|
|
620
698
|
}
|
|
699
|
+
if (selector['!gt'] == null) {
|
|
700
|
+
selector['!gt'] = [];
|
|
701
|
+
}
|
|
621
702
|
for (let match of gtRelativeMatch) {
|
|
622
703
|
try {
|
|
623
704
|
let [name, value] = splitn(match.trim(), '>', 2);
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
705
|
+
if (name.startsWith('-')) {
|
|
706
|
+
selector['!gt'].push([
|
|
707
|
+
name.slice(1),
|
|
708
|
+
null,
|
|
709
|
+
value.replace(/"/g, ''),
|
|
710
|
+
]);
|
|
711
|
+
}
|
|
712
|
+
else {
|
|
713
|
+
selector.gt.push([
|
|
714
|
+
name,
|
|
715
|
+
null,
|
|
716
|
+
value.replace(/"/g, ''),
|
|
717
|
+
]);
|
|
718
|
+
}
|
|
629
719
|
}
|
|
630
720
|
catch (e) {
|
|
631
721
|
continue;
|
|
@@ -634,17 +724,26 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
634
724
|
if (!selector.gt.length) {
|
|
635
725
|
delete selector.gt;
|
|
636
726
|
}
|
|
727
|
+
if (!selector['!gt'].length) {
|
|
728
|
+
delete selector['!gt'];
|
|
729
|
+
}
|
|
637
730
|
}
|
|
638
731
|
curQuery = curQuery.replace(gtRelativeRegex, '');
|
|
639
|
-
// eg. cdate>=15
|
|
640
|
-
const gteRegex = /(
|
|
732
|
+
// eg. cdate>=15 or -cdate>=15
|
|
733
|
+
const gteRegex = /(?:\s|^)-?([^\s=\[\]<>{}]+?)>=(-?\d+(?:\.\d+)?)(?=\s|\)|\}>|$)/g;
|
|
641
734
|
const gteMatch = curQuery.match(gteRegex);
|
|
642
735
|
if (gteMatch) {
|
|
643
736
|
selector.gte = [];
|
|
737
|
+
selector['!gte'] = [];
|
|
644
738
|
for (let match of gteMatch) {
|
|
645
739
|
try {
|
|
646
740
|
let [name, value] = splitn(match.trim(), '>=', 2);
|
|
647
|
-
|
|
741
|
+
if (name.startsWith('-')) {
|
|
742
|
+
selector['!gte'].push([name.slice(1), Number(value)]);
|
|
743
|
+
}
|
|
744
|
+
else {
|
|
745
|
+
selector.gte.push([name, Number(value)]);
|
|
746
|
+
}
|
|
648
747
|
}
|
|
649
748
|
catch (e) {
|
|
650
749
|
continue;
|
|
@@ -653,23 +752,38 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
653
752
|
if (!selector.gte.length) {
|
|
654
753
|
delete selector.gte;
|
|
655
754
|
}
|
|
755
|
+
if (!selector['!gte'].length) {
|
|
756
|
+
delete selector['!gte'];
|
|
757
|
+
}
|
|
656
758
|
}
|
|
657
759
|
curQuery = curQuery.replace(gteRegex, '');
|
|
658
|
-
// eg. cdate>=yesterday or cdate>="2 days ago"
|
|
659
|
-
const gteRelativeRegex = /(
|
|
760
|
+
// eg. cdate>=yesterday or -cdate>="2 days ago"
|
|
761
|
+
const gteRelativeRegex = /(?:\s|^)-?([^\s=\[\]<>{}]+?)>=(\w+|"[^"]+")(?=\s|\)|\}>|$)/g;
|
|
660
762
|
const gteRelativeMatch = curQuery.match(gteRelativeRegex);
|
|
661
763
|
if (gteRelativeMatch) {
|
|
662
764
|
if (selector.gte == null) {
|
|
663
765
|
selector.gte = [];
|
|
664
766
|
}
|
|
767
|
+
if (selector['!gte'] == null) {
|
|
768
|
+
selector['!gte'] = [];
|
|
769
|
+
}
|
|
665
770
|
for (let match of gteRelativeMatch) {
|
|
666
771
|
try {
|
|
667
772
|
let [name, value] = splitn(match.trim(), '>=', 2);
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
773
|
+
if (name.startsWith('-')) {
|
|
774
|
+
selector['!gte'].push([
|
|
775
|
+
name.slice(1),
|
|
776
|
+
null,
|
|
777
|
+
value.replace(/"/g, ''),
|
|
778
|
+
]);
|
|
779
|
+
}
|
|
780
|
+
else {
|
|
781
|
+
selector.gte.push([
|
|
782
|
+
name,
|
|
783
|
+
null,
|
|
784
|
+
value.replace(/"/g, ''),
|
|
785
|
+
]);
|
|
786
|
+
}
|
|
673
787
|
}
|
|
674
788
|
catch (e) {
|
|
675
789
|
continue;
|
|
@@ -678,17 +792,26 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
678
792
|
if (!selector.gte.length) {
|
|
679
793
|
delete selector.gte;
|
|
680
794
|
}
|
|
795
|
+
if (!selector['!gte'].length) {
|
|
796
|
+
delete selector['!gte'];
|
|
797
|
+
}
|
|
681
798
|
}
|
|
682
799
|
curQuery = curQuery.replace(gteRelativeRegex, '');
|
|
683
|
-
// eg. cdate<15
|
|
684
|
-
const ltRegex = /(
|
|
800
|
+
// eg. cdate<15 or -cdate<15
|
|
801
|
+
const ltRegex = /(?:\s|^)-?([^\s=\[\]<>{}]+?)<(-?\d+(?:\.\d+)?)(?=\s|\)|\}>|$)/g;
|
|
685
802
|
const ltMatch = curQuery.match(ltRegex);
|
|
686
803
|
if (ltMatch) {
|
|
687
804
|
selector.lt = [];
|
|
805
|
+
selector['!lt'] = [];
|
|
688
806
|
for (let match of ltMatch) {
|
|
689
807
|
try {
|
|
690
808
|
let [name, value] = splitn(match.trim(), '<', 2);
|
|
691
|
-
|
|
809
|
+
if (name.startsWith('-')) {
|
|
810
|
+
selector['!lt'].push([name.slice(1), Number(value)]);
|
|
811
|
+
}
|
|
812
|
+
else {
|
|
813
|
+
selector.lt.push([name, Number(value)]);
|
|
814
|
+
}
|
|
692
815
|
}
|
|
693
816
|
catch (e) {
|
|
694
817
|
continue;
|
|
@@ -697,23 +820,38 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
697
820
|
if (!selector.lt.length) {
|
|
698
821
|
delete selector.lt;
|
|
699
822
|
}
|
|
823
|
+
if (!selector['!lt'].length) {
|
|
824
|
+
delete selector['!lt'];
|
|
825
|
+
}
|
|
700
826
|
}
|
|
701
827
|
curQuery = curQuery.replace(ltRegex, '');
|
|
702
|
-
// eg. cdate<yesterday or cdate<"2 days ago"
|
|
703
|
-
const ltRelativeRegex = /(
|
|
828
|
+
// eg. cdate<yesterday or -cdate<"2 days ago"
|
|
829
|
+
const ltRelativeRegex = /(?:\s|^)-?([^\s=\[\]<>{}]+?)<(\w+|"[^"]+")(?=\s|\)|\}>|$)/g;
|
|
704
830
|
const ltRelativeMatch = curQuery.match(ltRelativeRegex);
|
|
705
831
|
if (ltRelativeMatch) {
|
|
706
832
|
if (selector.lt == null) {
|
|
707
833
|
selector.lt = [];
|
|
708
834
|
}
|
|
835
|
+
if (selector['!lt'] == null) {
|
|
836
|
+
selector['!lt'] = [];
|
|
837
|
+
}
|
|
709
838
|
for (let match of ltRelativeMatch) {
|
|
710
839
|
try {
|
|
711
840
|
let [name, value] = splitn(match.trim(), '<', 2);
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
841
|
+
if (name.startsWith('-')) {
|
|
842
|
+
selector['!lt'].push([
|
|
843
|
+
name.slice(1),
|
|
844
|
+
null,
|
|
845
|
+
value.replace(/"/g, ''),
|
|
846
|
+
]);
|
|
847
|
+
}
|
|
848
|
+
else {
|
|
849
|
+
selector.lt.push([
|
|
850
|
+
name,
|
|
851
|
+
null,
|
|
852
|
+
value.replace(/"/g, ''),
|
|
853
|
+
]);
|
|
854
|
+
}
|
|
717
855
|
}
|
|
718
856
|
catch (e) {
|
|
719
857
|
continue;
|
|
@@ -722,17 +860,26 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
722
860
|
if (!selector.lt.length) {
|
|
723
861
|
delete selector.lt;
|
|
724
862
|
}
|
|
863
|
+
if (!selector['!lt'].length) {
|
|
864
|
+
delete selector['!lt'];
|
|
865
|
+
}
|
|
725
866
|
}
|
|
726
867
|
curQuery = curQuery.replace(ltRelativeRegex, '');
|
|
727
|
-
// eg. cdate<=15
|
|
728
|
-
const lteRegex = /(
|
|
868
|
+
// eg. cdate<=15 or -cdate<=15
|
|
869
|
+
const lteRegex = /(?:\s|^)-?([^\s=\[\]<>{}]+?)<=(-?\d+(?:\.\d+)?)(?=\s|\)|\}>|$)/g;
|
|
729
870
|
const lteMatch = curQuery.match(lteRegex);
|
|
730
871
|
if (lteMatch) {
|
|
731
872
|
selector.lte = [];
|
|
873
|
+
selector['!lte'] = [];
|
|
732
874
|
for (let match of lteMatch) {
|
|
733
875
|
try {
|
|
734
876
|
let [name, value] = splitn(match.trim(), '<=', 2);
|
|
735
|
-
|
|
877
|
+
if (name.startsWith('-')) {
|
|
878
|
+
selector['!lte'].push([name.slice(1), Number(value)]);
|
|
879
|
+
}
|
|
880
|
+
else {
|
|
881
|
+
selector.lte.push([name, Number(value)]);
|
|
882
|
+
}
|
|
736
883
|
}
|
|
737
884
|
catch (e) {
|
|
738
885
|
continue;
|
|
@@ -741,23 +888,38 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
741
888
|
if (!selector.lte.length) {
|
|
742
889
|
delete selector.lte;
|
|
743
890
|
}
|
|
891
|
+
if (!selector['!lte'].length) {
|
|
892
|
+
delete selector['!lte'];
|
|
893
|
+
}
|
|
744
894
|
}
|
|
745
895
|
curQuery = curQuery.replace(lteRegex, '');
|
|
746
|
-
// eg. cdate<=yesterday or cdate<="2 days ago"
|
|
747
|
-
const lteRelativeRegex = /(
|
|
896
|
+
// eg. cdate<=yesterday or -cdate<="2 days ago"
|
|
897
|
+
const lteRelativeRegex = /(?:\s|^)-?([^\s=\[\]<>{}]+?)<=(\w+|"[^"]+")(?=\s|\)|\}>|$)/g;
|
|
748
898
|
const lteRelativeMatch = curQuery.match(lteRelativeRegex);
|
|
749
899
|
if (lteRelativeMatch) {
|
|
750
900
|
if (selector.lte == null) {
|
|
751
901
|
selector.lte = [];
|
|
752
902
|
}
|
|
903
|
+
if (selector['!lte'] == null) {
|
|
904
|
+
selector['!lte'] = [];
|
|
905
|
+
}
|
|
753
906
|
for (let match of lteRelativeMatch) {
|
|
754
907
|
try {
|
|
755
908
|
let [name, value] = splitn(match.trim(), '<=', 2);
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
909
|
+
if (name.startsWith('-')) {
|
|
910
|
+
selector['!lte'].push([
|
|
911
|
+
name.slice(1),
|
|
912
|
+
null,
|
|
913
|
+
value.replace(/"/g, ''),
|
|
914
|
+
]);
|
|
915
|
+
}
|
|
916
|
+
else {
|
|
917
|
+
selector.lte.push([
|
|
918
|
+
name,
|
|
919
|
+
null,
|
|
920
|
+
value.replace(/"/g, ''),
|
|
921
|
+
]);
|
|
922
|
+
}
|
|
761
923
|
}
|
|
762
924
|
catch (e) {
|
|
763
925
|
continue;
|
|
@@ -766,6 +928,9 @@ function selectorParser({ query, selector, qrefMap, bareHandler, }) {
|
|
|
766
928
|
if (!selector.lte.length) {
|
|
767
929
|
delete selector.lte;
|
|
768
930
|
}
|
|
931
|
+
if (!selector['!lte'].length) {
|
|
932
|
+
delete selector['!lte'];
|
|
933
|
+
}
|
|
769
934
|
}
|
|
770
935
|
curQuery = curQuery.replace(lteRelativeRegex, '');
|
|
771
936
|
return curQuery.trim();
|