@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.
- package/CHANGELOG.md +6 -0
- package/README.md +48 -46
- package/dist/queryParser.js +285 -120
- package/dist/queryParser.js.map +1 -1
- package/dist/queryParser.test.js +402 -29
- package/dist/queryParser.test.js.map +1 -1
- package/package.json +3 -3
- package/src/queryParser.test.ts +454 -29
- package/src/queryParser.ts +300 -120
package/src/queryParser.test.ts
CHANGED
|
@@ -3,6 +3,7 @@ import queryParser from './queryParser.js';
|
|
|
3
3
|
|
|
4
4
|
const BlogPost = function () {} as unknown as typeof Entity;
|
|
5
5
|
const Category = function () {} as unknown as typeof Entity;
|
|
6
|
+
const List = function () {} as unknown as typeof Entity;
|
|
6
7
|
|
|
7
8
|
describe('queryParser', () => {
|
|
8
9
|
it('parses a basic query', () => {
|
|
@@ -55,13 +56,13 @@ describe('queryParser', () => {
|
|
|
55
56
|
});
|
|
56
57
|
|
|
57
58
|
it('gives the correct entity and default fields to bare queries', () => {
|
|
58
|
-
const query = 'category<{
|
|
59
|
+
const query = 'category<{Cat search}>';
|
|
59
60
|
const [options, ...selectors] = queryParser({
|
|
60
61
|
query,
|
|
61
62
|
entityClass: BlogPost,
|
|
62
63
|
defaultFields: ['text'],
|
|
63
64
|
qrefMap: {
|
|
64
|
-
|
|
65
|
+
Cat: {
|
|
65
66
|
class: Category,
|
|
66
67
|
defaultFields: ['name'],
|
|
67
68
|
},
|
|
@@ -97,13 +98,13 @@ describe('queryParser', () => {
|
|
|
97
98
|
|
|
98
99
|
it('parses the example query from the readme', () => {
|
|
99
100
|
const query =
|
|
100
|
-
'limit:4 foobar (| [archived] mdate<"2 weeks ago") category<{
|
|
101
|
+
'limit:4 foobar (| [archived] mdate<"2 weeks ago") category<{Cat Tech}>';
|
|
101
102
|
const [options, ...selectors] = queryParser({
|
|
102
103
|
query,
|
|
103
104
|
entityClass: BlogPost,
|
|
104
105
|
defaultFields: ['title', 'body'],
|
|
105
106
|
qrefMap: {
|
|
106
|
-
|
|
107
|
+
Cat: {
|
|
107
108
|
class: Category,
|
|
108
109
|
defaultFields: ['name'],
|
|
109
110
|
},
|
|
@@ -289,6 +290,108 @@ describe('queryParser', () => {
|
|
|
289
290
|
]);
|
|
290
291
|
});
|
|
291
292
|
|
|
293
|
+
it('parses a query with not search', () => {
|
|
294
|
+
const query = 'limit:4 foobar -prop(a search string)';
|
|
295
|
+
const [options, ...selectors] = queryParser({
|
|
296
|
+
query,
|
|
297
|
+
entityClass: BlogPost,
|
|
298
|
+
defaultFields: ['title', 'body'],
|
|
299
|
+
qrefMap: {
|
|
300
|
+
cat: {
|
|
301
|
+
class: Category,
|
|
302
|
+
defaultFields: ['name'],
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
expect(options).toEqual({
|
|
308
|
+
class: BlogPost,
|
|
309
|
+
limit: 4,
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
expect(selectors).toEqual([
|
|
313
|
+
{
|
|
314
|
+
type: '&',
|
|
315
|
+
'!search': [['prop', 'a search string']],
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
type: '|',
|
|
319
|
+
ilike: [
|
|
320
|
+
['title', '%foobar%'],
|
|
321
|
+
['body', '%foobar%'],
|
|
322
|
+
],
|
|
323
|
+
},
|
|
324
|
+
]);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('parses a query with colon search', () => {
|
|
328
|
+
const query = 'limit:4 foobar prop:string';
|
|
329
|
+
const [options, ...selectors] = queryParser({
|
|
330
|
+
query,
|
|
331
|
+
entityClass: BlogPost,
|
|
332
|
+
defaultFields: ['title', 'body'],
|
|
333
|
+
qrefMap: {
|
|
334
|
+
cat: {
|
|
335
|
+
class: Category,
|
|
336
|
+
defaultFields: ['name'],
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
expect(options).toEqual({
|
|
342
|
+
class: BlogPost,
|
|
343
|
+
limit: 4,
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
expect(selectors).toEqual([
|
|
347
|
+
{
|
|
348
|
+
type: '&',
|
|
349
|
+
search: [['prop', 'string']],
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
type: '|',
|
|
353
|
+
ilike: [
|
|
354
|
+
['title', '%foobar%'],
|
|
355
|
+
['body', '%foobar%'],
|
|
356
|
+
],
|
|
357
|
+
},
|
|
358
|
+
]);
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
it('parses a query with not colon search', () => {
|
|
362
|
+
const query = 'limit:4 foobar -prop:string';
|
|
363
|
+
const [options, ...selectors] = queryParser({
|
|
364
|
+
query,
|
|
365
|
+
entityClass: BlogPost,
|
|
366
|
+
defaultFields: ['title', 'body'],
|
|
367
|
+
qrefMap: {
|
|
368
|
+
cat: {
|
|
369
|
+
class: Category,
|
|
370
|
+
defaultFields: ['name'],
|
|
371
|
+
},
|
|
372
|
+
},
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
expect(options).toEqual({
|
|
376
|
+
class: BlogPost,
|
|
377
|
+
limit: 4,
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
expect(selectors).toEqual([
|
|
381
|
+
{
|
|
382
|
+
type: '&',
|
|
383
|
+
'!search': [['prop', 'string']],
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
type: '|',
|
|
387
|
+
ilike: [
|
|
388
|
+
['title', '%foobar%'],
|
|
389
|
+
['body', '%foobar%'],
|
|
390
|
+
],
|
|
391
|
+
},
|
|
392
|
+
]);
|
|
393
|
+
});
|
|
394
|
+
|
|
292
395
|
it('parses a query with search in a selector', () => {
|
|
293
396
|
const query =
|
|
294
397
|
'limit:4 foobar (| prop(a search string) prop2("another search string"))';
|
|
@@ -332,6 +435,53 @@ describe('queryParser', () => {
|
|
|
332
435
|
]);
|
|
333
436
|
});
|
|
334
437
|
|
|
438
|
+
it('parses a query with colon search in a selector', () => {
|
|
439
|
+
const query =
|
|
440
|
+
'limit:4 foobar (| prop:string prop2:"another search string" -prop3:pickle -prop4:\'another -pickle string\')';
|
|
441
|
+
const [options, ...selectors] = queryParser({
|
|
442
|
+
query,
|
|
443
|
+
entityClass: BlogPost,
|
|
444
|
+
defaultFields: ['title', 'body'],
|
|
445
|
+
qrefMap: {
|
|
446
|
+
cat: {
|
|
447
|
+
class: Category,
|
|
448
|
+
defaultFields: ['name'],
|
|
449
|
+
},
|
|
450
|
+
},
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
expect(options).toEqual({
|
|
454
|
+
class: BlogPost,
|
|
455
|
+
limit: 4,
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
expect(selectors).toEqual([
|
|
459
|
+
{
|
|
460
|
+
type: '&',
|
|
461
|
+
selector: [
|
|
462
|
+
{
|
|
463
|
+
type: '|',
|
|
464
|
+
search: [
|
|
465
|
+
['prop', 'string'],
|
|
466
|
+
['prop2', '"another search string"'],
|
|
467
|
+
],
|
|
468
|
+
'!search': [
|
|
469
|
+
['prop3', 'pickle'],
|
|
470
|
+
['prop4', "'another -pickle string'"],
|
|
471
|
+
],
|
|
472
|
+
},
|
|
473
|
+
],
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
type: '|',
|
|
477
|
+
ilike: [
|
|
478
|
+
['title', '%foobar%'],
|
|
479
|
+
['body', '%foobar%'],
|
|
480
|
+
],
|
|
481
|
+
},
|
|
482
|
+
]);
|
|
483
|
+
});
|
|
484
|
+
|
|
335
485
|
it('parses a query with lt and tag', () => {
|
|
336
486
|
const query = 'limit:4 foobar mdate<"2 weeks ago" <tag>';
|
|
337
487
|
const [options, ...selectors] = queryParser({
|
|
@@ -537,7 +687,7 @@ describe('queryParser', () => {
|
|
|
537
687
|
});
|
|
538
688
|
|
|
539
689
|
it('parses simple not equal clauses', () => {
|
|
540
|
-
const query = 'prop
|
|
690
|
+
const query = '-prop=string';
|
|
541
691
|
const [options, ...selectors] = queryParser({
|
|
542
692
|
query,
|
|
543
693
|
entityClass: BlogPost,
|
|
@@ -575,7 +725,7 @@ describe('queryParser', () => {
|
|
|
575
725
|
});
|
|
576
726
|
|
|
577
727
|
it('parses quoted not equal clauses', () => {
|
|
578
|
-
const query = 'prop
|
|
728
|
+
const query = '-prop="a string"';
|
|
579
729
|
const [options, ...selectors] = queryParser({
|
|
580
730
|
query,
|
|
581
731
|
entityClass: BlogPost,
|
|
@@ -613,7 +763,7 @@ describe('queryParser', () => {
|
|
|
613
763
|
});
|
|
614
764
|
|
|
615
765
|
it('parses json not equal clauses', () => {
|
|
616
|
-
const query = 'prop
|
|
766
|
+
const query = '-prop=true';
|
|
617
767
|
const [options, ...selectors] = queryParser({
|
|
618
768
|
query,
|
|
619
769
|
entityClass: BlogPost,
|
|
@@ -651,7 +801,7 @@ describe('queryParser', () => {
|
|
|
651
801
|
});
|
|
652
802
|
|
|
653
803
|
it('parses not guid clauses', () => {
|
|
654
|
-
const query = '{
|
|
804
|
+
const query = '-{111111111111111111111111}';
|
|
655
805
|
const [options, ...selectors] = queryParser({
|
|
656
806
|
query,
|
|
657
807
|
entityClass: BlogPost,
|
|
@@ -689,7 +839,7 @@ describe('queryParser', () => {
|
|
|
689
839
|
});
|
|
690
840
|
|
|
691
841
|
it('parses not tag clauses', () => {
|
|
692
|
-
const query = '
|
|
842
|
+
const query = '-<tagname>';
|
|
693
843
|
const [options, ...selectors] = queryParser({
|
|
694
844
|
query,
|
|
695
845
|
entityClass: BlogPost,
|
|
@@ -727,7 +877,7 @@ describe('queryParser', () => {
|
|
|
727
877
|
});
|
|
728
878
|
|
|
729
879
|
it('parses not truthy clauses', () => {
|
|
730
|
-
const query = '[
|
|
880
|
+
const query = '-[truthyname]';
|
|
731
881
|
const [options, ...selectors] = queryParser({
|
|
732
882
|
query,
|
|
733
883
|
entityClass: BlogPost,
|
|
@@ -765,7 +915,7 @@ describe('queryParser', () => {
|
|
|
765
915
|
});
|
|
766
916
|
|
|
767
917
|
it('parses not ref clauses', () => {
|
|
768
|
-
const query = 'prop
|
|
918
|
+
const query = '-prop<{111111111111111111111111}>';
|
|
769
919
|
const [options, ...selectors] = queryParser({
|
|
770
920
|
query,
|
|
771
921
|
entityClass: BlogPost,
|
|
@@ -803,7 +953,7 @@ describe('queryParser', () => {
|
|
|
803
953
|
});
|
|
804
954
|
|
|
805
955
|
it('parses simple not contain clauses', () => {
|
|
806
|
-
const query = 'prop
|
|
956
|
+
const query = '-prop<string>';
|
|
807
957
|
const [options, ...selectors] = queryParser({
|
|
808
958
|
query,
|
|
809
959
|
entityClass: BlogPost,
|
|
@@ -841,7 +991,7 @@ describe('queryParser', () => {
|
|
|
841
991
|
});
|
|
842
992
|
|
|
843
993
|
it('parses json not contain clauses', () => {
|
|
844
|
-
const query = 'prop
|
|
994
|
+
const query = '-prop<true>';
|
|
845
995
|
const [options, ...selectors] = queryParser({
|
|
846
996
|
query,
|
|
847
997
|
entityClass: BlogPost,
|
|
@@ -879,7 +1029,7 @@ describe('queryParser', () => {
|
|
|
879
1029
|
});
|
|
880
1030
|
|
|
881
1031
|
it('parses not match clauses', () => {
|
|
882
|
-
const query = 'prop
|
|
1032
|
+
const query = '-prop~/regex/';
|
|
883
1033
|
const [options, ...selectors] = queryParser({
|
|
884
1034
|
query,
|
|
885
1035
|
entityClass: BlogPost,
|
|
@@ -917,7 +1067,7 @@ describe('queryParser', () => {
|
|
|
917
1067
|
});
|
|
918
1068
|
|
|
919
1069
|
it('parses not imatch clauses', () => {
|
|
920
|
-
const query = 'prop
|
|
1070
|
+
const query = '-prop~/regex/i';
|
|
921
1071
|
const [options, ...selectors] = queryParser({
|
|
922
1072
|
query,
|
|
923
1073
|
entityClass: BlogPost,
|
|
@@ -955,7 +1105,7 @@ describe('queryParser', () => {
|
|
|
955
1105
|
});
|
|
956
1106
|
|
|
957
1107
|
it('parses simple not like clauses', () => {
|
|
958
|
-
const query = 'prop
|
|
1108
|
+
const query = '-prop~pattern';
|
|
959
1109
|
const [options, ...selectors] = queryParser({
|
|
960
1110
|
query,
|
|
961
1111
|
entityClass: BlogPost,
|
|
@@ -993,7 +1143,7 @@ describe('queryParser', () => {
|
|
|
993
1143
|
});
|
|
994
1144
|
|
|
995
1145
|
it('parses quoted not like clauses', () => {
|
|
996
|
-
const query = 'prop
|
|
1146
|
+
const query = '-prop~"a pattern"';
|
|
997
1147
|
const [options, ...selectors] = queryParser({
|
|
998
1148
|
query,
|
|
999
1149
|
entityClass: BlogPost,
|
|
@@ -1031,7 +1181,7 @@ describe('queryParser', () => {
|
|
|
1031
1181
|
});
|
|
1032
1182
|
|
|
1033
1183
|
it('parses not ilike clauses', () => {
|
|
1034
|
-
const query = 'prop
|
|
1184
|
+
const query = '-prop~"a pattern"i';
|
|
1035
1185
|
const [options, ...selectors] = queryParser({
|
|
1036
1186
|
query,
|
|
1037
1187
|
entityClass: BlogPost,
|
|
@@ -1068,6 +1218,25 @@ describe('queryParser', () => {
|
|
|
1068
1218
|
]);
|
|
1069
1219
|
});
|
|
1070
1220
|
|
|
1221
|
+
it('parses simple not gt clauses', () => {
|
|
1222
|
+
const query = '-prop>30.5';
|
|
1223
|
+
const [options, ...selectors] = queryParser({
|
|
1224
|
+
query,
|
|
1225
|
+
entityClass: BlogPost,
|
|
1226
|
+
});
|
|
1227
|
+
|
|
1228
|
+
expect(options).toEqual({
|
|
1229
|
+
class: BlogPost,
|
|
1230
|
+
});
|
|
1231
|
+
|
|
1232
|
+
expect(selectors).toEqual([
|
|
1233
|
+
{
|
|
1234
|
+
type: '&',
|
|
1235
|
+
'!gt': [['prop', 30.5]],
|
|
1236
|
+
},
|
|
1237
|
+
]);
|
|
1238
|
+
});
|
|
1239
|
+
|
|
1071
1240
|
it('parses simple relative gt clauses', () => {
|
|
1072
1241
|
const query = 'prop>yesterday';
|
|
1073
1242
|
const [options, ...selectors] = queryParser({
|
|
@@ -1087,6 +1256,25 @@ describe('queryParser', () => {
|
|
|
1087
1256
|
]);
|
|
1088
1257
|
});
|
|
1089
1258
|
|
|
1259
|
+
it('parses simple relative not gt clauses', () => {
|
|
1260
|
+
const query = '-prop>yesterday';
|
|
1261
|
+
const [options, ...selectors] = queryParser({
|
|
1262
|
+
query,
|
|
1263
|
+
entityClass: BlogPost,
|
|
1264
|
+
});
|
|
1265
|
+
|
|
1266
|
+
expect(options).toEqual({
|
|
1267
|
+
class: BlogPost,
|
|
1268
|
+
});
|
|
1269
|
+
|
|
1270
|
+
expect(selectors).toEqual([
|
|
1271
|
+
{
|
|
1272
|
+
type: '&',
|
|
1273
|
+
'!gt': [['prop', null, 'yesterday']],
|
|
1274
|
+
},
|
|
1275
|
+
]);
|
|
1276
|
+
});
|
|
1277
|
+
|
|
1090
1278
|
it('parses quote relative gt clauses', () => {
|
|
1091
1279
|
const query = 'prop>"3 weeks ago"';
|
|
1092
1280
|
const [options, ...selectors] = queryParser({
|
|
@@ -1106,6 +1294,25 @@ describe('queryParser', () => {
|
|
|
1106
1294
|
]);
|
|
1107
1295
|
});
|
|
1108
1296
|
|
|
1297
|
+
it('parses quote relative not gt clauses', () => {
|
|
1298
|
+
const query = '-prop>"3 weeks ago"';
|
|
1299
|
+
const [options, ...selectors] = queryParser({
|
|
1300
|
+
query,
|
|
1301
|
+
entityClass: BlogPost,
|
|
1302
|
+
});
|
|
1303
|
+
|
|
1304
|
+
expect(options).toEqual({
|
|
1305
|
+
class: BlogPost,
|
|
1306
|
+
});
|
|
1307
|
+
|
|
1308
|
+
expect(selectors).toEqual([
|
|
1309
|
+
{
|
|
1310
|
+
type: '&',
|
|
1311
|
+
'!gt': [['prop', null, '3 weeks ago']],
|
|
1312
|
+
},
|
|
1313
|
+
]);
|
|
1314
|
+
});
|
|
1315
|
+
|
|
1109
1316
|
it('parses simple gte clauses', () => {
|
|
1110
1317
|
const query = 'prop>=30.5';
|
|
1111
1318
|
const [options, ...selectors] = queryParser({
|
|
@@ -1125,6 +1332,25 @@ describe('queryParser', () => {
|
|
|
1125
1332
|
]);
|
|
1126
1333
|
});
|
|
1127
1334
|
|
|
1335
|
+
it('parses simple not gte clauses', () => {
|
|
1336
|
+
const query = '-prop>=30.5';
|
|
1337
|
+
const [options, ...selectors] = queryParser({
|
|
1338
|
+
query,
|
|
1339
|
+
entityClass: BlogPost,
|
|
1340
|
+
});
|
|
1341
|
+
|
|
1342
|
+
expect(options).toEqual({
|
|
1343
|
+
class: BlogPost,
|
|
1344
|
+
});
|
|
1345
|
+
|
|
1346
|
+
expect(selectors).toEqual([
|
|
1347
|
+
{
|
|
1348
|
+
type: '&',
|
|
1349
|
+
'!gte': [['prop', 30.5]],
|
|
1350
|
+
},
|
|
1351
|
+
]);
|
|
1352
|
+
});
|
|
1353
|
+
|
|
1128
1354
|
it('parses simple relative gte clauses', () => {
|
|
1129
1355
|
const query = 'prop>=yesterday';
|
|
1130
1356
|
const [options, ...selectors] = queryParser({
|
|
@@ -1144,6 +1370,25 @@ describe('queryParser', () => {
|
|
|
1144
1370
|
]);
|
|
1145
1371
|
});
|
|
1146
1372
|
|
|
1373
|
+
it('parses simple relative not gte clauses', () => {
|
|
1374
|
+
const query = '-prop>=yesterday';
|
|
1375
|
+
const [options, ...selectors] = queryParser({
|
|
1376
|
+
query,
|
|
1377
|
+
entityClass: BlogPost,
|
|
1378
|
+
});
|
|
1379
|
+
|
|
1380
|
+
expect(options).toEqual({
|
|
1381
|
+
class: BlogPost,
|
|
1382
|
+
});
|
|
1383
|
+
|
|
1384
|
+
expect(selectors).toEqual([
|
|
1385
|
+
{
|
|
1386
|
+
type: '&',
|
|
1387
|
+
'!gte': [['prop', null, 'yesterday']],
|
|
1388
|
+
},
|
|
1389
|
+
]);
|
|
1390
|
+
});
|
|
1391
|
+
|
|
1147
1392
|
it('parses quote relative gte clauses', () => {
|
|
1148
1393
|
const query = 'prop>="3 weeks ago"';
|
|
1149
1394
|
const [options, ...selectors] = queryParser({
|
|
@@ -1163,6 +1408,25 @@ describe('queryParser', () => {
|
|
|
1163
1408
|
]);
|
|
1164
1409
|
});
|
|
1165
1410
|
|
|
1411
|
+
it('parses quote relative not gte clauses', () => {
|
|
1412
|
+
const query = '-prop>="3 weeks ago"';
|
|
1413
|
+
const [options, ...selectors] = queryParser({
|
|
1414
|
+
query,
|
|
1415
|
+
entityClass: BlogPost,
|
|
1416
|
+
});
|
|
1417
|
+
|
|
1418
|
+
expect(options).toEqual({
|
|
1419
|
+
class: BlogPost,
|
|
1420
|
+
});
|
|
1421
|
+
|
|
1422
|
+
expect(selectors).toEqual([
|
|
1423
|
+
{
|
|
1424
|
+
type: '&',
|
|
1425
|
+
'!gte': [['prop', null, '3 weeks ago']],
|
|
1426
|
+
},
|
|
1427
|
+
]);
|
|
1428
|
+
});
|
|
1429
|
+
|
|
1166
1430
|
it('parses simple lt clauses', () => {
|
|
1167
1431
|
const query = 'prop<30.5';
|
|
1168
1432
|
const [options, ...selectors] = queryParser({
|
|
@@ -1182,6 +1446,25 @@ describe('queryParser', () => {
|
|
|
1182
1446
|
]);
|
|
1183
1447
|
});
|
|
1184
1448
|
|
|
1449
|
+
it('parses simple not lt clauses', () => {
|
|
1450
|
+
const query = '-prop<30.5';
|
|
1451
|
+
const [options, ...selectors] = queryParser({
|
|
1452
|
+
query,
|
|
1453
|
+
entityClass: BlogPost,
|
|
1454
|
+
});
|
|
1455
|
+
|
|
1456
|
+
expect(options).toEqual({
|
|
1457
|
+
class: BlogPost,
|
|
1458
|
+
});
|
|
1459
|
+
|
|
1460
|
+
expect(selectors).toEqual([
|
|
1461
|
+
{
|
|
1462
|
+
type: '&',
|
|
1463
|
+
'!lt': [['prop', 30.5]],
|
|
1464
|
+
},
|
|
1465
|
+
]);
|
|
1466
|
+
});
|
|
1467
|
+
|
|
1185
1468
|
it('parses simple relative lt clauses', () => {
|
|
1186
1469
|
const query = 'prop<yesterday';
|
|
1187
1470
|
const [options, ...selectors] = queryParser({
|
|
@@ -1201,6 +1484,25 @@ describe('queryParser', () => {
|
|
|
1201
1484
|
]);
|
|
1202
1485
|
});
|
|
1203
1486
|
|
|
1487
|
+
it('parses simple relative not lt clauses', () => {
|
|
1488
|
+
const query = '-prop<yesterday';
|
|
1489
|
+
const [options, ...selectors] = queryParser({
|
|
1490
|
+
query,
|
|
1491
|
+
entityClass: BlogPost,
|
|
1492
|
+
});
|
|
1493
|
+
|
|
1494
|
+
expect(options).toEqual({
|
|
1495
|
+
class: BlogPost,
|
|
1496
|
+
});
|
|
1497
|
+
|
|
1498
|
+
expect(selectors).toEqual([
|
|
1499
|
+
{
|
|
1500
|
+
type: '&',
|
|
1501
|
+
'!lt': [['prop', null, 'yesterday']],
|
|
1502
|
+
},
|
|
1503
|
+
]);
|
|
1504
|
+
});
|
|
1505
|
+
|
|
1204
1506
|
it('parses quote relative lt clauses', () => {
|
|
1205
1507
|
const query = 'prop<"3 weeks ago"';
|
|
1206
1508
|
const [options, ...selectors] = queryParser({
|
|
@@ -1220,6 +1522,25 @@ describe('queryParser', () => {
|
|
|
1220
1522
|
]);
|
|
1221
1523
|
});
|
|
1222
1524
|
|
|
1525
|
+
it('parses quote relative not lt clauses', () => {
|
|
1526
|
+
const query = '-prop<"3 weeks ago"';
|
|
1527
|
+
const [options, ...selectors] = queryParser({
|
|
1528
|
+
query,
|
|
1529
|
+
entityClass: BlogPost,
|
|
1530
|
+
});
|
|
1531
|
+
|
|
1532
|
+
expect(options).toEqual({
|
|
1533
|
+
class: BlogPost,
|
|
1534
|
+
});
|
|
1535
|
+
|
|
1536
|
+
expect(selectors).toEqual([
|
|
1537
|
+
{
|
|
1538
|
+
type: '&',
|
|
1539
|
+
'!lt': [['prop', null, '3 weeks ago']],
|
|
1540
|
+
},
|
|
1541
|
+
]);
|
|
1542
|
+
});
|
|
1543
|
+
|
|
1223
1544
|
it('parses simple lte clauses', () => {
|
|
1224
1545
|
const query = 'prop<=30.5';
|
|
1225
1546
|
const [options, ...selectors] = queryParser({
|
|
@@ -1239,6 +1560,25 @@ describe('queryParser', () => {
|
|
|
1239
1560
|
]);
|
|
1240
1561
|
});
|
|
1241
1562
|
|
|
1563
|
+
it('parses simple not lte clauses', () => {
|
|
1564
|
+
const query = '-prop<=30.5';
|
|
1565
|
+
const [options, ...selectors] = queryParser({
|
|
1566
|
+
query,
|
|
1567
|
+
entityClass: BlogPost,
|
|
1568
|
+
});
|
|
1569
|
+
|
|
1570
|
+
expect(options).toEqual({
|
|
1571
|
+
class: BlogPost,
|
|
1572
|
+
});
|
|
1573
|
+
|
|
1574
|
+
expect(selectors).toEqual([
|
|
1575
|
+
{
|
|
1576
|
+
type: '&',
|
|
1577
|
+
'!lte': [['prop', 30.5]],
|
|
1578
|
+
},
|
|
1579
|
+
]);
|
|
1580
|
+
});
|
|
1581
|
+
|
|
1242
1582
|
it('parses simple relative lte clauses', () => {
|
|
1243
1583
|
const query = 'prop<=yesterday';
|
|
1244
1584
|
const [options, ...selectors] = queryParser({
|
|
@@ -1258,6 +1598,25 @@ describe('queryParser', () => {
|
|
|
1258
1598
|
]);
|
|
1259
1599
|
});
|
|
1260
1600
|
|
|
1601
|
+
it('parses simple relative not lte clauses', () => {
|
|
1602
|
+
const query = '-prop<=yesterday';
|
|
1603
|
+
const [options, ...selectors] = queryParser({
|
|
1604
|
+
query,
|
|
1605
|
+
entityClass: BlogPost,
|
|
1606
|
+
});
|
|
1607
|
+
|
|
1608
|
+
expect(options).toEqual({
|
|
1609
|
+
class: BlogPost,
|
|
1610
|
+
});
|
|
1611
|
+
|
|
1612
|
+
expect(selectors).toEqual([
|
|
1613
|
+
{
|
|
1614
|
+
type: '&',
|
|
1615
|
+
'!lte': [['prop', null, 'yesterday']],
|
|
1616
|
+
},
|
|
1617
|
+
]);
|
|
1618
|
+
});
|
|
1619
|
+
|
|
1261
1620
|
it('parses quote relative lte clauses', () => {
|
|
1262
1621
|
const query = 'prop<="3 weeks ago"';
|
|
1263
1622
|
const [options, ...selectors] = queryParser({
|
|
@@ -1277,9 +1636,28 @@ describe('queryParser', () => {
|
|
|
1277
1636
|
]);
|
|
1278
1637
|
});
|
|
1279
1638
|
|
|
1639
|
+
it('parses quote relative not lte clauses', () => {
|
|
1640
|
+
const query = '-prop<="3 weeks ago"';
|
|
1641
|
+
const [options, ...selectors] = queryParser({
|
|
1642
|
+
query,
|
|
1643
|
+
entityClass: BlogPost,
|
|
1644
|
+
});
|
|
1645
|
+
|
|
1646
|
+
expect(options).toEqual({
|
|
1647
|
+
class: BlogPost,
|
|
1648
|
+
});
|
|
1649
|
+
|
|
1650
|
+
expect(selectors).toEqual([
|
|
1651
|
+
{
|
|
1652
|
+
type: '&',
|
|
1653
|
+
'!lte': [['prop', null, '3 weeks ago']],
|
|
1654
|
+
},
|
|
1655
|
+
]);
|
|
1656
|
+
});
|
|
1657
|
+
|
|
1280
1658
|
it('parses complex selectors', () => {
|
|
1281
1659
|
const query =
|
|
1282
|
-
'(! [published] <draft>) (| cdate>"6 months ago" mdate>"1 month ago")';
|
|
1660
|
+
'(! [published] <draft>) (| -cdate>"6 months ago" mdate>"1 month ago")';
|
|
1283
1661
|
const [options, ...selectors] = queryParser({
|
|
1284
1662
|
query,
|
|
1285
1663
|
entityClass: BlogPost,
|
|
@@ -1295,10 +1673,8 @@ describe('queryParser', () => {
|
|
|
1295
1673
|
selector: [
|
|
1296
1674
|
{
|
|
1297
1675
|
type: '|',
|
|
1298
|
-
gt: [
|
|
1299
|
-
|
|
1300
|
-
['mdate', null, '1 month ago'],
|
|
1301
|
-
],
|
|
1676
|
+
'!gt': [['cdate', null, '6 months ago']],
|
|
1677
|
+
gt: [['mdate', null, '1 month ago']],
|
|
1302
1678
|
},
|
|
1303
1679
|
{
|
|
1304
1680
|
type: '!&',
|
|
@@ -1312,7 +1688,7 @@ describe('queryParser', () => {
|
|
|
1312
1688
|
|
|
1313
1689
|
it('parses nested selectors', () => {
|
|
1314
1690
|
const query =
|
|
1315
|
-
'(! [published] <draft> (| cdate>"6 months ago" mdate>"1 month ago"))';
|
|
1691
|
+
'(! [published] <draft> (| -cdate>"6 months ago" mdate>"1 month ago"))';
|
|
1316
1692
|
const [options, ...selectors] = queryParser({
|
|
1317
1693
|
query,
|
|
1318
1694
|
entityClass: BlogPost,
|
|
@@ -1330,10 +1706,8 @@ describe('queryParser', () => {
|
|
|
1330
1706
|
selector: [
|
|
1331
1707
|
{
|
|
1332
1708
|
type: '|',
|
|
1333
|
-
gt: [
|
|
1334
|
-
|
|
1335
|
-
['mdate', null, '1 month ago'],
|
|
1336
|
-
],
|
|
1709
|
+
'!gt': [['cdate', null, '6 months ago']],
|
|
1710
|
+
gt: [['mdate', null, '1 month ago']],
|
|
1337
1711
|
},
|
|
1338
1712
|
],
|
|
1339
1713
|
},
|
|
@@ -1342,7 +1716,7 @@ describe('queryParser', () => {
|
|
|
1342
1716
|
|
|
1343
1717
|
it('parses nested qref clauses', () => {
|
|
1344
1718
|
const query =
|
|
1345
|
-
'categories<{Category parent<{Category id="sort+newsletters"}>}>
|
|
1719
|
+
'categories<{Category parent<{Category list<{List frosting name(favorite)}>}> -parent<{Category id="sort+newsletters"}>}>';
|
|
1346
1720
|
const [options, ...selectors] = queryParser({
|
|
1347
1721
|
query,
|
|
1348
1722
|
entityClass: BlogPost,
|
|
@@ -1352,6 +1726,10 @@ describe('queryParser', () => {
|
|
|
1352
1726
|
class: Category,
|
|
1353
1727
|
defaultFields: ['name'],
|
|
1354
1728
|
},
|
|
1729
|
+
List: {
|
|
1730
|
+
class: List,
|
|
1731
|
+
defaultFields: ['name'],
|
|
1732
|
+
},
|
|
1355
1733
|
},
|
|
1356
1734
|
});
|
|
1357
1735
|
|
|
@@ -1370,6 +1748,33 @@ describe('queryParser', () => {
|
|
|
1370
1748
|
{
|
|
1371
1749
|
type: '&',
|
|
1372
1750
|
qref: [
|
|
1751
|
+
[
|
|
1752
|
+
'parent',
|
|
1753
|
+
[
|
|
1754
|
+
{ class: Category },
|
|
1755
|
+
{
|
|
1756
|
+
type: '&',
|
|
1757
|
+
qref: [
|
|
1758
|
+
[
|
|
1759
|
+
'list',
|
|
1760
|
+
[
|
|
1761
|
+
{ class: List },
|
|
1762
|
+
{
|
|
1763
|
+
type: '&',
|
|
1764
|
+
search: [['name', 'favorite']],
|
|
1765
|
+
},
|
|
1766
|
+
{
|
|
1767
|
+
type: '|',
|
|
1768
|
+
ilike: [['name', '%frosting%']],
|
|
1769
|
+
},
|
|
1770
|
+
],
|
|
1771
|
+
],
|
|
1772
|
+
],
|
|
1773
|
+
},
|
|
1774
|
+
],
|
|
1775
|
+
],
|
|
1776
|
+
],
|
|
1777
|
+
'!qref': [
|
|
1373
1778
|
[
|
|
1374
1779
|
'parent',
|
|
1375
1780
|
[
|
|
@@ -1388,4 +1793,24 @@ describe('queryParser', () => {
|
|
|
1388
1793
|
},
|
|
1389
1794
|
]);
|
|
1390
1795
|
});
|
|
1796
|
+
|
|
1797
|
+
it('handles badly nested qref', () => {
|
|
1798
|
+
const query = 'categories<{Category parent<{Category id="top"}>';
|
|
1799
|
+
const [options, ...selectors] = queryParser({
|
|
1800
|
+
query,
|
|
1801
|
+
entityClass: BlogPost,
|
|
1802
|
+
});
|
|
1803
|
+
|
|
1804
|
+
expect(options).toEqual({
|
|
1805
|
+
class: BlogPost,
|
|
1806
|
+
});
|
|
1807
|
+
|
|
1808
|
+
expect(selectors).toEqual([
|
|
1809
|
+
{
|
|
1810
|
+
type: '&',
|
|
1811
|
+
contain: [['categories', '{Category parent<{Category}']],
|
|
1812
|
+
equal: [['id', 'top']],
|
|
1813
|
+
},
|
|
1814
|
+
]);
|
|
1815
|
+
});
|
|
1391
1816
|
});
|