@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/model-query",
3
- "version": "8.0.0-alpha.25",
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.21",
31
- "@travetto/model": "^8.0.0-alpha.24",
32
- "@travetto/schema": "^8.0.0-alpha.23"
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.22"
35
+ "@travetto/test": "^8.0.0-alpha.23"
36
36
  },
37
37
  "peerDependenciesMeta": {
38
38
  "@travetto/test": {
@@ -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)) {
@@ -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
+ }
@@ -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 service.create(WithNestedLists, {
403
- tags: ['a', 'b']
404
- });
405
-
406
- await service.create(WithNestedLists, {
407
- names: ['c', 'd']
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 service.create(WithNestedNestedLists, {
492
- sub: {},
493
- tags: []
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 service.create(
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 service.create(
598
- PersonFamily,
598
+ await this.saveAll(PersonFamily, [
599
599
  PersonFamily.from({
600
- family: {
601
- children: [{ name: 'one' }, { name: 'two' }]
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
- children: [{ name: 'three' }, { name: 'four' }]
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: {
@@ -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
  }