@travetto/model-query 8.0.0-alpha.25 → 8.0.0-alpha.27
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/package.json +5 -5
- package/src/util/suggest.ts +1 -1
- package/support/test/model.ts +16 -0
- package/support/test/query.ts +66 -80
- package/support/test/suggest.ts +53 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/model-query",
|
|
3
|
-
"version": "8.0.0-alpha.
|
|
3
|
+
"version": "8.0.0-alpha.27",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Datastore abstraction for advanced query support.",
|
|
6
6
|
"keywords": [
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"directory": "module/model-query"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@travetto/di": "^8.0.0-alpha.
|
|
31
|
-
"@travetto/model": "^8.0.0-alpha.
|
|
32
|
-
"@travetto/schema": "^8.0.0-alpha.
|
|
30
|
+
"@travetto/di": "^8.0.0-alpha.22",
|
|
31
|
+
"@travetto/model": "^8.0.0-alpha.25",
|
|
32
|
+
"@travetto/schema": "^8.0.0-alpha.24"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@travetto/test": "^8.0.0-alpha.
|
|
35
|
+
"@travetto/test": "^8.0.0-alpha.23"
|
|
36
36
|
},
|
|
37
37
|
"peerDependenciesMeta": {
|
|
38
38
|
"@travetto/test": {
|
package/src/util/suggest.ts
CHANGED
|
@@ -86,7 +86,7 @@ export class ModelQuerySuggestUtil {
|
|
|
86
86
|
|
|
87
87
|
for (const result of results) {
|
|
88
88
|
let resultValue = result[castKey<T>(parts[0])];
|
|
89
|
-
for (let i = 1; i < parts.length; i += 1) {
|
|
89
|
+
for (let i = 1; i < parts.length && resultValue !== undefined && resultValue !== null; i += 1) {
|
|
90
90
|
resultValue = resultValue[castKey(parts[i])];
|
|
91
91
|
}
|
|
92
92
|
if (Array.isArray(resultValue)) {
|
package/support/test/model.ts
CHANGED
|
@@ -115,3 +115,19 @@ export class PersonFamily implements ModelType {
|
|
|
115
115
|
id: string;
|
|
116
116
|
family?: Family;
|
|
117
117
|
}
|
|
118
|
+
|
|
119
|
+
@Schema()
|
|
120
|
+
export class RecipeIngredient {
|
|
121
|
+
name: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@Schema()
|
|
125
|
+
export class RecipeSection {
|
|
126
|
+
ingredients: RecipeIngredient[] = [];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@Model()
|
|
130
|
+
export class Recipe implements ModelType {
|
|
131
|
+
id: string;
|
|
132
|
+
sections: RecipeSection[] = [];
|
|
133
|
+
}
|
package/support/test/query.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { Suite, Test } from '@travetto/test';
|
|
|
7
7
|
import { BaseModelSuite } from '@travetto/model/support/test/base.ts';
|
|
8
8
|
|
|
9
9
|
import type { ModelQuerySupport } from '../../src/types/query.ts';
|
|
10
|
-
import { Aged, Location, Names, Note, Person, PersonFamily, SimpleList, WithNestedLists, WithNestedNestedLists } from './model.ts';
|
|
10
|
+
import { Aged, Location, Names, Note, Person, PersonFamily, Recipe, SimpleList, WithNestedLists, WithNestedNestedLists } from './model.ts';
|
|
11
11
|
|
|
12
12
|
@Suite()
|
|
13
13
|
export abstract class ModelQuerySuite extends BaseModelSuite<ModelQuerySupport & ModelCrudSupport> {
|
|
@@ -399,28 +399,13 @@ export abstract class ModelQuerySuite extends BaseModelSuite<ModelQuerySupport &
|
|
|
399
399
|
@Test()
|
|
400
400
|
async verifyArrayEmptyVsNot() {
|
|
401
401
|
const service = await this.service;
|
|
402
|
-
await
|
|
403
|
-
tags: ['a', 'b']
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
names: [
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
await service.create(WithNestedLists, {
|
|
411
|
-
names: ['c', 'd'],
|
|
412
|
-
tags: ['e', 'f']
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
await service.create(WithNestedLists, {
|
|
416
|
-
names: ['g', 'h'],
|
|
417
|
-
tags: []
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
await service.create(WithNestedLists, {
|
|
421
|
-
names: [],
|
|
422
|
-
tags: []
|
|
423
|
-
});
|
|
402
|
+
await this.saveAll(WithNestedLists, [
|
|
403
|
+
WithNestedLists.from({ tags: ['a', 'b'] }),
|
|
404
|
+
WithNestedLists.from({ names: ['c', 'd'] }),
|
|
405
|
+
WithNestedLists.from({ names: ['c', 'd'], tags: ['e', 'f'] }),
|
|
406
|
+
WithNestedLists.from({ names: ['g', 'h'], tags: [] }),
|
|
407
|
+
WithNestedLists.from({ names: [], tags: [] })
|
|
408
|
+
]);
|
|
424
409
|
|
|
425
410
|
let total = await service.queryCount(WithNestedLists, {
|
|
426
411
|
where: {
|
|
@@ -428,6 +413,7 @@ export abstract class ModelQuerySuite extends BaseModelSuite<ModelQuerySupport &
|
|
|
428
413
|
}
|
|
429
414
|
});
|
|
430
415
|
assert(total === 3);
|
|
416
|
+
|
|
431
417
|
total = await service.queryCount(WithNestedLists, {
|
|
432
418
|
where: {
|
|
433
419
|
names: { $exists: false }
|
|
@@ -463,35 +449,20 @@ export abstract class ModelQuerySuite extends BaseModelSuite<ModelQuerySupport &
|
|
|
463
449
|
names: { $exists: true }
|
|
464
450
|
}
|
|
465
451
|
});
|
|
466
|
-
|
|
467
452
|
assert(total === 1);
|
|
468
453
|
}
|
|
469
454
|
|
|
470
455
|
@Test()
|
|
471
456
|
async verifyNestedArrayEmptyVsNot() {
|
|
472
457
|
const service = await this.service;
|
|
473
|
-
await service.create(WithNestedNestedLists, {
|
|
474
|
-
tags: ['a', 'b']
|
|
475
|
-
});
|
|
476
|
-
|
|
477
|
-
await service.create(WithNestedNestedLists, {
|
|
478
|
-
sub: { names: ['c', 'd'] }
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
await service.create(WithNestedNestedLists, {
|
|
482
|
-
sub: { names: ['c', 'd'] },
|
|
483
|
-
tags: ['e', 'f']
|
|
484
|
-
});
|
|
485
|
-
|
|
486
|
-
await service.create(WithNestedNestedLists, {
|
|
487
|
-
sub: { names: ['g', 'h'] },
|
|
488
|
-
tags: []
|
|
489
|
-
});
|
|
490
458
|
|
|
491
|
-
await
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
459
|
+
await this.saveAll(WithNestedNestedLists, [
|
|
460
|
+
WithNestedNestedLists.from({ tags: ['a', 'b'] }),
|
|
461
|
+
WithNestedNestedLists.from({ sub: { names: ['c', 'd'] } }),
|
|
462
|
+
WithNestedNestedLists.from({ sub: { names: ['c', 'd'] }, tags: ['e', 'f'] }),
|
|
463
|
+
WithNestedNestedLists.from({ sub: { names: ['g', 'h'] }, tags: [] }),
|
|
464
|
+
WithNestedNestedLists.from({ sub: {}, tags: [] })
|
|
465
|
+
]);
|
|
495
466
|
|
|
496
467
|
let total = await service.queryCount(WithNestedNestedLists, {
|
|
497
468
|
where: {
|
|
@@ -499,6 +470,7 @@ export abstract class ModelQuerySuite extends BaseModelSuite<ModelQuerySupport &
|
|
|
499
470
|
}
|
|
500
471
|
});
|
|
501
472
|
assert(total === 3);
|
|
473
|
+
|
|
502
474
|
total = await service.queryCount(WithNestedNestedLists, {
|
|
503
475
|
where: {
|
|
504
476
|
sub: { names: { $exists: false } }
|
|
@@ -538,36 +510,65 @@ export abstract class ModelQuerySuite extends BaseModelSuite<ModelQuerySupport &
|
|
|
538
510
|
assert(total === 1);
|
|
539
511
|
}
|
|
540
512
|
|
|
513
|
+
@Test('Verify queries on nested arrays of schemas')
|
|
514
|
+
async verifyNestedArraySchemaQuery() {
|
|
515
|
+
const service = await this.service;
|
|
516
|
+
|
|
517
|
+
await this.saveAll(Recipe, [
|
|
518
|
+
Recipe.from({
|
|
519
|
+
sections: [{ ingredients: [{ name: 'garlic' }, { name: 'onion' }] }]
|
|
520
|
+
}),
|
|
521
|
+
Recipe.from({
|
|
522
|
+
sections: [{ ingredients: [{ name: 'paprika' }, { name: 'salt' }] }]
|
|
523
|
+
}),
|
|
524
|
+
Recipe.from({
|
|
525
|
+
sections: [{ ingredients: [{ name: 'garlic' }, { name: 'thyme' }] }]
|
|
526
|
+
})
|
|
527
|
+
]);
|
|
528
|
+
|
|
529
|
+
const matchSingle = await service.query(Recipe, {
|
|
530
|
+
where: {
|
|
531
|
+
sections: { ingredients: { name: 'garlic' } }
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
assert(matchSingle.length === 2);
|
|
535
|
+
|
|
536
|
+
const matchIn = await service.query(Recipe, {
|
|
537
|
+
where: {
|
|
538
|
+
sections: { ingredients: { name: { $in: ['onion', 'salt'] } } }
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
assert(matchIn.length === 2);
|
|
542
|
+
|
|
543
|
+
const matchNotEqual = await service.query(Recipe, {
|
|
544
|
+
where: {
|
|
545
|
+
sections: { ingredients: { name: { $ne: 'garlic' } } }
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
assert(matchNotEqual.length === 1);
|
|
549
|
+
}
|
|
550
|
+
|
|
541
551
|
@Test('Verify array of objects property queries')
|
|
542
552
|
async verifyArrayOfObjectsProperty() {
|
|
543
553
|
const service = await this.service;
|
|
544
554
|
|
|
545
|
-
await
|
|
546
|
-
Note,
|
|
555
|
+
await this.saveAll(Note, [
|
|
547
556
|
Note.from({
|
|
548
557
|
entities: [
|
|
549
558
|
{ id: '1', label: 'one' },
|
|
550
559
|
{ id: '2', label: 'two' }
|
|
551
560
|
]
|
|
552
|
-
})
|
|
553
|
-
);
|
|
554
|
-
|
|
555
|
-
await service.create(
|
|
556
|
-
Note,
|
|
561
|
+
}),
|
|
557
562
|
Note.from({
|
|
558
563
|
entities: [
|
|
559
564
|
{ id: '3', label: 'three' },
|
|
560
565
|
{ id: '4', label: 'four' }
|
|
561
566
|
]
|
|
562
|
-
})
|
|
563
|
-
);
|
|
564
|
-
|
|
565
|
-
await service.create(
|
|
566
|
-
Note,
|
|
567
|
+
}),
|
|
567
568
|
Note.from({
|
|
568
569
|
entities: [{ id: '5', label: 'five' }]
|
|
569
570
|
})
|
|
570
|
-
);
|
|
571
|
+
]);
|
|
571
572
|
|
|
572
573
|
const inResults = await service.query(Note, {
|
|
573
574
|
where: {
|
|
@@ -594,32 +595,17 @@ export abstract class ModelQuerySuite extends BaseModelSuite<ModelQuerySupport &
|
|
|
594
595
|
async verifyNestedObjectArrayProperty() {
|
|
595
596
|
const service = await this.service;
|
|
596
597
|
|
|
597
|
-
await
|
|
598
|
-
PersonFamily,
|
|
598
|
+
await this.saveAll(PersonFamily, [
|
|
599
599
|
PersonFamily.from({
|
|
600
|
-
family: {
|
|
601
|
-
|
|
602
|
-
}
|
|
603
|
-
})
|
|
604
|
-
);
|
|
605
|
-
|
|
606
|
-
await service.create(
|
|
607
|
-
PersonFamily,
|
|
600
|
+
family: { children: [{ name: 'one' }, { name: 'two' }] }
|
|
601
|
+
}),
|
|
608
602
|
PersonFamily.from({
|
|
609
|
-
family: {
|
|
610
|
-
|
|
611
|
-
}
|
|
612
|
-
})
|
|
613
|
-
);
|
|
614
|
-
|
|
615
|
-
await service.create(
|
|
616
|
-
PersonFamily,
|
|
603
|
+
family: { children: [{ name: 'three' }, { name: 'four' }] }
|
|
604
|
+
}),
|
|
617
605
|
PersonFamily.from({
|
|
618
|
-
family: {
|
|
619
|
-
children: [{ name: 'five' }]
|
|
620
|
-
}
|
|
606
|
+
family: { children: [{ name: 'five' }] }
|
|
621
607
|
})
|
|
622
|
-
);
|
|
608
|
+
]);
|
|
623
609
|
|
|
624
610
|
const inResults = await service.query(PersonFamily, {
|
|
625
611
|
where: {
|
package/support/test/suggest.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { Suite, Test } from '@travetto/test';
|
|
|
6
6
|
import { BaseModelSuite } from '@travetto/model/support/test/base.ts';
|
|
7
7
|
|
|
8
8
|
import type { ModelQuerySuggestSupport } from '../../src/types/suggest.ts';
|
|
9
|
-
import { Person } from './model.ts';
|
|
9
|
+
import { Person, WithNestedLists, WithNestedNestedLists } from './model.ts';
|
|
10
10
|
|
|
11
11
|
@Suite()
|
|
12
12
|
export abstract class ModelQuerySuggestSuite extends BaseModelSuite<ModelQuerySuggestSupport & ModelCrudSupport> {
|
|
@@ -27,6 +27,23 @@ export abstract class ModelQuerySuggestSuite extends BaseModelSuite<ModelQuerySu
|
|
|
27
27
|
await this.saveAll(Person, people);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
async #loadNestedLists() {
|
|
31
|
+
await this.saveAll(WithNestedLists, [
|
|
32
|
+
WithNestedLists.from({ tags: ['apple', 'banana', 'apricot'], names: ['alex', 'amber'] }),
|
|
33
|
+
WithNestedLists.from({ tags: ['blueberry', 'avocado'], names: ['bob', 'bill'] }),
|
|
34
|
+
WithNestedLists.from({ tags: ['cherry', 'date'], names: ['charlie'] })
|
|
35
|
+
]);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async #loadNestedNestedLists() {
|
|
39
|
+
await this.saveAll(WithNestedNestedLists, [
|
|
40
|
+
WithNestedNestedLists.from({ tags: ['apple', 'banana'], sub: { names: ['alex', 'amber'] } }),
|
|
41
|
+
WithNestedNestedLists.from({ tags: ['blueberry'], sub: { names: ['avocado', 'bill'] } }),
|
|
42
|
+
WithNestedNestedLists.from({ tags: ['cherry'], sub: { names: ['charlie'] } }),
|
|
43
|
+
WithNestedNestedLists.from({ tags: ['date'] })
|
|
44
|
+
]);
|
|
45
|
+
}
|
|
46
|
+
|
|
30
47
|
@Test('Verify value suggestion')
|
|
31
48
|
async testSuggestion() {
|
|
32
49
|
const service = await this.service;
|
|
@@ -65,4 +82,39 @@ export abstract class ModelQuerySuggestSuite extends BaseModelSuite<ModelQuerySu
|
|
|
65
82
|
assert(suggestedEntities[0] instanceof Person);
|
|
66
83
|
assert(suggestedEntities[1] instanceof Person);
|
|
67
84
|
}
|
|
85
|
+
|
|
86
|
+
@Test('Verify suggestion on string arrays')
|
|
87
|
+
async verifyStringArraySuggestions() {
|
|
88
|
+
const service = await this.service;
|
|
89
|
+
|
|
90
|
+
await this.#loadNestedLists();
|
|
91
|
+
|
|
92
|
+
const suggestedValues = await service.suggestValuesByQuery(WithNestedLists, 'tags', 'ap');
|
|
93
|
+
assert(suggestedValues.length === 2);
|
|
94
|
+
assert(suggestedValues[0] === 'apple');
|
|
95
|
+
assert(suggestedValues[1] === 'apricot');
|
|
96
|
+
|
|
97
|
+
const suggestedEntities = await service.suggestByQuery(WithNestedLists, 'tags', 'ap');
|
|
98
|
+
assert(suggestedEntities.length === 1);
|
|
99
|
+
assert(suggestedEntities[0] instanceof WithNestedLists);
|
|
100
|
+
assert(suggestedEntities[0].tags?.includes('apple'));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@Test('Verify suggestion on nested string arrays')
|
|
104
|
+
async verifyNestedStringArraySuggestions() {
|
|
105
|
+
const service = await this.service;
|
|
106
|
+
|
|
107
|
+
await this.#loadNestedNestedLists();
|
|
108
|
+
|
|
109
|
+
const suggestedValues = await service.suggestValuesByQuery(WithNestedNestedLists, 'sub.names', 'a');
|
|
110
|
+
assert(suggestedValues.length === 3);
|
|
111
|
+
assert(suggestedValues[0] === 'alex');
|
|
112
|
+
assert(suggestedValues[1] === 'amber');
|
|
113
|
+
assert(suggestedValues[2] === 'avocado');
|
|
114
|
+
|
|
115
|
+
const suggestedEntities = await service.suggestByQuery(WithNestedNestedLists, 'sub.names', 'al');
|
|
116
|
+
assert(suggestedEntities.length === 1);
|
|
117
|
+
assert(suggestedEntities[0] instanceof WithNestedNestedLists);
|
|
118
|
+
assert(suggestedEntities[0].sub?.names?.includes('alex'));
|
|
119
|
+
}
|
|
68
120
|
}
|