@nymphjs/query-parser 1.0.0-beta.122 → 1.0.0-beta.123

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.
@@ -116,13 +116,13 @@ function selectorsParser({ query, entityClass, type, defaultFields, qrefMap, opt
116
116
  bareHandler,
117
117
  });
118
118
  if (options) {
119
- const limitRegex = /(?: |^)limit:(\d+)(?= |$)/;
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 = /(?: |^)offset:(\d+)(?= |$)/;
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 = /(?: |^)sort:(-|[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)(?= |$)/;
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 = /(?: |^)reverse:(true|false|1|0)(?= |$)/;
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
- // eg. prop(some search string) or prop!(some search string)
172
- const searchRegex = /(?: |^)([^\s=\[\]<>{}]+?)!?\([^\)]+\)(?= |$)/g;
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.endsWith('!')) {
181
- selector['!search'].push([name.slice(0, -1), value]);
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. user<{User name="Hunter"}> or user!<{User name="Hunter"}>
200
- const qrefRegex = /(?: |^)([^\s=\[\]<>{}]+?)!?<\{(\w+) (.*?[^\\])\}>(?= |$)/g;
201
- const qrefMatch = curQuery.match(qrefRegex);
202
- if (qrefMatch) {
203
- selector.qref = [];
204
- selector['!qref'] = [];
205
- for (let match of qrefMatch) {
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().slice(0, -1), '<', 2);
208
- value = unQuoteCurlies(value.slice(1, -1));
209
- let [className, qrefQuery] = splitn(value, ' ', 2);
210
- const EntityClass = qrefMap[className].class;
211
- if (EntityClass == null) {
212
- continue;
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.qref.push([name, qref]);
297
+ selector.search.push([name, value]);
226
298
  }
227
299
  }
228
300
  catch (e) {
229
301
  continue;
230
302
  }
231
303
  }
232
- if (!selector.qref.length) {
233
- delete selector.qref;
304
+ if (selector.search == null || !selector.search.length) {
305
+ delete selector.search;
234
306
  }
235
- if (!selector['!qref'].length) {
236
- delete selector['!qref'];
307
+ if (selector['!search'] == null || !selector['!search'].length) {
308
+ delete selector['!search'];
237
309
  }
238
310
  }
239
- curQuery = curQuery.replace(qrefRegex, '');
311
+ curQuery = curQuery.replace(searchColonRegex, '');
240
312
  // eg. someArray=[1,2] or someObject={"prop":"some value"}
241
- const equalJsonRegex = /(?: |^)([^\s=\[\]<>{}]+?)!?=(\{|\[)/g;
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.endsWith('!')) {
330
+ if (name.startsWith('-')) {
259
331
  selector['!equal'].unshift([
260
- name.slice(0, -1),
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 = /(?: |^)([^\s=\[\]<>{}]+?)!?=(""|".*?[^\\]"|[^ ]+)(?= |$)/g;
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.endsWith('!')) {
373
+ if (name.startsWith('-')) {
302
374
  selector['!equal'].push([
303
- name.slice(0, -1),
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.endsWith('!')) {
384
+ if (name.startsWith('-')) {
313
385
  selector['!equal'].push([
314
- name.slice(0, -1),
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!<{790274347f9b3a018c2cedee}>
339
- const refRegex = /(?: |^)([^\s=\[\]<>{}]+?)!?<\{([0-9a-f]{24})\}>(?= |$)/g;
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.endsWith('!')) {
348
- selector['!ref'].push([name.slice(0, -1), value.slice(1, -1)]);
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!<"some string">
367
- const containRegex = /(?: |^)([^\s=\[\]<>{}]+?)!?(<(?:[^"][^>]*?|".*?[^\\]"))>(?= |$)/g;
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.endsWith('!')) {
448
+ if (name.startsWith('-')) {
377
449
  selector['!contain'].push([
378
- name.slice(0, -1),
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.endsWith('!')) {
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!~/hunter/i
411
- const posixRegex = /(?: |^)([^\s=\[\]<>{}]+?)!?~(\/\/|\/.*?[^\\]\/)i?(?= |$)/g;
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.endsWith('!')) {
490
+ if (name.startsWith('-')) {
422
491
  if (value.endsWith('i')) {
423
492
  selector['!imatch'].push([
424
- name.slice(0, -1),
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(0, -1),
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!~"hunter"i
463
- const likeRegex = /(?: |^)([^\s=\[\]<>{}]+?)!?~(""i?|".*?[^\\]"i?|[^ ]+)(?= |$)/g;
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.endsWith('!')) {
542
+ if (name.startsWith('-')) {
474
543
  if (value.endsWith('"i')) {
475
544
  selector['!ilike'].push([
476
- name.slice(0, -1),
545
+ name.slice(1),
477
546
  unQuoteString(value.slice(0, -1)),
478
547
  ]);
479
548
  }
480
549
  else {
481
- selector['!like'].push([name.slice(0, -1), unQuoteString(value)]);
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 {!790274347f9b3a018c2cedee}
512
- const guidRegex = /(?: |^)\{!?([0-9a-f]{24})\}(?= |$)/g;
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(/^\{|\}$/g, '');
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 [!defaultPrimaryGroup]
540
- const truthyRegex = /(?: |^)\[(!?[^\s=\[\]<>{}]+?)\](?= |$)/g;
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(/^\[|\]$/g, '');
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 <!archived>
568
- const tagRegex = /(?: |^)<(!?\w+)>(?= |$)/g;
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(/^<|>$/g, '');
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 = /(?: |^)([^\s=\[\]<>{}]+?)>(-?\d+(?:\.\d+)?)(?= |$)/g;
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
- selector.gt.push([name, Number(value)]);
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 = /(?: |^)([^\s=\[\]<>{}]+?)>(\w+|"[^"]+")(?= |$)/g;
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
- selector.gt.push([
625
- name,
626
- null,
627
- value.replace(/"/g, ''),
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 = /(?: |^)([^\s=\[\]<>{}]+?)>=(-?\d+(?:\.\d+)?)(?= |$)/g;
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
- selector.gte.push([name, Number(value)]);
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 = /(?: |^)([^\s=\[\]<>{}]+?)>=(\w+|"[^"]+")(?= |$)/g;
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
- selector.gte.push([
669
- name,
670
- null,
671
- value.replace(/"/g, ''),
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 = /(?: |^)([^\s=\[\]<>{}]+?)<(-?\d+(?:\.\d+)?)(?= |$)/g;
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
- selector.lt.push([name, Number(value)]);
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 = /(?: |^)([^\s=\[\]<>{}]+?)<(\w+|"[^"]+")(?= |$)/g;
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
- selector.lt.push([
713
- name,
714
- null,
715
- value.replace(/"/g, ''),
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 = /(?: |^)([^\s=\[\]<>{}]+?)<=(-?\d+(?:\.\d+)?)(?= |$)/g;
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
- selector.lte.push([name, Number(value)]);
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 = /(?: |^)([^\s=\[\]<>{}]+?)<=(\w+|"[^"]+")(?= |$)/g;
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
- selector.lte.push([
757
- name,
758
- null,
759
- value.replace(/"/g, ''),
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();