@travetto/model-query 6.0.1 → 7.0.0-rc.0
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/internal/types.ts +2 -2
- package/src/model/query.ts +11 -11
- package/src/model/where-clause.ts +5 -13
- package/src/util/crud.ts +2 -2
- package/src/util/query.ts +12 -6
- package/src/util/suggest.ts +18 -12
- package/src/verifier.ts +6 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/model-query",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0-rc.0",
|
|
4
4
|
"description": "Datastore abstraction for advanced query support.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"datastore",
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
"directory": "module/model-query"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@travetto/di": "^
|
|
30
|
-
"@travetto/model": "^
|
|
31
|
-
"@travetto/schema": "^
|
|
29
|
+
"@travetto/di": "^7.0.0-rc.0",
|
|
30
|
+
"@travetto/model": "^7.0.0-rc.0",
|
|
31
|
+
"@travetto/schema": "^7.0.0-rc.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@travetto/test": "^
|
|
34
|
+
"@travetto/test": "^7.0.0-rc.0"
|
|
35
35
|
},
|
|
36
36
|
"peerDependenciesMeta": {
|
|
37
37
|
"@travetto/test": {
|
package/src/internal/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SchemaFieldConfig, Point } from '@travetto/schema';
|
|
2
2
|
import { Class, toConcrete } from '@travetto/runtime';
|
|
3
3
|
|
|
4
4
|
const st = (t: string | string[], isArr: boolean = false): Set<string> =>
|
|
@@ -36,7 +36,7 @@ export class TypeUtil {
|
|
|
36
36
|
/**
|
|
37
37
|
* Get declared type of a given field, only for primitive types
|
|
38
38
|
*/
|
|
39
|
-
static getDeclaredType(f:
|
|
39
|
+
static getDeclaredType(f: SchemaFieldConfig | Class): keyof typeof TypeUtil.OPERATORS | undefined {
|
|
40
40
|
const type = 'type' in f ? f.type : f;
|
|
41
41
|
switch (type) {
|
|
42
42
|
case String: return 'string';
|
package/src/model/query.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { WhereClauseRaw,
|
|
1
|
+
import { WhereClauseRaw, RetainQueryPrimitiveFields } from './where-clause.ts';
|
|
2
2
|
|
|
3
3
|
type SelectClauseRaw<T> = {
|
|
4
4
|
[P in keyof T]?:
|
|
5
|
-
T[P] extends object ? SelectClauseRaw<
|
|
5
|
+
T[P] extends object ? SelectClauseRaw<RetainQueryPrimitiveFields<T[P]>> : (1 | 0 | boolean);
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
type GroupClauseRaw<T> = {
|
|
9
|
-
[P in keyof T]?: T[P] extends object ? GroupClauseRaw<
|
|
9
|
+
[P in keyof T]?: T[P] extends object ? GroupClauseRaw<RetainQueryPrimitiveFields<T[P]>> : (1 | 0 | boolean);
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
type SortClauseRaw<T> = {
|
|
13
13
|
[P in keyof T]?:
|
|
14
|
-
T[P] extends object ? SortClauseRaw<
|
|
14
|
+
T[P] extends object ? SortClauseRaw<RetainQueryPrimitiveFields<T[P]>> : 1 | -1;
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
type QueryOptionsRaw<T> = {
|
|
@@ -34,28 +34,28 @@ type PageableModelQueryRaw<T> = ModelQueryRaw<T> & QueryOptionsRaw<T>;
|
|
|
34
34
|
/**
|
|
35
35
|
* Type of a full query
|
|
36
36
|
*/
|
|
37
|
-
export type Query<T> = QueryRaw<
|
|
37
|
+
export type Query<T> = QueryRaw<RetainQueryPrimitiveFields<T>>;
|
|
38
38
|
/**
|
|
39
39
|
* Query with support for pagination (limit, offset)
|
|
40
40
|
*/
|
|
41
|
-
export type PageableModelQuery<T> = PageableModelQueryRaw<
|
|
41
|
+
export type PageableModelQuery<T> = PageableModelQueryRaw<RetainQueryPrimitiveFields<T>>;
|
|
42
42
|
/**
|
|
43
43
|
* Standard query options (limit, offset)
|
|
44
44
|
*/
|
|
45
|
-
export type QueryOptions<T> = QueryOptionsRaw<
|
|
45
|
+
export type QueryOptions<T> = QueryOptionsRaw<RetainQueryPrimitiveFields<T>>;
|
|
46
46
|
/**
|
|
47
47
|
* Select clause
|
|
48
48
|
*/
|
|
49
|
-
export type SelectClause<T> = SelectClauseRaw<
|
|
49
|
+
export type SelectClause<T> = SelectClauseRaw<RetainQueryPrimitiveFields<T>>;
|
|
50
50
|
/**
|
|
51
51
|
* Sort clause
|
|
52
52
|
*/
|
|
53
|
-
export type SortClause<T> = SortClauseRaw<
|
|
53
|
+
export type SortClause<T> = SortClauseRaw<RetainQueryPrimitiveFields<T>>;
|
|
54
54
|
/**
|
|
55
55
|
* Group clause
|
|
56
56
|
*/
|
|
57
|
-
export type GroupClause<T> = GroupClauseRaw<
|
|
57
|
+
export type GroupClause<T> = GroupClauseRaw<RetainQueryPrimitiveFields<T>>;
|
|
58
58
|
/**
|
|
59
59
|
* Model query, requiring a model object
|
|
60
60
|
*/
|
|
61
|
-
export type ModelQuery<T> = ModelQueryRaw<
|
|
61
|
+
export type ModelQuery<T> = ModelQueryRaw<RetainQueryPrimitiveFields<T>>;
|
|
@@ -1,18 +1,10 @@
|
|
|
1
|
-
import type { Primitive, TimeSpan } from '@travetto/runtime';
|
|
1
|
+
import type { Primitive, RetainPrimitiveFields, TimeSpan } from '@travetto/runtime';
|
|
2
2
|
import { Point } from '@travetto/schema';
|
|
3
3
|
|
|
4
4
|
export type QueryPrimitive = Primitive | Point;
|
|
5
5
|
export type QueryPrimitiveArray = QueryPrimitive[];
|
|
6
6
|
export type DistanceUnit = 'mi' | 'm' | 'km' | 'ft' | 'rad';
|
|
7
|
-
|
|
8
|
-
export type ValidFieldNames<T> = {
|
|
9
|
-
[K in keyof T]:
|
|
10
|
-
(T[K] extends (QueryPrimitive | undefined) ? K :
|
|
11
|
-
(T[K] extends (Function | undefined) ? never :
|
|
12
|
-
K))
|
|
13
|
-
}[keyof T];
|
|
14
|
-
|
|
15
|
-
export type RetainFields<T> = Pick<T, ValidFieldNames<T>>;
|
|
7
|
+
export type RetainQueryPrimitiveFields<T> = RetainPrimitiveFields<T, Point>;
|
|
16
8
|
|
|
17
9
|
type General<T> = {
|
|
18
10
|
$eq?: T;
|
|
@@ -38,7 +30,7 @@ type ArrayField<T> =
|
|
|
38
30
|
{ $ne?: T | T[] } |
|
|
39
31
|
{ $all?: T[] } |
|
|
40
32
|
{ $in?: T[] } |
|
|
41
|
-
PropWhereClause<
|
|
33
|
+
PropWhereClause<RetainQueryPrimitiveFields<T>> |
|
|
42
34
|
T | T[];
|
|
43
35
|
|
|
44
36
|
type StringField = { $regex?: RegExp | string };
|
|
@@ -58,7 +50,7 @@ export type PropWhereClause<T> = {
|
|
|
58
50
|
(T[P] extends (Date | undefined) ? (General<Date> | ScalarField<Date> | ComparableField<Date | TimeSpan> | Date) :
|
|
59
51
|
(T[P] extends (Point | undefined) ? (General<Point> | ScalarField<Point> | GeoField | Point) :
|
|
60
52
|
(T[P] extends ((infer U)[] | undefined) ? ArrayField<U> :
|
|
61
|
-
(T[P] extends (object | undefined) ? PropWhereClause<
|
|
53
|
+
(T[P] extends (object | undefined) ? PropWhereClause<RetainQueryPrimitiveFields<T[P]>> : never)))))));
|
|
62
54
|
};
|
|
63
55
|
|
|
64
56
|
/**
|
|
@@ -73,7 +65,7 @@ export type WhereClauseRaw<T> =
|
|
|
73
65
|
/**
|
|
74
66
|
* Full where clause, typed against the input type T
|
|
75
67
|
*/
|
|
76
|
-
export type WhereClause<T> = WhereClauseRaw<
|
|
68
|
+
export type WhereClause<T> = WhereClauseRaw<RetainQueryPrimitiveFields<T>>;
|
|
77
69
|
|
|
78
70
|
/**
|
|
79
71
|
* Provides all the valid string type fields from a given type T
|
package/src/util/crud.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Class, hasFunction } from '@travetto/runtime';
|
|
2
|
-
import { ModelType, ModelCrudSupport,
|
|
2
|
+
import { ModelType, ModelCrudSupport, ModelRegistryIndex } from '@travetto/model';
|
|
3
3
|
|
|
4
4
|
import { ModelQueryCrudSupport } from '../types/crud.ts';
|
|
5
5
|
|
|
@@ -13,7 +13,7 @@ export class ModelQueryCrudUtil {
|
|
|
13
13
|
* Delete all expired
|
|
14
14
|
*/
|
|
15
15
|
static async deleteExpired<T extends ModelType>(svc: ModelQueryCrudSupport & ModelCrudSupport, cls: Class<T>): Promise<number> {
|
|
16
|
-
const expiry = await
|
|
16
|
+
const expiry = await ModelRegistryIndex.getExpiryFieldName(cls);
|
|
17
17
|
const res = await svc.deleteByQuery<ModelType>(cls, {
|
|
18
18
|
where: {
|
|
19
19
|
[expiry]: {
|
package/src/util/query.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Class, AppError, TimeUtil, castTo, hasFunction } from '@travetto/runtime';
|
|
2
|
-
import { ModelType,
|
|
3
|
-
import {
|
|
2
|
+
import { ModelType, NotFoundError, ModelRegistryIndex } from '@travetto/model';
|
|
3
|
+
import { SchemaRegistryIndex } from '@travetto/schema';
|
|
4
4
|
|
|
5
5
|
import { WhereClause, WhereClauseRaw } from '../model/where-clause.ts';
|
|
6
6
|
import { ModelQuerySupport } from '../types/query.ts';
|
|
@@ -56,11 +56,17 @@ export class ModelQueryUtil {
|
|
|
56
56
|
static getWhereClause<T extends ModelType>(cls: Class<T>, q: WhereClause<T> | undefined, checkExpiry = true): WhereClause<T> {
|
|
57
57
|
const clauses: WhereClauseRaw<T>[] = (q ? [q] : []);
|
|
58
58
|
|
|
59
|
-
const
|
|
60
|
-
if (
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
const polymorphicConfig = SchemaRegistryIndex.getDiscriminatedConfig(cls);
|
|
60
|
+
if (polymorphicConfig) {
|
|
61
|
+
clauses.push(castTo(polymorphicConfig.discriminatedBase ? {
|
|
62
|
+
[polymorphicConfig.discriminatedField]: { $in: SchemaRegistryIndex.getDiscriminatedTypes(cls) }
|
|
63
|
+
} : {
|
|
64
|
+
[polymorphicConfig.discriminatedField]: polymorphicConfig.discriminatedType
|
|
65
|
+
}
|
|
66
|
+
));
|
|
63
67
|
}
|
|
68
|
+
|
|
69
|
+
const conf = ModelRegistryIndex.getConfig(cls);
|
|
64
70
|
if (checkExpiry && conf.expiresAt) {
|
|
65
71
|
clauses.push(castTo({
|
|
66
72
|
$or: [
|
package/src/util/suggest.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ModelRegistryIndex, ModelType } from '@travetto/model';
|
|
2
2
|
import { castTo, Class, hasFunction } from '@travetto/runtime';
|
|
3
|
-
import {
|
|
3
|
+
import { SchemaRegistryIndex } from '@travetto/schema';
|
|
4
4
|
|
|
5
5
|
import { PageableModelQuery, Query } from '../model/query.ts';
|
|
6
6
|
import { ValidStringFields, WhereClauseRaw } from '../model/where-clause.ts';
|
|
@@ -27,15 +27,25 @@ export class ModelQuerySuggestUtil {
|
|
|
27
27
|
* Build suggest query on top of query language
|
|
28
28
|
*/
|
|
29
29
|
static getSuggestQuery<T extends ModelType>(cls: Class<T>, field: ValidStringFields<T>, prefix?: string, query?: Query<T>): Query<T> {
|
|
30
|
-
const config = ModelRegistry.get(cls);
|
|
31
30
|
const limit = query?.limit ?? 10;
|
|
32
31
|
const clauses: WhereClauseRaw<ModelType>[] = prefix ? [{ [field]: { $regex: this.getSuggestRegex(prefix) } }] : [];
|
|
32
|
+
const select: Query<T>['select'] = {
|
|
33
|
+
...query?.select
|
|
34
|
+
};
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
clauses.push({
|
|
36
|
+
const polymorphicConfig = SchemaRegistryIndex.getDiscriminatedConfig(cls);
|
|
37
|
+
if (polymorphicConfig) {
|
|
38
|
+
clauses.push({
|
|
39
|
+
[polymorphicConfig.discriminatedField]: polymorphicConfig.discriminatedBase ?
|
|
40
|
+
{ $in: SchemaRegistryIndex.getDiscriminatedTypes(cls) } :
|
|
41
|
+
polymorphicConfig.discriminatedType
|
|
42
|
+
});
|
|
43
|
+
if (query?.select) {
|
|
44
|
+
Object.assign(select, { [polymorphicConfig.discriminatedField]: true });
|
|
45
|
+
}
|
|
37
46
|
}
|
|
38
47
|
|
|
48
|
+
const config = ModelRegistryIndex.getConfig(cls);
|
|
39
49
|
if (config.expiresAt) {
|
|
40
50
|
clauses.push({ [config.expiresAt]: { $gt: new Date() } });
|
|
41
51
|
}
|
|
@@ -47,7 +57,7 @@ export class ModelQuerySuggestUtil {
|
|
|
47
57
|
return {
|
|
48
58
|
where: clauses.length ? (clauses.length > 1 ? { $and: clauses } : clauses[0]) : {},
|
|
49
59
|
limit,
|
|
50
|
-
select
|
|
60
|
+
select
|
|
51
61
|
};
|
|
52
62
|
}
|
|
53
63
|
|
|
@@ -84,10 +94,6 @@ export class ModelQuerySuggestUtil {
|
|
|
84
94
|
* Build suggestion query
|
|
85
95
|
*/
|
|
86
96
|
static getSuggestFieldQuery<T extends ModelType>(cls: Class<T>, field: ValidStringFields<T>, prefix?: string, query?: PageableModelQuery<T>): Query<T> {
|
|
87
|
-
|
|
88
|
-
return this.getSuggestQuery<T>(cls, castTo(field), prefix, {
|
|
89
|
-
...(query ?? {}),
|
|
90
|
-
select: castTo({ [field]: true, ...(config.subType ? { [SchemaRegistry.get(cls).subTypeField]: true } : {}) })
|
|
91
|
-
});
|
|
97
|
+
return this.getSuggestQuery<T>(cls, castTo(field), prefix, query);
|
|
92
98
|
}
|
|
93
99
|
}
|
package/src/verifier.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint @typescript-eslint/no-unused-vars: ["error", { "args": "none"} ] */
|
|
2
|
-
import { DataUtil,
|
|
2
|
+
import { DataUtil, ValidationResultError, ValidationError, SchemaRegistryIndex } from '@travetto/schema';
|
|
3
3
|
import { Class } from '@travetto/runtime';
|
|
4
4
|
|
|
5
5
|
import { ModelQuery, Query, PageableModelQuery } from './model/query.ts';
|
|
@@ -52,7 +52,7 @@ export class QueryVerifier {
|
|
|
52
52
|
* Handle generic clauses
|
|
53
53
|
*/
|
|
54
54
|
static processGenericClause<T>(state: State, cls: Class<T>, val: object, handler: ProcessingHandler): void {
|
|
55
|
-
const view =
|
|
55
|
+
const view = SchemaRegistryIndex.getConfig(cls).fields;
|
|
56
56
|
|
|
57
57
|
if (val === undefined || val === null) {
|
|
58
58
|
state.log('Value cannot be undefined or null');
|
|
@@ -75,23 +75,23 @@ export class QueryVerifier {
|
|
|
75
75
|
continue;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
if (!(key in view
|
|
78
|
+
if (!(key in view)) {
|
|
79
79
|
state.log(`Unknown member ${key} of ${cls.name}`);
|
|
80
80
|
continue;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
// Find field
|
|
84
|
-
const field = view
|
|
84
|
+
const field = view[key];
|
|
85
85
|
const op = TypeUtil.getDeclaredType(field);
|
|
86
86
|
|
|
87
87
|
// If a simple operation
|
|
88
88
|
if (op) {
|
|
89
|
-
handler.onSimpleType(state.extend(key), op, value, field.array);
|
|
89
|
+
handler.onSimpleType(state.extend(key), op, value, field.array ?? false);
|
|
90
90
|
} else {
|
|
91
91
|
// Otherwise recurse
|
|
92
92
|
const subCls = field.type;
|
|
93
93
|
const subVal = value;
|
|
94
|
-
if (handler.onComplexType && handler.onComplexType(state, subCls, subVal, field.array)) {
|
|
94
|
+
if (handler.onComplexType && handler.onComplexType(state, subCls, subVal, field.array ?? false)) {
|
|
95
95
|
continue;
|
|
96
96
|
}
|
|
97
97
|
this.processGenericClause(state.extend(key), subCls, subVal, handler);
|