@travetto/model-indexed 8.0.0-alpha.16 → 8.0.0-alpha.19

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/README.md CHANGED
@@ -136,7 +136,7 @@ export const specificOrders = keyedIndex(Order, {
136
136
  ```
137
137
 
138
138
  ## Using Indexes
139
- Model services that implement [ModelIndexedSupport](https://github.com/travetto/travetto/tree/main/module/model-indexed/src/types/service.ts#L15) allow you to query using the indexes you've defined.
139
+ Model services that implement [ModelIndexedSupport](https://github.com/travetto/travetto/tree/main/module/model-indexed/src/types/service.ts#L16) allow you to query using the indexes you've defined.
140
140
 
141
141
  ### Service Interface
142
142
 
@@ -216,7 +216,7 @@ export interface ModelIndexedSupport extends ModelBasicSupport {
216
216
  pageByIndex<
217
217
  T extends ModelType,
218
218
  S extends SortedIndexSelection<T>,
219
- K extends KeyedIndexSelection<T>
219
+ K extends KeyedIndexSelection<T>,
220
220
  >(cls: Class<T>, idx: SortedIndex<T, K, S>, body: KeyedIndexBody<T, K>, options?: ModelPageOptions): Promise<ModelPageResult<T>>;
221
221
 
222
222
  /**
@@ -232,8 +232,26 @@ export interface ModelIndexedSupport extends ModelBasicSupport {
232
232
  listByIndex<
233
233
  T extends ModelType,
234
234
  S extends SortedIndexSelection<T>,
235
- K extends KeyedIndexSelection<T>
235
+ K extends KeyedIndexSelection<T>,
236
236
  >(cls: Class<T>, idx: SortedIndex<T, K, S>, body: KeyedIndexBody<T, K>, options?: ModelListOptions): AsyncIterable<T[]>;
237
+
238
+ /**
239
+ * Suggest entities by ranged index as defined by fields of idx and a prefix
240
+ *
241
+ * Note: Limit is generally honored, but can vary depending on the underlying storage implementation.
242
+ *
243
+ * @param cls The type to search by
244
+ * @param idx The index to search against
245
+ * @param body The payload of fields needed to search
246
+ * @param prefix The prefix to use for suggesting entities
247
+ * @param options The configuration for pagination
248
+ */
249
+ suggestByIndex<
250
+ T extends ModelType,
251
+ S extends SortedIndexSelection<T>,
252
+ K extends KeyedIndexSelection<T>,
253
+ B extends SortedIndexSelectionType<T, S> & string
254
+ >(cls: Class<T>, idx: SortedIndex<T, K, S>, body: KeyedIndexBody<T, K>, prefix: B, options?: ModelIndexedSearchOptions): Promise<T[]>;
237
255
  }
238
256
  ```
239
257
 
@@ -383,7 +401,7 @@ export async function listWithFilterExample(modelService: ModelIndexedSupport) {
383
401
  ```
384
402
 
385
403
  ## Integration
386
- Index registration happens automatically when models are decorated with [@Model](https://github.com/travetto/travetto/tree/main/module/model/src/registry/decorator.ts#L14). Model services like [Memory Model Support](https://github.com/travetto/travetto/tree/main/module/model-memory#readme "Memory backing for the travetto model module."), [MongoDB Model Support](https://github.com/travetto/travetto/tree/main/module/model-mongo#readme "Mongo backing for the travetto model module."), and [SQL Model Service](https://github.com/travetto/travetto/tree/main/module/model-sql#readme "SQL backing for the travetto model module, with real-time modeling support for SQL schemas.") implement the [ModelIndexedSupport](https://github.com/travetto/travetto/tree/main/module/model-indexed/src/types/service.ts#L15) interface to provide indexed access.
404
+ Index registration happens automatically when models are decorated with [@Model](https://github.com/travetto/travetto/tree/main/module/model/src/registry/decorator.ts#L14). Model services like [Memory Model Support](https://github.com/travetto/travetto/tree/main/module/model-memory#readme "Memory backing for the travetto model module."), [MongoDB Model Support](https://github.com/travetto/travetto/tree/main/module/model-mongo#readme "Mongo backing for the travetto model module."), and [SQL Model Service](https://github.com/travetto/travetto/tree/main/module/model-sql#readme "SQL backing for the travetto model module, with real-time modeling support for SQL schemas.") implement the [ModelIndexedSupport](https://github.com/travetto/travetto/tree/main/module/model-indexed/src/types/service.ts#L16) interface to provide indexed access.
387
405
 
388
406
  ### Reading Registry Information
389
407
  You can access registered indexes via [ModelRegistryIndex](https://github.com/travetto/travetto/tree/main/module/model/src/registry/registry-index.ts#L12) at runtime:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/model-indexed",
3
- "version": "8.0.0-alpha.16",
3
+ "version": "8.0.0-alpha.19",
4
4
  "type": "module",
5
5
  "description": "Basic indexing support for model sources that support it.",
6
6
  "keywords": [
@@ -26,13 +26,13 @@
26
26
  "directory": "module/model-indexed"
27
27
  },
28
28
  "dependencies": {
29
- "@travetto/model": "^8.0.0-alpha.14",
30
- "@travetto/registry": "^8.0.0-alpha.13",
31
- "@travetto/schema": "^8.0.0-alpha.14"
29
+ "@travetto/model": "^8.0.0-alpha.17",
30
+ "@travetto/registry": "^8.0.0-alpha.16",
31
+ "@travetto/schema": "^8.0.0-alpha.17"
32
32
  },
33
33
  "peerDependencies": {
34
- "@travetto/cli": "^8.0.0-alpha.19",
35
- "@travetto/test": "^8.0.0-alpha.13"
34
+ "@travetto/cli": "^8.0.0-alpha.22",
35
+ "@travetto/test": "^8.0.0-alpha.16"
36
36
  },
37
37
  "peerDependenciesMeta": {
38
38
  "@travetto/cli": {
package/src/computed.ts CHANGED
@@ -2,8 +2,7 @@ import type { ModelType } from '@travetto/model';
2
2
  import { castTo, type Any } from '@travetto/runtime';
3
3
 
4
4
  import {
5
- type KeyedIndexSelection, type SortedIndexSelection, type AllIndexes, type KeyedIndexBody,
6
- type FullKeyedIndexBody, type TemplateValue, type TemplatePart
5
+ type AllIndexes, type KeyedIndexBody, type FullKeyedIndexBody, type TemplateValue, type TemplatePart
7
6
  } from './types/indexes.ts';
8
7
  import { IndexedFieldError } from './types/error.ts';
9
8
 
@@ -67,8 +66,8 @@ type Body<T extends ModelType> = KeyedIndexBody<T, Any> | FullKeyedIndexBody<T,
67
66
  type IndexProcessConfig<T = {}> = T & { keyed?: boolean, sort?: boolean };
68
67
 
69
68
  export class ModelIndexedComputedIndex<T extends ModelType> {
70
- static get<T extends ModelType, K extends KeyedIndexSelection<T>, S extends SortedIndexSelection<T>>(
71
- idx: AllIndexes<T, K, S>,
69
+ static get<T extends ModelType>(
70
+ idx: AllIndexes<T>,
72
71
  body: Body<T>,
73
72
  ): ModelIndexedComputedIndex<T> {
74
73
  return new ModelIndexedComputedIndex(idx, body);
@@ -85,7 +84,8 @@ export class ModelIndexedComputedIndex<T extends ModelType> {
85
84
  ) {
86
85
  this.idx = idx;
87
86
  this.keyedParts = buildIndexParts(idx.keyTemplate, castTo(body));
88
- this.sortParts = buildIndexParts(idx.sortTemplate, castTo(body), value => typeof value === 'number' || value instanceof Date);
87
+ this.sortParts = buildIndexParts(idx.sortTemplate, castTo(body),
88
+ value => typeof value === 'number' || value instanceof Date || typeof value === 'string');
89
89
  if ('id' in body && typeof body.id === 'string') {
90
90
  this.idPart = { path: ['id'], value: body.id, state: body.id === null || body.id === undefined ? 'empty' : 'found', templateValue: true };
91
91
  }
@@ -112,13 +112,15 @@ export class ModelIndexedComputedIndex<T extends ModelType> {
112
112
  return parts.map(({ value }) => value).map(value => `${value}`).join(sep);
113
113
  }
114
114
 
115
- getSort(): number {
115
+ getSort(): number | string {
116
116
  const { value } = this.sortParts[0] ?? {};
117
117
  const direction = (this.sortParts[0]?.templateValue ?? 1);
118
118
  if (value instanceof Date) {
119
119
  return value.getTime() * direction;
120
120
  } else if (typeof value === 'number') {
121
121
  return value * direction;
122
+ } else if (typeof value === 'string') {
123
+ return value;
122
124
  } else {
123
125
  return 0;
124
126
  }
@@ -1,19 +1,30 @@
1
1
  import type { ModelType, IndexConfig } from '@travetto/model';
2
2
  import { type IntrinsicType, type Any, type DeepPartial } from '@travetto/runtime';
3
3
 
4
- type TypeProjection<T, V> = {
4
+ type SortScalar = string | number | Date;
5
+
6
+ type TypeProjection<T, V, B = IntrinsicType> = {
5
7
  [P in keyof T]?:
6
- (T[P] extends (IntrinsicType | undefined) ? (V | undefined) :
8
+ (T[P] extends (B | undefined) ? (V | undefined) :
7
9
  (T[P] extends Any[] ?
8
- (TypeProjection<T[P][number], V> | null | undefined)[] :
9
- TypeProjection<T[P], V>)
10
+ (TypeProjection<T[P][number], V, B> | null | undefined)[] :
11
+ TypeProjection<T[P], V, B>)
10
12
  );
11
13
  };
12
14
 
15
+ export type SortedIndexSelectionType<T, S> =
16
+ (T extends SortScalar ? T :
17
+ (T extends Any[] ? SortedIndexSelectionType<T[number], S> :
18
+ (S extends object ? (
19
+ (T extends object ?
20
+ { [K in keyof S]: K extends keyof T ? SortedIndexSelectionType<T[K], S[K]> : never }[keyof S] :
21
+ never
22
+ )) : never)));
23
+
13
24
  export type KeyedIndexSelection<T extends ModelType> = TypeProjection<T, true>;
14
25
  export type SortedIndexSelection<T extends ModelType> = TypeProjection<T, 1 | -1>;
15
26
 
16
- export type KeyedIndexBody<T, K> = {
27
+ export type KeyedIndexBody<T, K = Any> = {
17
28
  [P in keyof K]: (P extends keyof T ?
18
29
  (K[P] extends true | 1 | -1 ? T[P] :
19
30
  (T[P] extends Any[] | null | undefined ? T[P] :
@@ -52,8 +63,8 @@ export type TemplatePart<T extends TemplateValue = TemplateValue> = { path: stri
52
63
 
53
64
  export interface KeyedIndex<
54
65
  T extends ModelType,
55
- K extends KeyedIndexSelection<T>,
56
- S extends SortedIndexSelection<T>
66
+ K extends KeyedIndexSelection<T> = Any,
67
+ S extends SortedIndexSelection<T> = Any,
57
68
  > extends IndexConfig<'indexed:keyed'> {
58
69
  key: K;
59
70
  sort: S;
@@ -64,8 +75,8 @@ export interface KeyedIndex<
64
75
 
65
76
  export interface SortedIndex<
66
77
  T extends ModelType,
67
- K extends KeyedIndexSelection<T>,
68
- S extends SortedIndexSelection<T>
78
+ K extends KeyedIndexSelection<T> = Any,
79
+ S extends SortedIndexSelection<T> = Any
69
80
  > extends IndexConfig<'indexed:sorted'> {
70
81
  key: K;
71
82
  sort: S;
@@ -76,12 +87,13 @@ export interface SortedIndex<
76
87
  export type SingleItemIndex<
77
88
  T extends ModelType,
78
89
  K extends KeyedIndexSelection<T> = Any,
79
- S extends SortedIndexSelection<T> = Any
90
+ S extends SortedIndexSelection<T> = Any,
80
91
  > = KeyedIndex<T, K, S> | SortedIndex<T, K, S>;
81
92
 
82
93
  export type AllIndexes<
83
94
  T extends ModelType,
84
95
  K extends KeyedIndexSelection<T> = Any,
85
- S extends SortedIndexSelection<T> = Any
96
+ S extends SortedIndexSelection<T> = Any,
86
97
  > = KeyedIndex<T, K, S> | SortedIndex<T, K, S>;
87
98
 
99
+
package/src/types/list.ts CHANGED
@@ -1,8 +1,11 @@
1
1
  import type { ModelType } from '@travetto/model';
2
2
 
3
- export interface ModelPageOptions<O = string> {
3
+ export interface ModelIndexedSearchOptions {
4
4
  batchSizeHint?: number;
5
5
  limit?: number;
6
+ }
7
+
8
+ export interface ModelPageOptions<O = string> extends ModelIndexedSearchOptions {
6
9
  offset?: O;
7
10
  }
8
11
 
@@ -3,9 +3,10 @@ import type { Class } from '@travetto/runtime';
3
3
 
4
4
  import type {
5
5
  KeyedIndexSelection, KeyedIndexBody, SortedIndexSelection, SortedIndex,
6
- SingleItemIndex, FullKeyedIndexBody, FullKeyedIndexWithPartialBody
6
+ SingleItemIndex, FullKeyedIndexBody, FullKeyedIndexWithPartialBody,
7
+ SortedIndexSelectionType
7
8
  } from './indexes.ts';
8
- import type { ModelPageOptions, ModelPageResult } from './list.ts';
9
+ import type { ModelIndexedSearchOptions, ModelPageOptions, ModelPageResult } from './list.ts';
9
10
 
10
11
  /**
11
12
  * Support for simple indexed activity
@@ -86,7 +87,7 @@ export interface ModelIndexedSupport extends ModelBasicSupport {
86
87
  pageByIndex<
87
88
  T extends ModelType,
88
89
  S extends SortedIndexSelection<T>,
89
- K extends KeyedIndexSelection<T>
90
+ K extends KeyedIndexSelection<T>,
90
91
  >(cls: Class<T>, idx: SortedIndex<T, K, S>, body: KeyedIndexBody<T, K>, options?: ModelPageOptions): Promise<ModelPageResult<T>>;
91
92
 
92
93
  /**
@@ -102,6 +103,24 @@ export interface ModelIndexedSupport extends ModelBasicSupport {
102
103
  listByIndex<
103
104
  T extends ModelType,
104
105
  S extends SortedIndexSelection<T>,
105
- K extends KeyedIndexSelection<T>
106
+ K extends KeyedIndexSelection<T>,
106
107
  >(cls: Class<T>, idx: SortedIndex<T, K, S>, body: KeyedIndexBody<T, K>, options?: ModelListOptions): AsyncIterable<T[]>;
108
+
109
+ /**
110
+ * Suggest entities by ranged index as defined by fields of idx and a prefix
111
+ *
112
+ * Note: Limit is generally honored, but can vary depending on the underlying storage implementation.
113
+ *
114
+ * @param cls The type to search by
115
+ * @param idx The index to search against
116
+ * @param body The payload of fields needed to search
117
+ * @param prefix The prefix to use for suggesting entities
118
+ * @param options The configuration for pagination
119
+ */
120
+ suggestByIndex<
121
+ T extends ModelType,
122
+ S extends SortedIndexSelection<T>,
123
+ K extends KeyedIndexSelection<T>,
124
+ B extends SortedIndexSelectionType<T, S> & string
125
+ >(cls: Class<T>, idx: SortedIndex<T, K, S>, body: KeyedIndexBody<T, K>, prefix: B, options?: ModelIndexedSearchOptions): Promise<T[]>;
107
126
  }
package/src/util.ts CHANGED
@@ -59,4 +59,11 @@ export class ModelIndexedUtil {
59
59
  body.id = id;
60
60
  return await service.update(cls, castTo(body));
61
61
  }
62
+
63
+ /**
64
+ * Build regex for suggesting
65
+ */
66
+ static getSuggestRegex(prefix?: string): RegExp {
67
+ return prefix ? new RegExp(`^${prefix}`, 'i') : /./;
68
+ }
62
69
  }
@@ -2,91 +2,18 @@ import assert from 'node:assert';
2
2
  import timers from 'node:timers/promises';
3
3
 
4
4
  import { Suite, Test } from '@travetto/test';
5
- import { Schema } from '@travetto/schema';
6
5
  import { castTo, TimeUtil } from '@travetto/runtime';
7
- import { ExistsError, Model, NotFoundError } from '@travetto/model';
6
+ import { ExistsError, ModelBulkUtil, NotFoundError } from '@travetto/model';
8
7
  import { BaseModelSuite } from '@travetto/model/support/test/base.ts';
9
8
 
10
9
  import type { ModelIndexedSupport } from '../../src/types/service.ts';
11
- import { keyedIndex, sortedIndex, uniqueIndex } from '../../src/indexes.ts';
12
10
  import { IndexedFieldError } from '../../src/types/error.ts';
13
11
 
14
- @Model('index_user')
15
- class User {
16
- id: string;
17
- name: string;
18
- }
19
-
20
- const userNameIndex = keyedIndex(User, {
21
- name: 'userName',
22
- key: { name: true }
23
- });
24
-
25
- @Model('index_unique_user')
26
- class UniqueUser {
27
- id: string;
28
- name: string;
29
- }
30
-
31
- const userUniqueNameIndex = uniqueIndex(UniqueUser, {
32
- name: 'userUniqueName',
33
- key: { name: true }
34
- });
35
-
36
- @Model('index_user_2')
37
- class User2 {
38
- id: string;
39
- name: string;
40
- }
41
-
42
- @Model()
43
- class User3 {
44
- id: string;
45
- name: string;
46
- age: number;
47
- color?: string;
48
- }
49
-
50
- const userAgeIndex = sortedIndex(User3, {
51
- name: 'userAge',
52
- key: { name: true },
53
- sort: { age: 1 }
54
- });
55
- const userAgeReversedIndex = sortedIndex(User3, {
56
- name: 'userAgeReverse',
57
- key: { name: true },
58
- sort: { age: -1 }
59
- });
60
- const userAgeNoKeyIndex = sortedIndex(User3, {
61
- name: 'userAgeNoKey',
62
- key: {},
63
- sort: { age: 1 }
64
- });
65
-
66
- @Schema()
67
- class Child {
68
- name: string;
69
- age: number;
70
- }
71
-
72
- @Model()
73
- class User4 {
74
- id: string;
75
- createdDate?: Date = new Date();
76
- color: string;
77
- child: Child;
78
- }
79
-
80
- const childAgeIndex = sortedIndex(User4, {
81
- name: 'childAge',
82
- key: { child: { name: true } },
83
- sort: { child: { age: 1 } }
84
- });
85
- const nameCreatedIndex = sortedIndex(User4, {
86
- name: 'nameCreated',
87
- key: { child: { name: true } },
88
- sort: { createdDate: 1 }
89
- });
12
+ import { SUGGEST_DATA, SuggestItem, suggestSort } from './models/suggest.ts';
13
+ import {
14
+ childAgeIndex, nameCreatedIndex, UniqueUser, User, User2, User3, User4, userAgeIndex,
15
+ userAgeNoKeyIndex, userAgeReversedIndex, userNameIndex, userUniqueNameIndex
16
+ } from './models/indexed.ts';
90
17
 
91
18
  @Suite()
92
19
  export abstract class ModelIndexedSuite extends BaseModelSuite<ModelIndexedSupport> {
@@ -95,6 +22,17 @@ export abstract class ModelIndexedSuite extends BaseModelSuite<ModelIndexedSuppo
95
22
  supportsDeepIndexes = true;
96
23
  supportsUniqueIndexes = true;
97
24
 
25
+ async #seed(names: string[]): Promise<void> {
26
+ const service = await this.service;
27
+ if (ModelBulkUtil.isSupported(service)) {
28
+ await service.processBulk(SuggestItem, names.map(name => ({ insert: { name } })));
29
+ } else {
30
+ for (const item of names) {
31
+ await service.create(SuggestItem, SuggestItem.from({ name: item }));
32
+ }
33
+ }
34
+ }
35
+
98
36
  @Test()
99
37
  async writeAndRead() {
100
38
  const service = await this.service;
@@ -424,4 +362,40 @@ export abstract class ModelIndexedSuite extends BaseModelSuite<ModelIndexedSuppo
424
362
  assert(found.length === 1);
425
363
  }
426
364
  }
365
+
366
+ @Test('suggestByIndex returns items matching prefix')
367
+ async testSuggestSearchBasic() {
368
+ const service = await this.service;
369
+
370
+ await this.#seed(SUGGEST_DATA);
371
+
372
+ const results = await service.suggestByIndex(SuggestItem, suggestSort, {}, 'ap', { limit: 10 });
373
+
374
+ assert(results.length === 10);
375
+ assert(results.every(r => r.name.startsWith('ap')));
376
+ }
377
+
378
+ @Test('suggestByIndex returns empty array when no items match prefix')
379
+ async testSuggestSearchNoMatch() {
380
+ const service = await this.service;
381
+
382
+ await this.#seed(SUGGEST_DATA);
383
+
384
+ const results = await service.suggestByIndex(SuggestItem, suggestSort, {}, 'zzz');
385
+
386
+ assert(results.length === 0);
387
+ }
388
+
389
+ @Test('suggestByIndex respects limit option')
390
+ async testSuggestSearchLimit() {
391
+ const service = await this.service;
392
+
393
+ await this.#seed(SUGGEST_DATA);
394
+
395
+ const results = await service.suggestByIndex(SuggestItem, suggestSort, {}, 'ba', { limit: 5 });
396
+
397
+ assert(results.length === 5);
398
+ assert(/^ba/.test(results[0].name));
399
+ assert(results.every(r => r.name.startsWith('ba')));
400
+ }
427
401
  }
@@ -0,0 +1,82 @@
1
+ import { Model } from '@travetto/model';
2
+ import { Schema } from '@travetto/schema';
3
+
4
+ import { keyedIndex, sortedIndex, uniqueIndex } from '../../../src/indexes.ts';
5
+
6
+ @Model('index_user')
7
+ export class User {
8
+ id: string;
9
+ name: string;
10
+ }
11
+
12
+ export const userNameIndex = keyedIndex(User, {
13
+ name: 'userName',
14
+ key: { name: true }
15
+ });
16
+
17
+ @Model('index_unique_user')
18
+ export class UniqueUser {
19
+ id: string;
20
+ name: string;
21
+ }
22
+
23
+ export const userUniqueNameIndex = uniqueIndex(UniqueUser, {
24
+ name: 'userUniqueName',
25
+ key: { name: true }
26
+ });
27
+
28
+ @Model('index_user_2')
29
+ export class User2 {
30
+ id: string;
31
+ name: string;
32
+ }
33
+
34
+ @Model()
35
+ export class User3 {
36
+ id: string;
37
+ name: string;
38
+ age: number;
39
+ color?: string;
40
+ }
41
+
42
+ export const userAgeIndex = sortedIndex(User3, {
43
+ name: 'userAge',
44
+ key: { name: true },
45
+ sort: { age: 1 }
46
+ });
47
+ export const userAgeReversedIndex = sortedIndex(User3, {
48
+ name: 'userAgeReverse',
49
+ key: { name: true },
50
+ sort: { age: -1 }
51
+ });
52
+ export const userAgeNoKeyIndex = sortedIndex(User3, {
53
+ name: 'userAgeNoKey',
54
+ key: {},
55
+ sort: { age: 1 }
56
+ });
57
+
58
+ @Schema()
59
+ export class Child {
60
+ name: string;
61
+ age: number;
62
+ }
63
+
64
+ @Model()
65
+ export class User4 {
66
+ id: string;
67
+ createdDate?: Date = new Date();
68
+ color: string;
69
+ child: Child;
70
+ }
71
+
72
+ export const childAgeIndex = sortedIndex(User4, {
73
+ name: 'childAge',
74
+ key: { child: { name: true } },
75
+ sort: { child: { age: 1 } }
76
+ });
77
+
78
+ export const nameCreatedIndex = sortedIndex(User4, {
79
+ name: 'nameCreated',
80
+ key: { child: { name: true } },
81
+ sort: { createdDate: 1 }
82
+ });
@@ -0,0 +1,52 @@
1
+ import { Model } from '@travetto/model';
2
+ import { sortedIndex } from '../../../src/indexes.ts';
3
+
4
+ // 60 'ap'-prefixed names, 60 'ba'-prefixed names, 20 'ch'-prefixed names = 140 total
5
+ const AP_NAMES = [
6
+ 'apple', 'apricot', 'apostle', 'apathy', 'apex', 'apiece', 'aplomb', 'apnea',
7
+ 'apollo', 'apparel', 'appeal', 'appear', 'append', 'apple2', 'applet', 'apply',
8
+ 'appoint', 'appraise', 'approve', 'aptitude', 'aptly', 'aport', 'apogee', 'apron',
9
+ 'apse', 'apt', 'aped', 'aper', 'apes', 'aphis', 'apia', 'apian',
10
+ 'apiary', 'apical', 'apices', 'apiece2', 'apish', 'apism', 'aply', 'apneal',
11
+ 'apostate', 'apothegm', 'appease', 'appetize', 'applaud', 'applause', 'apple3', 'apple4',
12
+ 'apple5', 'apple6', 'apple7', 'apple8', 'apple9', 'apple10', 'apple11', 'apple12',
13
+ 'apple13', 'apple14', 'apple15', 'apple16',
14
+ ];
15
+
16
+ const BA_NAMES = [
17
+ 'banana', 'bamboo', 'banjo', 'bandit', 'banner', 'banyan', 'barley', 'barrel',
18
+ 'basil', 'basket', 'bassoon', 'bathe', 'battle', 'bayou', 'bazaar', 'babble',
19
+ 'badger', 'baffle', 'ballad', 'ballet', 'ballot', 'balm', 'bamboo2', 'bandage',
20
+ 'bangle', 'banter', 'barb', 'bard', 'bargain', 'bark', 'barn', 'barrage',
21
+ 'barrier', 'baste', 'batch', 'bathe2', 'baton', 'batter', 'beacon', 'beak',
22
+ 'balance', 'bale', 'baleful', 'balk', 'ballast', 'bane', 'banish', 'bank',
23
+ 'bankroll', 'bare', 'barely', 'barren', 'barricade', 'bay', 'baying', 'bayonet',
24
+ 'bazooka', 'backpack', 'backstop', 'badminton',
25
+ ];
26
+
27
+ const CH_NAMES = [
28
+ 'cherry', 'citrus', 'charm', 'chair', 'chalk', 'chance', 'change', 'channel',
29
+ 'chant', 'chapel', 'chapter', 'charge', 'chart', 'chase', 'chasm', 'cheap',
30
+ 'cheer', 'chess', 'chest', 'chime',
31
+ ];
32
+
33
+ export const SUGGEST_DATA = [
34
+ ...AP_NAMES,
35
+ ...BA_NAMES,
36
+ ...CH_NAMES,
37
+ ];
38
+
39
+ @Model('suggestItem')
40
+ export class SuggestItem {
41
+ id: string;
42
+ name: string;
43
+ age?: number;
44
+ }
45
+
46
+ export const suggestSort = sortedIndex(SuggestItem, {
47
+ name: 'sortByName',
48
+ key: {},
49
+ sort: {
50
+ name: 1
51
+ }
52
+ });
@@ -1,7 +1,6 @@
1
1
  import assert from 'node:assert';
2
2
 
3
3
  import { Suite, Test } from '@travetto/test';
4
- import { castTo } from '@travetto/runtime';
5
4
  import { Discriminated } from '@travetto/schema';
6
5
  import { Model, NotFoundError, SubTypeNotSupportedError } from '@travetto/model';
7
6
 
@@ -45,7 +44,7 @@ export abstract class ModelIndexedPolymorphismSuite extends BaseModelSuite<Model
45
44
 
46
45
  @Test('Polymorphic index', { skip: BaseModelSuite.ifNot(ModelIndexedUtil.isSupported) })
47
46
  async polymorphicIndexGet() {
48
- const service: ModelIndexedSupport = castTo(await this.service);
47
+ const service = await this.service;
49
48
  const now = 30;
50
49
  const [doc, fire, eng] = [
51
50
  IndexedDoctor.from({ name: 'bob', specialty: 'feet', age: now }),
@@ -53,7 +52,7 @@ export abstract class ModelIndexedPolymorphismSuite extends BaseModelSuite<Model
53
52
  IndexedEngineer.from({ name: 'cob', major: 'oranges', age: now })
54
53
  ];
55
54
 
56
- await this.saveAll(IndexedWorker, [doc, fire, eng]);
55
+ const updated = await this.saveAll(IndexedWorker, [doc, fire, eng]);
57
56
 
58
57
  const result = await service.getByIndex(IndexedWorker, workerNameIndex, {
59
58
  age: now,
@@ -75,7 +74,7 @@ export abstract class ModelIndexedPolymorphismSuite extends BaseModelSuite<Model
75
74
 
76
75
  @Test('Polymorphic index', { skip: BaseModelSuite.ifNot(ModelIndexedUtil.isSupported) })
77
76
  async polymorphicIndexDelete() {
78
- const service: ModelIndexedSupport = castTo(await this.service);
77
+ const service = await this.service;
79
78
  const now = 30;
80
79
  const [doc, fire, eng] = [
81
80
  IndexedDoctor.from({ name: 'bob', specialty: 'feet', age: now }),