@ballistix.digital/odata-query-builder 0.9.0 → 0.11.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/dist/index.d.ts +4 -4
- package/dist/index.js.map +1 -1
- package/dist/module/query/domain/chain/chain.model.d.ts +32 -12
- package/dist/module/query/domain/chain/expandChain.model.d.ts +28 -13
- package/dist/module/query/domain/chain/itemChain.model.d.ts +8 -5
- package/dist/module/query/domain/exceptionDetail.model.d.ts +3 -2
- package/dist/module/query/domain/exceptionDetail.model.js +3 -2
- package/dist/module/query/domain/exceptionDetail.model.js.map +1 -1
- package/dist/module/query/domain/filter/dateExpr.model.d.ts +1 -1
- package/dist/module/query/domain/filter/node.model.d.ts +3 -2
- package/dist/module/query/domain/filter/node.model.js +3 -2
- package/dist/module/query/domain/filter/node.model.js.map +1 -1
- package/dist/module/query/domain/filter/scope.model.d.ts +24 -10
- package/dist/module/query/domain/queryState.model.d.ts +3 -3
- package/dist/module/query/exception/invalidFilter.exception.js +4 -0
- package/dist/module/query/exception/invalidFilter.exception.js.map +1 -1
- package/dist/module/query/exception/queryBuilder.exception.d.ts +4 -1
- package/dist/module/query/exception/queryBuilder.exception.js +4 -1
- package/dist/module/query/exception/queryBuilder.exception.js.map +1 -1
- package/dist/module/query/exception/reservedName.exception.js +4 -4
- package/dist/module/query/exception/reservedName.exception.js.map +1 -1
- package/dist/module/query/service/emit/emit.service.d.ts +5 -3
- package/dist/module/query/service/emit/emit.service.js.map +1 -1
- package/dist/module/query/service/filter/filter.service.js +5 -3
- package/dist/module/query/service/filter/filter.service.js.map +1 -1
- package/dist/module/query/service/filter/scope.service.d.ts +8 -7
- package/dist/module/query/service/filter/scope.service.js +38 -20
- package/dist/module/query/service/filter/scope.service.js.map +1 -1
- package/dist/module/query/service/queryChain.service.d.ts +24 -14
- package/dist/module/query/service/queryChain.service.js +28 -14
- package/dist/module/query/service/queryChain.service.js.map +1 -1
- package/dist/module/query/util/filter/predicate.util.js +2 -0
- package/dist/module/query/util/filter/predicate.util.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* 400 is deliberately absent, so it is a compile error rather than a runtime
|
|
7
7
|
* failure.
|
|
8
8
|
*/
|
|
9
|
-
import type { Chain, ExpandKey, ExpandNamespace, QueryParams } from './module/query/domain/chain/chain.model';
|
|
10
|
-
import type { ExpandChain } from './module/query/domain/chain/expandChain.model';
|
|
9
|
+
import type { Chain, EmbeddedExpandNamespace, ExpandKey, ExpandNamespace, QueryParams } from './module/query/domain/chain/chain.model';
|
|
10
|
+
import type { ExpandChain, ToOneExpandChain } from './module/query/domain/chain/expandChain.model';
|
|
11
11
|
import type { ItemChain } from './module/query/domain/chain/itemChain.model';
|
|
12
12
|
import { QueryBuilderExceptionCode } from './module/query/domain/exceptionCode.model';
|
|
13
13
|
import type { ExceptionDetail } from './module/query/domain/exceptionDetail.model';
|
|
@@ -19,7 +19,7 @@ import type { Node, Predicate } from './module/query/domain/filter/node.model';
|
|
|
19
19
|
import type { NumberExpr } from './module/query/domain/filter/numberExpr.model';
|
|
20
20
|
import type { Operators } from './module/query/domain/filter/operators.model';
|
|
21
21
|
import type { Scalar, Unwrap } from './module/query/domain/filter/scalar.model';
|
|
22
|
-
import type { EmbeddedObjectKeys, EmbeddedOf, ExprFor, LambdaNamespace, OwnKeys, PrimitiveArrayKeys, PrimitiveLambdaNamespace, Relation, ScalarFieldKeys, Scope, ToManyKeys, ToOneKeys } from './module/query/domain/filter/scope.model';
|
|
22
|
+
import type { ColumnExpr, EmbeddedObjectKeys, EmbeddedOf, ExprFor, InlineToOneKeys, LambdaNamespace, OwnKeys, PrimitiveArrayKeys, PrimitiveLambdaNamespace, Relation, ScalarFieldKeys, Scope, SelectColumn, SelectScope, ToManyKeys, ToOneKeys } from './module/query/domain/filter/scope.model';
|
|
23
23
|
import type { StringExpr } from './module/query/domain/filter/stringExpr.model';
|
|
24
24
|
import { InvalidFilterError } from './module/query/exception/invalidFilter.exception';
|
|
25
25
|
import { QueryBuilderException } from './module/query/exception/queryBuilder.exception';
|
|
@@ -27,4 +27,4 @@ import { ReservedNameError } from './module/query/exception/reservedName.excepti
|
|
|
27
27
|
import { and, maxdatetime, mindatetime, not, now, or, raw } from './module/query/service/filter/filter.facade';
|
|
28
28
|
import { odataItem, odataQuery } from './module/query/service/queryChain.service';
|
|
29
29
|
export { InvalidFilterError, QueryBuilderException, QueryBuilderExceptionCode, ReservedNameError, and, maxdatetime, mindatetime, not, now, odataItem, odataQuery, or, raw, };
|
|
30
|
-
export type { BooleanExpr, CastResult, Castable, Chain, Comparable, DateExpr, DateInput, EdmTarget, EmbeddedObjectKeys, EmbeddedOf, ExceptionDetail, ExpandChain, ExpandKey, ExpandNamespace, ExprFor, ItemChain, LambdaNamespace, Node, NumberExpr, Operators, OwnKeys, Predicate, PrimitiveArrayKeys, PrimitiveLambdaNamespace, QueryParams, Relation, Scalar, ScalarFieldKeys, Scope, StringExpr, ToManyKeys, ToOneKeys, Unwrap, };
|
|
30
|
+
export type { BooleanExpr, CastResult, Castable, Chain, ColumnExpr, Comparable, DateExpr, DateInput, EdmTarget, EmbeddedExpandNamespace, EmbeddedObjectKeys, EmbeddedOf, ExceptionDetail, ExpandChain, ExpandKey, ExpandNamespace, ExprFor, InlineToOneKeys, ItemChain, LambdaNamespace, Node, NumberExpr, Operators, OwnKeys, Predicate, PrimitiveArrayKeys, PrimitiveLambdaNamespace, QueryParams, Relation, Scalar, ScalarFieldKeys, Scope, SelectColumn, SelectScope, StringExpr, ToManyKeys, ToOneExpandChain, ToOneKeys, Unwrap, };
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAcH,mFAAsF;AAwDrF,0GAxDQ,+CAAyB,OAwDR;AApB1B,8FAAsF;AAkBrF,mGAlBQ,4CAAkB,OAkBR;AAjBnB,4FAAwF;AAkBvF,sGAlBQ,8CAAqB,OAkBR;AAjBtB,4FAAoF;AAmBnF,kGAnBQ,0CAAiB,OAmBR;AAlBlB,+EAQqD;AAWpD,oFAlBA,mBAAG,OAkBA;AACH,4FAlBA,2BAAW,OAkBA;AACX,4FAlBA,2BAAW,OAkBA;AACX,oFAlBA,mBAAG,OAkBA;AACH,oFAlBA,mBAAG,OAkBA;AAGH,mFApBA,kBAAE,OAoBA;AACF,oFApBA,mBAAG,OAoBA;AAlBJ,kFAGmD;AAYlD,0FAdA,8BAAS,OAcA;AACT,2FAdA,+BAAU,OAcA"}
|
|
@@ -4,34 +4,54 @@
|
|
|
4
4
|
* The builder produces a query STRING. It does not fetch, and it does not know
|
|
5
5
|
* about the `_embedded` / `_page` response envelope.
|
|
6
6
|
*
|
|
7
|
-
* `ExpandNamespace` is the type of the `expand` member of
|
|
8
|
-
*
|
|
7
|
+
* `ExpandNamespace` is the type of the `expand` member of every chain
|
|
8
|
+
* type. It holds one function per relation of the DTO, typed from
|
|
9
9
|
* `_embedded`: `q.expand.` lists exactly the relations `_embedded` declares,
|
|
10
|
-
* and each callback is typed to the entity that relation reaches.
|
|
11
|
-
*
|
|
10
|
+
* and each callback is typed to the entity that relation reaches. A to-many
|
|
11
|
+
* relation's callback receives an `ExpandChain`, a to-one relation's a
|
|
12
|
+
* `ToOneExpandChain`. There is no build step and no `$metadata` document.
|
|
12
13
|
*/
|
|
13
14
|
import type { Predicate } from '../filter/node.model';
|
|
14
15
|
import type { Operators } from '../filter/operators.model';
|
|
15
|
-
import type { ColumnExpr, Relation, ScalarFieldKeys, Scope, SelectScope, ToManyKeys, ToOneKeys } from '../filter/scope.model';
|
|
16
|
+
import type { ColumnExpr, EmbeddedObjectKeys, InlineToOneKeys, PrimitiveArrayKeys, Relation, ScalarFieldKeys, Scope, SelectColumn, SelectScope, ToManyKeys, ToOneKeys } from '../filter/scope.model';
|
|
16
17
|
import type { StringExpr } from '../filter/stringExpr.model';
|
|
17
|
-
import type { ExpandChain } from './expandChain.model';
|
|
18
|
+
import type { ExpandChain, ToOneExpandChain } from './expandChain.model';
|
|
18
19
|
/** A flat `{ $option: value }` map, for a caller that serialises its own URL. */
|
|
19
20
|
export type QueryParams = Record<string, string>;
|
|
20
21
|
/** Every expandable relation name of a DTO. A real allowlist. */
|
|
21
22
|
export type ExpandKey<T> = ToOneKeys<T> | ToManyKeys<T>;
|
|
22
23
|
/**
|
|
23
24
|
* `Self` is the chain the call returns, so `expand.a(...).expand.b(...)`
|
|
24
|
-
* chains at whatever level it is written.
|
|
25
|
+
* chains at whatever level it is written. An embedded object reads as an
|
|
26
|
+
* `EmbeddedExpandNamespace`, so `expand.address.supplier()` reaches the inline
|
|
27
|
+
* to-one inside it.
|
|
25
28
|
*/
|
|
26
29
|
export type ExpandNamespace<T, Self> = {
|
|
27
|
-
readonly [K in ExpandKey<T>]: (build?: (chain: ExpandChain<Relation<T, K>>) => unknown) => Self;
|
|
30
|
+
readonly [K in ExpandKey<T>]: (build?: (chain: K extends ToManyKeys<T> ? ExpandChain<Relation<T, K>> : ToOneExpandChain<Relation<T, K>>) => unknown) => Self;
|
|
31
|
+
} & {
|
|
32
|
+
readonly [K in Exclude<EmbeddedObjectKeys<T>, ExpandKey<T> | InlineToOneKeys<T>>]: EmbeddedExpandNamespace<NonNullable<T[K]>, Self>;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* The inline to-ones inside embedded object `E`, and the embedded objects
|
|
36
|
+
* nested in it. A call prints the joined path: `expand.address.supplier()`
|
|
37
|
+
* gives `$expand=address/supplier`. The call takes no callback, because the
|
|
38
|
+
* server rejects options on an expand path of more than one segment
|
|
39
|
+
* (test/e2e/rejections.spec.ts).
|
|
40
|
+
*/
|
|
41
|
+
export type EmbeddedExpandNamespace<E, Self> = {
|
|
42
|
+
readonly [K in InlineToOneKeys<E>]: () => Self;
|
|
43
|
+
} & {
|
|
44
|
+
readonly [K in Exclude<EmbeddedObjectKeys<E>, InlineToOneKeys<E>>]: EmbeddedExpandNamespace<NonNullable<E[K]>, Self>;
|
|
28
45
|
};
|
|
29
46
|
export interface Chain<T> {
|
|
30
47
|
readonly expand: ExpandNamespace<T, Chain<T>>;
|
|
31
|
-
/** Own columns, by name. */
|
|
32
|
-
select(...keys: ScalarFieldKeys<T>[]): Chain<T>;
|
|
33
|
-
/**
|
|
34
|
-
|
|
48
|
+
/** Own columns and primitive array columns, by name. */
|
|
49
|
+
select(...keys: (ScalarFieldKeys<T> | PrimitiveArrayKeys<T>)[]): Chain<T>;
|
|
50
|
+
/**
|
|
51
|
+
* Own columns, primitive array columns and embedded leaves:
|
|
52
|
+
* `select((v) => [v.id, v.tags, v.address.city])`.
|
|
53
|
+
*/
|
|
54
|
+
select(columns: (scope: SelectScope<T>) => SelectColumn | readonly SelectColumn[]): Chain<T>;
|
|
35
55
|
/** Repeated calls AND together. */
|
|
36
56
|
filter(build: (scope: Scope<T>, operators: Operators) => Predicate): Chain<T>;
|
|
37
57
|
/** `$search` + its mandatory `$searchColumns`, as one verb. */
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* What a nested `$expand` may carry
|
|
3
|
-
* `$expand`, `$top` and `$skip`, and
|
|
2
|
+
* What a nested `$expand` may carry. `ExpandChain` is the chain of a to-many
|
|
3
|
+
* relation: `$filter`, `$select`, a further `$expand`, `$top` and `$skip`, and
|
|
4
|
+
* nothing else. `ToOneExpandChain` is the chain of a to-one relation: the same
|
|
5
|
+
* without `$top` and `$skip`, because the server pages a collection only and
|
|
6
|
+
* answers `$expand=owner($top=5)` with a 400.
|
|
4
7
|
*
|
|
5
8
|
* `$orderby`, `$count` and `$levels` inside `$expand` are an
|
|
6
9
|
* `UnsupportedFeatureError` from the server, so they are absent from this
|
|
@@ -15,27 +18,39 @@
|
|
|
15
18
|
*/
|
|
16
19
|
import type { Predicate } from '../filter/node.model';
|
|
17
20
|
import type { Operators } from '../filter/operators.model';
|
|
18
|
-
import type {
|
|
21
|
+
import type { PrimitiveArrayKeys, ScalarFieldKeys, Scope, SelectColumn, SelectScope } from '../filter/scope.model';
|
|
19
22
|
import type { ExpandNamespace } from './chain.model';
|
|
20
23
|
export interface ExpandChain<T> {
|
|
21
24
|
readonly expand: ExpandNamespace<T, ExpandChain<T>>;
|
|
22
|
-
/** Own columns, by name. */
|
|
23
|
-
select(...keys: ScalarFieldKeys<T>[]): ExpandChain<T>;
|
|
24
|
-
/**
|
|
25
|
-
|
|
25
|
+
/** Own columns and primitive array columns, by name. */
|
|
26
|
+
select(...keys: (ScalarFieldKeys<T> | PrimitiveArrayKeys<T>)[]): ExpandChain<T>;
|
|
27
|
+
/**
|
|
28
|
+
* Own columns, primitive array columns and embedded leaves:
|
|
29
|
+
* `select((v) => [v.id, v.tags, v.address.city])`.
|
|
30
|
+
*/
|
|
31
|
+
select(columns: (scope: SelectScope<T>) => SelectColumn | readonly SelectColumn[]): ExpandChain<T>;
|
|
26
32
|
/**
|
|
27
33
|
* `$expand=rel($filter=…)`. The scope is the EXPANDED entity, so paths are
|
|
28
34
|
* written relative to it, not to the root. Repeated calls AND together.
|
|
29
35
|
*/
|
|
30
36
|
filter(build: (scope: Scope<T>, operators: Operators) => Predicate): ExpandChain<T>;
|
|
37
|
+
/** `$expand=rel($top=…)`. The server applies it per parent row. */
|
|
38
|
+
top(count: number): ExpandChain<T>;
|
|
39
|
+
/** `$expand=rel($skip=…)`. The server applies it per parent row. */
|
|
40
|
+
skip(count: number): ExpandChain<T>;
|
|
41
|
+
}
|
|
42
|
+
export interface ToOneExpandChain<T> {
|
|
43
|
+
readonly expand: ExpandNamespace<T, ToOneExpandChain<T>>;
|
|
44
|
+
/** Own columns and primitive array columns, by name. */
|
|
45
|
+
select(...keys: (ScalarFieldKeys<T> | PrimitiveArrayKeys<T>)[]): ToOneExpandChain<T>;
|
|
31
46
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
47
|
+
* Own columns, primitive array columns and embedded leaves:
|
|
48
|
+
* `select((v) => [v.id, v.tags, v.address.city])`.
|
|
34
49
|
*/
|
|
35
|
-
|
|
50
|
+
select(columns: (scope: SelectScope<T>) => SelectColumn | readonly SelectColumn[]): ToOneExpandChain<T>;
|
|
36
51
|
/**
|
|
37
|
-
* `$expand=rel($
|
|
38
|
-
*
|
|
52
|
+
* `$expand=rel($filter=…)`. The scope is the EXPANDED entity, so paths are
|
|
53
|
+
* written relative to it, not to the root. Repeated calls AND together.
|
|
39
54
|
*/
|
|
40
|
-
|
|
55
|
+
filter(build: (scope: Scope<T>, operators: Operators) => Predicate): ToOneExpandChain<T>;
|
|
41
56
|
}
|
|
@@ -5,14 +5,17 @@
|
|
|
5
5
|
* `$count` and `$search` have nothing to act on. Only the shaping options are
|
|
6
6
|
* offered.
|
|
7
7
|
*/
|
|
8
|
-
import type {
|
|
8
|
+
import type { PrimitiveArrayKeys, ScalarFieldKeys, SelectColumn, SelectScope } from '../filter/scope.model';
|
|
9
9
|
import type { ExpandNamespace, QueryParams } from './chain.model';
|
|
10
10
|
export interface ItemChain<T> {
|
|
11
11
|
readonly expand: ExpandNamespace<T, ItemChain<T>>;
|
|
12
|
-
/** Own columns, by name. */
|
|
13
|
-
select(...keys: ScalarFieldKeys<T>[]): ItemChain<T>;
|
|
14
|
-
/**
|
|
15
|
-
|
|
12
|
+
/** Own columns and primitive array columns, by name. */
|
|
13
|
+
select(...keys: (ScalarFieldKeys<T> | PrimitiveArrayKeys<T>)[]): ItemChain<T>;
|
|
14
|
+
/**
|
|
15
|
+
* Own columns, primitive array columns and embedded leaves:
|
|
16
|
+
* `select((v) => [v.id, v.tags, v.address.city])`.
|
|
17
|
+
*/
|
|
18
|
+
select(columns: (scope: SelectScope<T>) => SelectColumn | readonly SelectColumn[]): ItemChain<T>;
|
|
16
19
|
toQueryString(): string;
|
|
17
20
|
/**
|
|
18
21
|
* The same query as separate parts, with the transport escaping undone, for
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The machine-readable payload behind an error message. One entry of
|
|
3
|
-
* `QueryBuilderException.errors` is one of these
|
|
4
|
-
* the
|
|
3
|
+
* `QueryBuilderException.errors` is one of these. For InvalidFilterError,
|
|
4
|
+
* errors[0].reason is the message; ReservedNameError has a longer message and
|
|
5
|
+
* a fixed reason.
|
|
5
6
|
*
|
|
6
7
|
* Plain serializable data: an adapter can put the array straight into an HTTP
|
|
7
8
|
* response body.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
3
|
* The machine-readable payload behind an error message. One entry of
|
|
4
|
-
* `QueryBuilderException.errors` is one of these
|
|
5
|
-
* the
|
|
4
|
+
* `QueryBuilderException.errors` is one of these. For InvalidFilterError,
|
|
5
|
+
* errors[0].reason is the message; ReservedNameError has a longer message and
|
|
6
|
+
* a fixed reason.
|
|
6
7
|
*
|
|
7
8
|
* Plain serializable data: an adapter can put the array straight into an HTTP
|
|
8
9
|
* response body.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exceptionDetail.model.js","sourceRoot":"","sources":["../../../../src/module/query/domain/exceptionDetail.model.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"exceptionDetail.model.js","sourceRoot":"","sources":["../../../../src/module/query/domain/exceptionDetail.model.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A temporal expression. A DTO types a timestamp column as an ISO `string`, so
|
|
3
3
|
* this type is reached through the explicit `.asDate()` opt-in rather than
|
|
4
|
-
* inferred — which keeps the
|
|
4
|
+
* inferred — which keeps the component functions off every text column.
|
|
5
5
|
*/
|
|
6
6
|
import type { Castable } from './castable.model';
|
|
7
7
|
import type { Comparable } from './comparable.model';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The two shapes every filter fragment is one of.
|
|
3
3
|
*
|
|
4
|
-
* Nothing in this file has a runtime body
|
|
5
|
-
*
|
|
4
|
+
* Nothing in this file has a runtime body. PredicateNode in
|
|
5
|
+
* util/filter/predicate.util.ts implements Predicate, and ExpressionNode in
|
|
6
|
+
* service/filter/scope.service.ts carries the text of every other Node.
|
|
6
7
|
* A construct the server rejects is not typed here at all, so a 400 becomes a
|
|
7
8
|
* red squiggle.
|
|
8
9
|
*/
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* The two shapes every filter fragment is one of.
|
|
4
4
|
*
|
|
5
|
-
* Nothing in this file has a runtime body
|
|
6
|
-
*
|
|
5
|
+
* Nothing in this file has a runtime body. PredicateNode in
|
|
6
|
+
* util/filter/predicate.util.ts implements Predicate, and ExpressionNode in
|
|
7
|
+
* service/filter/scope.service.ts carries the text of every other Node.
|
|
7
8
|
* A construct the server rejects is not typed here at all, so a 400 becomes a
|
|
8
9
|
* red squiggle.
|
|
9
10
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.model.js","sourceRoot":"","sources":["../../../../../src/module/query/domain/filter/node.model.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"node.model.js","sourceRoot":"","sources":["../../../../../src/module/query/domain/filter/node.model.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG"}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* The eleven helper types below are mutually recursive (`Scope<T>` mentions
|
|
6
|
-
* `Scope<Relation>`), so they stay in one file rather than being split one per
|
|
7
|
-
* type: the split would only add import cycles between declaration files.
|
|
2
|
+
* The scopes that a filter, search, orderBy or select callback reads.
|
|
3
|
+
* `Scope<T>` and `LambdaNamespace<R>` refer to each other; the key types sit
|
|
4
|
+
* next to them because both scopes are built from them.
|
|
8
5
|
*
|
|
9
6
|
* The key sets are subtracted with `Exclude` rather than `Omit`. `Omit` makes
|
|
10
7
|
* TypeScript compute `keyof` of a type that mentions `Scope<T>` again, which it
|
|
@@ -63,6 +60,15 @@ export type PrimitiveArrayKeys<T> = Extract<{
|
|
|
63
60
|
export type EmbeddedObjectKeys<T> = Extract<{
|
|
64
61
|
[K in keyof T]-?: K extends '_embedded' ? never : NonNullable<T[K]> extends Scalar ? never : NonNullable<T[K]> extends readonly unknown[] ? never : NonNullable<T[K]> extends object ? K : never;
|
|
65
62
|
}[keyof T], string>;
|
|
63
|
+
/**
|
|
64
|
+
* Every embedded object property whose type is a row-backed DTO, which the
|
|
65
|
+
* type shows by its `_embedded` key: an inline to-one (`address.supplier`).
|
|
66
|
+
* A filter reads it like an embedded object; its columns reach the response
|
|
67
|
+
* through `$expand`, never through `$select`.
|
|
68
|
+
*/
|
|
69
|
+
export type InlineToOneKeys<T> = {
|
|
70
|
+
[K in EmbeddedObjectKeys<T>]-?: '_embedded' extends keyof NonNullable<T[K]> ? K : never;
|
|
71
|
+
}[EmbeddedObjectKeys<T>];
|
|
66
72
|
/** Every `_embedded` relation of a DTO that holds a single row. */
|
|
67
73
|
export type ToOneKeys<T> = Extract<{
|
|
68
74
|
[K in keyof EmbeddedOf<T>]-?: NonNullable<EmbeddedOf<T>[K]> extends readonly unknown[] ? never : K;
|
|
@@ -99,12 +105,20 @@ export type Scope<T> = {
|
|
|
99
105
|
*/
|
|
100
106
|
export type ColumnExpr = StringExpr<string> | NumberExpr<number | bigint> | DateExpr | BooleanExpr;
|
|
101
107
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
|
|
108
|
+
* One column, as a `select` callback returns it: a `ColumnExpr`, or a
|
|
109
|
+
* primitive array column, which `$select` takes but `$orderby` does not.
|
|
110
|
+
*/
|
|
111
|
+
export type SelectColumn = ColumnExpr | PrimitiveLambdaNamespace<Scalar>;
|
|
112
|
+
/**
|
|
113
|
+
* What a `select` callback reads: own columns, primitive array columns and
|
|
114
|
+
* embedded objects, never a relation. A relation column comes through
|
|
115
|
+
* `$expand`, so neither `owner/email` nor the inline to-one
|
|
116
|
+
* `address/supplier/name` is a `$select` path.
|
|
105
117
|
*/
|
|
106
118
|
export type SelectScope<T> = {
|
|
107
119
|
readonly [K in ScalarFieldKeys<T>]: ExprFor<T[K]>;
|
|
108
120
|
} & {
|
|
109
|
-
readonly [K in
|
|
121
|
+
readonly [K in PrimitiveArrayKeys<T>]: PrimitiveLambdaNamespace<Unwrap<NonNullable<T[K]>>>;
|
|
122
|
+
} & {
|
|
123
|
+
readonly [K in Exclude<EmbeddedObjectKeys<T>, InlineToOneKeys<T>>]: SelectScope<NonNullable<T[K]>>;
|
|
110
124
|
};
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* the predicates and the search parts it carries.
|
|
5
5
|
*
|
|
6
6
|
* One shape serves every level. The type layer is what decides which verbs a
|
|
7
|
-
* level offers
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* level offers. The emitter does not check the level: toQueryParts() prints
|
|
8
|
+
* every root field, and nestedParts() prints only $filter, $select, $expand,
|
|
9
|
+
* $top and $skip of an expanded level.
|
|
10
10
|
*
|
|
11
11
|
* It sits at the root of `domain/` because it is the contract of
|
|
12
12
|
* `src/module/query/`, not the product of one stage.
|
|
@@ -7,6 +7,10 @@ exports.InvalidFilterError = void 0;
|
|
|
7
7
|
* Every case the type layer can reject is rejected at compile time instead;
|
|
8
8
|
* this covers what only the runtime can see — an empty `in()` list, a NaN
|
|
9
9
|
* literal, a callback that returns a column instead of a predicate.
|
|
10
|
+
*
|
|
11
|
+
* Despite the name, this is the error of every runtime check that is not a
|
|
12
|
+
* reserved name: top() and skip() values and search(), orderBy() and select()
|
|
13
|
+
* columns included.
|
|
10
14
|
*/
|
|
11
15
|
const exceptionCode_model_1 = require("../domain/exceptionCode.model");
|
|
12
16
|
const queryBuilder_exception_1 = require("./queryBuilder.exception");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invalidFilter.exception.js","sourceRoot":"","sources":["../../../../src/module/query/exception/invalidFilter.exception.ts"],"names":[],"mappings":";;;AAAA
|
|
1
|
+
{"version":3,"file":"invalidFilter.exception.js","sourceRoot":"","sources":["../../../../src/module/query/exception/invalidFilter.exception.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;GAUG;AACH,uEAA0E;AAC1E,qEAAiE;AAEjE,MAAa,kBAAmB,SAAQ,8CAAqB;IAC5D,YAAY,MAAc,EAAE,OAAgB;QAC3C,KAAK,CAAC,+CAAyB,CAAC,cAAc,EAAE,MAAM,EAAE;YACvD,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE;SACxD,CAAC,CAAC;IACJ,CAAC;CACD;AAND,gDAMC"}
|
|
@@ -22,7 +22,10 @@ export declare abstract class QueryBuilderException extends Error {
|
|
|
22
22
|
readonly statusCode: number;
|
|
23
23
|
/** Stable machine-readable code, e.g. "RESERVED_NAME". */
|
|
24
24
|
readonly code: QueryBuilderExceptionCode;
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Every detail behind this error. For InvalidFilterError, errors[0].reason
|
|
27
|
+
* is the message; ReservedNameError has a longer message and a fixed reason.
|
|
28
|
+
*/
|
|
26
29
|
readonly errors: ExceptionDetail[];
|
|
27
30
|
protected constructor(code: QueryBuilderExceptionCode, message: string, errors: ExceptionDetail[]);
|
|
28
31
|
}
|
|
@@ -23,7 +23,10 @@ class QueryBuilderException extends Error {
|
|
|
23
23
|
statusCode;
|
|
24
24
|
/** Stable machine-readable code, e.g. "RESERVED_NAME". */
|
|
25
25
|
code;
|
|
26
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Every detail behind this error. For InvalidFilterError, errors[0].reason
|
|
28
|
+
* is the message; ReservedNameError has a longer message and a fixed reason.
|
|
29
|
+
*/
|
|
27
30
|
errors;
|
|
28
31
|
constructor(code, message, errors) {
|
|
29
32
|
super(message);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryBuilder.exception.js","sourceRoot":"","sources":["../../../../src/module/query/exception/queryBuilder.exception.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAKH,MAAsB,qBAAsB,SAAQ,KAAK;IACxD,sDAAsD;IAC7C,MAAM,CAAS;IACxB,8DAA8D;IACrD,UAAU,CAAS;IAC5B,0DAA0D;IACjD,IAAI,CAA4B;IACzC
|
|
1
|
+
{"version":3,"file":"queryBuilder.exception.js","sourceRoot":"","sources":["../../../../src/module/query/exception/queryBuilder.exception.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAKH,MAAsB,qBAAsB,SAAQ,KAAK;IACxD,sDAAsD;IAC7C,MAAM,CAAS;IACxB,8DAA8D;IACrD,UAAU,CAAS;IAC5B,0DAA0D;IACjD,IAAI,CAA4B;IACzC;;;OAGG;IACM,MAAM,CAAoB;IAEnC,YACC,IAA+B,EAC/B,OAAe,EACf,MAAyB;QAEzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC;QAClB,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;CACD;AAzBD,sDAyBC"}
|
|
@@ -4,16 +4,16 @@ exports.ReservedNameError = void 0;
|
|
|
4
4
|
/**
|
|
5
5
|
* A name the builder cannot hand out, because JavaScript itself would call it.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* A filter scope member (ScopeService.createMember() in scope.service.ts) and
|
|
8
|
+
* chain.expand throw for then, toJSON, toString and valueOf. JavaScript reads
|
|
9
|
+
* these names in await, JSON.stringify and string or number coercion.
|
|
10
10
|
*/
|
|
11
11
|
const exceptionCode_model_1 = require("../domain/exceptionCode.model");
|
|
12
12
|
const queryBuilder_exception_1 = require("./queryBuilder.exception");
|
|
13
13
|
class ReservedNameError extends queryBuilder_exception_1.QueryBuilderException {
|
|
14
14
|
reservedName;
|
|
15
15
|
constructor(reservedName) {
|
|
16
|
-
super(exceptionCode_model_1.QueryBuilderExceptionCode.RESERVED_NAME, `"${reservedName}" is reserved on
|
|
16
|
+
super(exceptionCode_model_1.QueryBuilderExceptionCode.RESERVED_NAME, `"${reservedName}" is reserved on the query builder. The builder is not a ` +
|
|
17
17
|
`promise and is not serialisable; call .toQueryString() instead.`, [
|
|
18
18
|
{
|
|
19
19
|
reason: 'the name is reserved on a builder scope',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reservedName.exception.js","sourceRoot":"","sources":["../../../../src/module/query/exception/reservedName.exception.ts"],"names":[],"mappings":";;;AAAA;;;;;;GAMG;AACH,uEAA0E;AAC1E,qEAAiE;AAEjE,MAAa,iBAAkB,SAAQ,8CAAqB;IACtC;IAArB,YAAqB,YAAoB;QACxC,KAAK,CACJ,+CAAyB,CAAC,aAAa,EACvC,IAAI,YAAY,
|
|
1
|
+
{"version":3,"file":"reservedName.exception.js","sourceRoot":"","sources":["../../../../src/module/query/exception/reservedName.exception.ts"],"names":[],"mappings":";;;AAAA;;;;;;GAMG;AACH,uEAA0E;AAC1E,qEAAiE;AAEjE,MAAa,iBAAkB,SAAQ,8CAAqB;IACtC;IAArB,YAAqB,YAAoB;QACxC,KAAK,CACJ,+CAAyB,CAAC,aAAa,EACvC,IAAI,YAAY,2DAA2D;YAC1E,iEAAiE,EAClE;YACC;gBACC,MAAM,EAAE,yCAAyC;gBACjD,OAAO,EAAE,YAAY;aACrB;SACD,CACD,CAAC;QAXkB,iBAAY,GAAZ,YAAY,CAAQ;IAYzC,CAAC;CACD;AAdD,8CAcC"}
|
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
* golden-string test can be written against a hand-built state.
|
|
6
6
|
*
|
|
7
7
|
* `toQueryString()` and `toParams()` read the same ordered parts from
|
|
8
|
-
* `toQueryParts()`, so the
|
|
9
|
-
*
|
|
10
|
-
* one leaves in place.
|
|
8
|
+
* `toQueryParts()`, so for text the builder escapes, the string form and the
|
|
9
|
+
* map form say the same query. They differ only in the transport escaping
|
|
10
|
+
* each one leaves in place. raw() text goes into both forms as written, so a
|
|
11
|
+
* + or a percent escape in it means one thing in toQueryString() and another
|
|
12
|
+
* in toParams().
|
|
11
13
|
*/
|
|
12
14
|
import type { QueryState } from '../../domain/queryState.model';
|
|
13
15
|
export declare class EmitService {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.service.js","sourceRoot":"","sources":["../../../../../src/module/query/service/emit/emit.service.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"emit.service.js","sourceRoot":"","sources":["../../../../../src/module/query/service/emit/emit.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,17 +13,19 @@ class FilterService {
|
|
|
13
13
|
return (0, predicate_util_1.combine)('or', predicates);
|
|
14
14
|
}
|
|
15
15
|
static not(predicate) {
|
|
16
|
+
if (!(predicate instanceof predicate_util_1.PredicateNode))
|
|
17
|
+
throw new invalidFilter_exception_1.InvalidFilterError('not() takes predicates, not a bare column', 'not');
|
|
16
18
|
// `not (…)` carries its own grouping, so it never needs wrapping again.
|
|
17
19
|
return new predicate_util_1.PredicateNode(`not (${predicate.text})`);
|
|
18
20
|
}
|
|
19
21
|
static now() {
|
|
20
|
-
return scope_service_1.ScopeService.createMember(new scope_service_1.ExpressionNode('now()'
|
|
22
|
+
return scope_service_1.ScopeService.createMember(new scope_service_1.ExpressionNode('now()'));
|
|
21
23
|
}
|
|
22
24
|
static maxdatetime() {
|
|
23
|
-
return scope_service_1.ScopeService.createMember(new scope_service_1.ExpressionNode('maxdatetime()'
|
|
25
|
+
return scope_service_1.ScopeService.createMember(new scope_service_1.ExpressionNode('maxdatetime()'));
|
|
24
26
|
}
|
|
25
27
|
static mindatetime() {
|
|
26
|
-
return scope_service_1.ScopeService.createMember(new scope_service_1.ExpressionNode('mindatetime()'
|
|
28
|
+
return scope_service_1.ScopeService.createMember(new scope_service_1.ExpressionNode('mindatetime()'));
|
|
27
29
|
}
|
|
28
30
|
static raw(odataExpression) {
|
|
29
31
|
return new predicate_util_1.PredicateNode(odataExpression, true);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.service.js","sourceRoot":"","sources":["../../../../../src/module/query/service/filter/filter.service.ts"],"names":[],"mappings":";;;AAgBA,qFAA6E;AAC7E,+DAAgE;AAChE,qEAA0E;AAC1E,mDAA+D;AAI/D,MAAa,aAAa;IACzB,MAAM,CAAC,GAAG,CAAC,GAAG,UAAuB;QACpC,OAAO,IAAA,wBAAO,EAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,CAAC,EAAE,CAAC,GAAG,UAAuB;QACnC,OAAO,IAAA,wBAAO,EAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,CAAC,GAAG,CAAC,SAAoB;QAC9B,wEAAwE;QACxE,OAAO,IAAI,8BAAa,CAAC,QAAQ,SAAS,CAAC,IAAI,GAAG,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,CAAC,GAAG;QACT,OAAO,4BAAY,CAAC,YAAY,CAAC,IAAI,8BAAc,CAAC,OAAO,
|
|
1
|
+
{"version":3,"file":"filter.service.js","sourceRoot":"","sources":["../../../../../src/module/query/service/filter/filter.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
export declare class ExpressionNode {
|
|
2
2
|
readonly text: string;
|
|
3
|
-
/** lambda nesting level, for deterministic alias letters */
|
|
4
|
-
readonly depth: number;
|
|
5
3
|
/** true for `a add 1`: needs parentheses as an operand of `mul`. */
|
|
6
4
|
readonly arithmetic: boolean;
|
|
7
5
|
constructor(text: string,
|
|
8
|
-
/** lambda nesting level, for deterministic alias letters */
|
|
9
|
-
depth: number,
|
|
10
6
|
/** true for `a add 1`: needs parentheses as an operand of `mul`. */
|
|
11
7
|
arithmetic?: boolean);
|
|
12
8
|
}
|
|
@@ -14,9 +10,8 @@ export declare class ScopeService {
|
|
|
14
10
|
/** The only key that reads a node. A DTO key can never be a symbol. */
|
|
15
11
|
private static readonly NODE;
|
|
16
12
|
/**
|
|
17
|
-
* The filter scope of an entity: an empty path
|
|
18
|
-
*
|
|
19
|
-
* root.
|
|
13
|
+
* The filter scope of an entity: an empty path. An expanded entity is
|
|
14
|
+
* filtered relative to itself, so it takes the same empty root.
|
|
20
15
|
*/
|
|
21
16
|
static rootScope(): any;
|
|
22
17
|
/**
|
|
@@ -54,6 +49,12 @@ export declare class ScopeService {
|
|
|
54
49
|
private static binaryFunction;
|
|
55
50
|
private static arithmetic;
|
|
56
51
|
private static stringMatch;
|
|
52
|
+
/**
|
|
53
|
+
* The number of lambda bodies running at this moment. A lambda takes its
|
|
54
|
+
* alias from it, so a lambda inside another lambda body gets the next
|
|
55
|
+
* letter, also when it opens on a root path.
|
|
56
|
+
*/
|
|
57
|
+
private static openLambdas;
|
|
57
58
|
/**
|
|
58
59
|
* A distinct alias letter per lambda nesting level, so an inner lambda never
|
|
59
60
|
* shadows the outer one and `b/x ne a/y` stays expressible.
|
|
@@ -7,15 +7,11 @@ const escape_util_1 = require("../../util/filter/escape.util");
|
|
|
7
7
|
const predicate_util_1 = require("../../util/filter/predicate.util");
|
|
8
8
|
class ExpressionNode {
|
|
9
9
|
text;
|
|
10
|
-
depth;
|
|
11
10
|
arithmetic;
|
|
12
11
|
constructor(text,
|
|
13
|
-
/** lambda nesting level, for deterministic alias letters */
|
|
14
|
-
depth,
|
|
15
12
|
/** true for `a add 1`: needs parentheses as an operand of `mul`. */
|
|
16
13
|
arithmetic = false) {
|
|
17
14
|
this.text = text;
|
|
18
|
-
this.depth = depth;
|
|
19
15
|
this.arithmetic = arithmetic;
|
|
20
16
|
}
|
|
21
17
|
}
|
|
@@ -24,12 +20,11 @@ class ScopeService {
|
|
|
24
20
|
/** The only key that reads a node. A DTO key can never be a symbol. */
|
|
25
21
|
static NODE = Symbol('odata.node');
|
|
26
22
|
/**
|
|
27
|
-
* The filter scope of an entity: an empty path
|
|
28
|
-
*
|
|
29
|
-
* root.
|
|
23
|
+
* The filter scope of an entity: an empty path. An expanded entity is
|
|
24
|
+
* filtered relative to itself, so it takes the same empty root.
|
|
30
25
|
*/
|
|
31
26
|
static rootScope() {
|
|
32
|
-
return ScopeService.createMember(new ExpressionNode(''
|
|
27
|
+
return ScopeService.createMember(new ExpressionNode(''));
|
|
33
28
|
}
|
|
34
29
|
/**
|
|
35
30
|
* `createMember(node)` is a value; `createMember(node, parent, name)` is a
|
|
@@ -65,17 +60,16 @@ class ScopeService {
|
|
|
65
60
|
property === 'toString' ||
|
|
66
61
|
property === 'valueOf')
|
|
67
62
|
throw new reservedName_exception_1.ReservedNameError(property);
|
|
68
|
-
return ScopeService.createMember(new ExpressionNode(node.text ? `${node.text}/${property}` : property
|
|
63
|
+
return ScopeService.createMember(new ExpressionNode(node.text ? `${node.text}/${property}` : property), node, property);
|
|
69
64
|
},
|
|
70
65
|
apply(_target, _thisArgument, callArguments) {
|
|
71
66
|
if (parent === undefined || name === undefined)
|
|
72
|
-
throw new invalidFilter_exception_1.InvalidFilterError(`"${node.text}" is a
|
|
67
|
+
throw new invalidFilter_exception_1.InvalidFilterError(`"${node.text}" is a value, not a function`, node.text);
|
|
73
68
|
const method = ScopeService.filterFunction(name);
|
|
74
69
|
if (method === undefined)
|
|
75
70
|
throw new invalidFilter_exception_1.InvalidFilterError(`${name}() is not an OData filter function served by this API`, name);
|
|
76
71
|
return method(parent, callArguments);
|
|
77
72
|
},
|
|
78
|
-
has: (_target, property) => typeof property === 'string',
|
|
79
73
|
});
|
|
80
74
|
}
|
|
81
75
|
/** The node behind a scope proxy, or `undefined` for a plain value. */
|
|
@@ -122,7 +116,18 @@ class ScopeService {
|
|
|
122
116
|
if (typeof value === 'number') {
|
|
123
117
|
if (!Number.isFinite(value))
|
|
124
118
|
throw new invalidFilter_exception_1.InvalidFilterError(`${value} is not an OData number literal`, String(value));
|
|
125
|
-
|
|
119
|
+
const text = String(value);
|
|
120
|
+
if (!text.includes('e'))
|
|
121
|
+
return text;
|
|
122
|
+
// The grammar has no exponent form, so 1e-7 and 1e21 print in full.
|
|
123
|
+
// Below 1e-100 the full form rounds to 0, a different value.
|
|
124
|
+
const fullText = value.toLocaleString('en-US', {
|
|
125
|
+
useGrouping: false,
|
|
126
|
+
maximumFractionDigits: 100,
|
|
127
|
+
});
|
|
128
|
+
if (Number(fullText) !== value)
|
|
129
|
+
throw new invalidFilter_exception_1.InvalidFilterError(`${value} is not an OData number literal`, text);
|
|
130
|
+
return fullText;
|
|
126
131
|
}
|
|
127
132
|
if (value instanceof Date) {
|
|
128
133
|
if (Number.isNaN(value.getTime()))
|
|
@@ -142,18 +147,24 @@ class ScopeService {
|
|
|
142
147
|
}
|
|
143
148
|
/** A one-argument SQL function: `name(self)`. */
|
|
144
149
|
static unaryFunction(name) {
|
|
145
|
-
return (self) => ScopeService.createMember(new ExpressionNode(`${name}(${self.text})
|
|
150
|
+
return (self) => ScopeService.createMember(new ExpressionNode(`${name}(${self.text})`));
|
|
146
151
|
}
|
|
147
152
|
/** A two-argument SQL function: `name(self,argument)`. */
|
|
148
153
|
static binaryFunction(name) {
|
|
149
|
-
return (self, callArguments) => ScopeService.createMember(new ExpressionNode(`${name}(${self.text},${ScopeService.literal(callArguments[0])})
|
|
154
|
+
return (self, callArguments) => ScopeService.createMember(new ExpressionNode(`${name}(${self.text},${ScopeService.literal(callArguments[0])})`));
|
|
150
155
|
}
|
|
151
156
|
static arithmetic(operator) {
|
|
152
|
-
return (self, callArguments) => ScopeService.createMember(new ExpressionNode(`${ScopeService.parenthesiseArithmetic(self)} ${operator} ${ScopeService.literal(callArguments[0])}`,
|
|
157
|
+
return (self, callArguments) => ScopeService.createMember(new ExpressionNode(`${ScopeService.parenthesiseArithmetic(self)} ${operator} ${ScopeService.literal(callArguments[0])}`, true));
|
|
153
158
|
}
|
|
154
159
|
static stringMatch(name) {
|
|
155
160
|
return (self, callArguments) => new predicate_util_1.PredicateNode(`${name}(${self.text},${ScopeService.literal(callArguments[0])})`);
|
|
156
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* The number of lambda bodies running at this moment. A lambda takes its
|
|
164
|
+
* alias from it, so a lambda inside another lambda body gets the next
|
|
165
|
+
* letter, also when it opens on a root path.
|
|
166
|
+
*/
|
|
167
|
+
static openLambdas = 0;
|
|
157
168
|
/**
|
|
158
169
|
* A distinct alias letter per lambda nesting level, so an inner lambda never
|
|
159
170
|
* shadows the outer one and `b/x ne a/y` stays expressible.
|
|
@@ -171,8 +182,15 @@ class ScopeService {
|
|
|
171
182
|
throw new invalidFilter_exception_1.InvalidFilterError('all() requires a predicate; the server rejects a bare all()', 'all');
|
|
172
183
|
return new predicate_util_1.PredicateNode(`${self.text}/any()`);
|
|
173
184
|
}
|
|
174
|
-
const alias = ScopeService.lambdaAlias(
|
|
175
|
-
|
|
185
|
+
const alias = ScopeService.lambdaAlias(ScopeService.openLambdas);
|
|
186
|
+
ScopeService.openLambdas += 1;
|
|
187
|
+
let inner;
|
|
188
|
+
try {
|
|
189
|
+
inner = build(ScopeService.createMember(new ExpressionNode(alias)));
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
ScopeService.openLambdas -= 1;
|
|
193
|
+
}
|
|
176
194
|
if (!(inner instanceof predicate_util_1.PredicateNode))
|
|
177
195
|
throw new invalidFilter_exception_1.InvalidFilterError(`${kind}() must return a predicate, not a bare column`, kind);
|
|
178
196
|
// The colon carries no space: the grammar requires `any(a:…)`.
|
|
@@ -195,7 +213,7 @@ class ScopeService {
|
|
|
195
213
|
if (ScopeService.nodeOf(member))
|
|
196
214
|
throw new invalidFilter_exception_1.InvalidFilterError('in() takes literal values only; the server rejects a column or an expression inside in (...)', 'in');
|
|
197
215
|
}
|
|
198
|
-
return new predicate_util_1.PredicateNode(`${self
|
|
216
|
+
return new predicate_util_1.PredicateNode(`${ScopeService.parenthesiseArithmetic(self)} in (${values
|
|
199
217
|
.map((value) => ScopeService.literal(value, true))
|
|
200
218
|
.join(',')})`);
|
|
201
219
|
},
|
|
@@ -211,7 +229,7 @@ class ScopeService {
|
|
|
211
229
|
concat: ScopeService.binaryFunction('concat'),
|
|
212
230
|
substring: (self, callArguments) => ScopeService.createMember(new ExpressionNode(callArguments[1] === undefined
|
|
213
231
|
? `substring(${self.text},${ScopeService.literal(callArguments[0])})`
|
|
214
|
-
: `substring(${self.text},${ScopeService.literal(callArguments[0])},${ScopeService.literal(callArguments[1])})
|
|
232
|
+
: `substring(${self.text},${ScopeService.literal(callArguments[0])},${ScopeService.literal(callArguments[1])})`)),
|
|
215
233
|
indexOf: ScopeService.binaryFunction('indexof'),
|
|
216
234
|
contains: ScopeService.stringMatch('contains'),
|
|
217
235
|
startsWith: ScopeService.stringMatch('startswith'),
|
|
@@ -240,7 +258,7 @@ class ScopeService {
|
|
|
240
258
|
floor: ScopeService.unaryFunction('floor'),
|
|
241
259
|
round: ScopeService.unaryFunction('round'),
|
|
242
260
|
/* type */
|
|
243
|
-
cast: (self, callArguments) => ScopeService.createMember(new ExpressionNode(`cast(${self.text},${callArguments[0]})
|
|
261
|
+
cast: (self, callArguments) => ScopeService.createMember(new ExpressionNode(`cast(${self.text},${callArguments[0]})`)),
|
|
244
262
|
/* lambdas */
|
|
245
263
|
any: ScopeService.lambda('any'),
|
|
246
264
|
all: ScopeService.lambda('all'),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.service.js","sourceRoot":"","sources":["../../../../../src/module/query/service/filter/scope.service.ts"],"names":[],"mappings":";;;AA0CA,qFAA6E;AAC7E,mFAA2E;AAC3E,+DAAsD;AACtD,qEAAiE;AAEjE,MAAa,cAAc;IAEhB;IAEA;
|
|
1
|
+
{"version":3,"file":"scope.service.js","sourceRoot":"","sources":["../../../../../src/module/query/service/filter/scope.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,12 +11,13 @@
|
|
|
11
11
|
* query therefore does not change this class, and a change to this class does
|
|
12
12
|
* not change how the query is printed.
|
|
13
13
|
*
|
|
14
|
-
* `Chain<T>`, `ItemChain<T>` and `
|
|
15
|
-
* this one class. Only the type that a factory returns
|
|
16
|
-
* has every member. `ItemChain<T>` has `select`, `expand`,
|
|
17
|
-
* and `toParams()`. `ExpandChain<T>` has `select`, `expand`,
|
|
18
|
-
* and `skip`, the options that the server accepts inside
|
|
19
|
-
*
|
|
14
|
+
* `Chain<T>`, `ItemChain<T>`, `ExpandChain<T>` and `ToOneExpandChain<T>` are
|
|
15
|
+
* four interfaces over this one class. Only the type that a factory returns
|
|
16
|
+
* differs. `Chain<T>` has every member. `ItemChain<T>` has `select`, `expand`,
|
|
17
|
+
* `toQueryString()` and `toParams()`. `ExpandChain<T>` has `select`, `expand`,
|
|
18
|
+
* `filter`, `top` and `skip`, the options that the server accepts inside the
|
|
19
|
+
* `$expand` of a to-many relation. `ToOneExpandChain<T>` has the same without
|
|
20
|
+
* `top` and `skip`. At runtime, every instance has every member.
|
|
20
21
|
*/
|
|
21
22
|
import type { Chain, QueryParams } from '../domain/chain/chain.model';
|
|
22
23
|
import type { ItemChain } from '../domain/chain/itemChain.model';
|
|
@@ -26,18 +27,27 @@ import type { QueryState } from '../domain/queryState.model';
|
|
|
26
27
|
export declare class QueryChainService {
|
|
27
28
|
readonly queryState: QueryState;
|
|
28
29
|
/**
|
|
29
|
-
* Returns a `Proxy` whose every string property is a
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* `
|
|
30
|
+
* Returns a `Proxy` whose every string property is a member that remembers
|
|
31
|
+
* its path. A call on a member adds the relation at that path; a read from
|
|
32
|
+
* it gives the member one segment further. The relation names exist only in
|
|
33
|
+
* the type system, so there is nothing to enumerate and no allowlist to
|
|
34
|
+
* check. `then`, `toJSON`, `toString` and `valueOf` throw
|
|
35
|
+
* `ReservedNameError`, so the object never passes for a promise, a JSON
|
|
36
|
+
* value or a primitive, and a coercion adds no relation.
|
|
35
37
|
*
|
|
36
38
|
* `chain.expand.parent((parent) => parent.select('name'))` gives
|
|
37
|
-
* `$expand=parent($select=name)
|
|
38
|
-
*
|
|
39
|
+
* `$expand=parent($select=name)`, and `chain.expand.address.supplier()`
|
|
40
|
+
* gives `$expand=address/supplier`. See docs/maintainer/architecture.md,
|
|
41
|
+
* How `Proxy` works here.
|
|
39
42
|
*/
|
|
40
43
|
get expand(): unknown;
|
|
44
|
+
/**
|
|
45
|
+
* The `Proxy` behind `expand` and behind each member read from it. The root
|
|
46
|
+
* target is a plain object, so `chain.expand` itself is not callable; every
|
|
47
|
+
* other target is the call that adds the relation at `path`. The traps are
|
|
48
|
+
* arrow functions, so `this` is the `QueryChainService` and not the handler.
|
|
49
|
+
*/
|
|
50
|
+
private expandPath;
|
|
41
51
|
select(...keys: string[] | [(scope: unknown) => unknown]): this;
|
|
42
52
|
filter(build: (scope: unknown, operators: Operators) => Predicate): this;
|
|
43
53
|
search(term: string, columns: (scope: unknown) => Node | readonly Node[]): this;
|
|
@@ -13,37 +13,51 @@ class QueryChainService {
|
|
|
13
13
|
filters: [],
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
|
-
* Returns a `Proxy` whose every string property is a
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* `
|
|
16
|
+
* Returns a `Proxy` whose every string property is a member that remembers
|
|
17
|
+
* its path. A call on a member adds the relation at that path; a read from
|
|
18
|
+
* it gives the member one segment further. The relation names exist only in
|
|
19
|
+
* the type system, so there is nothing to enumerate and no allowlist to
|
|
20
|
+
* check. `then`, `toJSON`, `toString` and `valueOf` throw
|
|
21
|
+
* `ReservedNameError`, so the object never passes for a promise, a JSON
|
|
22
|
+
* value or a primitive, and a coercion adds no relation.
|
|
22
23
|
*
|
|
23
24
|
* `chain.expand.parent((parent) => parent.select('name'))` gives
|
|
24
|
-
* `$expand=parent($select=name)
|
|
25
|
-
*
|
|
25
|
+
* `$expand=parent($select=name)`, and `chain.expand.address.supplier()`
|
|
26
|
+
* gives `$expand=address/supplier`. See docs/maintainer/architecture.md,
|
|
27
|
+
* How `Proxy` works here.
|
|
26
28
|
*/
|
|
27
29
|
get expand() {
|
|
28
|
-
return
|
|
30
|
+
return this.expandPath(Object.create(null), '');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The `Proxy` behind `expand` and behind each member read from it. The root
|
|
34
|
+
* target is a plain object, so `chain.expand` itself is not callable; every
|
|
35
|
+
* other target is the call that adds the relation at `path`. The traps are
|
|
36
|
+
* arrow functions, so `this` is the `QueryChainService` and not the handler.
|
|
37
|
+
*/
|
|
38
|
+
expandPath(target, path) {
|
|
39
|
+
return new Proxy(target, {
|
|
29
40
|
get: (_target, property) => {
|
|
30
41
|
if (typeof property !== 'string')
|
|
31
42
|
return undefined;
|
|
32
|
-
if (property === 'then' ||
|
|
43
|
+
if (property === 'then' ||
|
|
44
|
+
property === 'toJSON' ||
|
|
45
|
+
property === 'toString' ||
|
|
46
|
+
property === 'valueOf')
|
|
33
47
|
throw new reservedName_exception_1.ReservedNameError(property);
|
|
34
48
|
if (property === 'constructor')
|
|
35
49
|
return undefined;
|
|
36
|
-
|
|
50
|
+
const name = path ? `${path}/${property}` : property;
|
|
51
|
+
return this.expandPath((build) => {
|
|
37
52
|
const child = new QueryChainService();
|
|
38
53
|
build?.(child);
|
|
39
54
|
this.queryState.expand.push({
|
|
40
|
-
name
|
|
55
|
+
name,
|
|
41
56
|
queryState: child.queryState,
|
|
42
57
|
});
|
|
43
58
|
return this;
|
|
44
|
-
};
|
|
59
|
+
}, name);
|
|
45
60
|
},
|
|
46
|
-
has: (_target, property) => typeof property === 'string',
|
|
47
61
|
});
|
|
48
62
|
}
|
|
49
63
|
select(...keys) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryChain.service.js","sourceRoot":"","sources":["../../../../src/module/query/service/queryChain.service.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"queryChain.service.js","sourceRoot":"","sources":["../../../../src/module/query/service/queryChain.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,6 +27,8 @@ const operand = (predicate) => predicate instanceof PredicateNode && predicate.c
|
|
|
27
27
|
const combine = (operator, parts) => {
|
|
28
28
|
if (parts.length === 0)
|
|
29
29
|
throw new invalidFilter_exception_1.InvalidFilterError(`${operator}() needs at least one predicate`, operator);
|
|
30
|
+
if (parts.some((part) => !(part instanceof PredicateNode)))
|
|
31
|
+
throw new invalidFilter_exception_1.InvalidFilterError(`${operator}() takes predicates, not a bare column`, operator);
|
|
30
32
|
if (parts.length === 1)
|
|
31
33
|
return parts[0];
|
|
32
34
|
return new PredicateNode(parts.map(operand).join(` ${operator} `), true);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"predicate.util.js","sourceRoot":"","sources":["../../../../../src/module/query/util/filter/predicate.util.ts"],"names":[],"mappings":";;;AASA,qFAA6E;AAE7E,MAAa,aAAa;IAGf;IAEA;IAJD,WAAW,GAAG,IAAa,CAAC;IACrC,YACU,IAAY;IACrB,sEAAsE;IAC7D,YAAqB,KAAK;QAF1B,SAAI,GAAJ,IAAI,CAAQ;QAEZ,cAAS,GAAT,SAAS,CAAiB;IACjC,CAAC;IACJ,GAAG,CAAC,GAAG,MAAmB;QACzB,OAAO,IAAA,eAAO,EAAC,KAAK,EAAE,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;IAC1C,CAAC;IACD,EAAE,CAAC,GAAG,MAAmB;QACxB,OAAO,IAAA,eAAO,EAAC,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;IACzC,CAAC;CACD;AAbD,sCAaC;AAED,wEAAwE;AACxE,MAAM,OAAO,GAAG,CAAC,SAAoB,EAAU,EAAE,CAChD,SAAS,YAAY,aAAa,IAAI,SAAS,CAAC,SAAS;IACxD,CAAC,CAAC,IAAI,SAAS,CAAC,IAAI,GAAG;IACvB,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC;AAEZ,MAAM,OAAO,GAAG,CACtB,QAAsB,EACtB,KAAkB,EACN,EAAE;IACd,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QACrB,MAAM,IAAI,4CAAkB,CAC3B,GAAG,QAAQ,iCAAiC,EAC5C,QAAQ,CACR,CAAC;IACH,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;IACxC,OAAO,IAAI,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,QAAQ,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AAC1E,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"predicate.util.js","sourceRoot":"","sources":["../../../../../src/module/query/util/filter/predicate.util.ts"],"names":[],"mappings":";;;AASA,qFAA6E;AAE7E,MAAa,aAAa;IAGf;IAEA;IAJD,WAAW,GAAG,IAAa,CAAC;IACrC,YACU,IAAY;IACrB,sEAAsE;IAC7D,YAAqB,KAAK;QAF1B,SAAI,GAAJ,IAAI,CAAQ;QAEZ,cAAS,GAAT,SAAS,CAAiB;IACjC,CAAC;IACJ,GAAG,CAAC,GAAG,MAAmB;QACzB,OAAO,IAAA,eAAO,EAAC,KAAK,EAAE,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;IAC1C,CAAC;IACD,EAAE,CAAC,GAAG,MAAmB;QACxB,OAAO,IAAA,eAAO,EAAC,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;IACzC,CAAC;CACD;AAbD,sCAaC;AAED,wEAAwE;AACxE,MAAM,OAAO,GAAG,CAAC,SAAoB,EAAU,EAAE,CAChD,SAAS,YAAY,aAAa,IAAI,SAAS,CAAC,SAAS;IACxD,CAAC,CAAC,IAAI,SAAS,CAAC,IAAI,GAAG;IACvB,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC;AAEZ,MAAM,OAAO,GAAG,CACtB,QAAsB,EACtB,KAAkB,EACN,EAAE;IACd,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QACrB,MAAM,IAAI,4CAAkB,CAC3B,GAAG,QAAQ,iCAAiC,EAC5C,QAAQ,CACR,CAAC;IACH,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,YAAY,aAAa,CAAC,CAAC;QACzD,MAAM,IAAI,4CAAkB,CAC3B,GAAG,QAAQ,wCAAwC,EACnD,QAAQ,CACR,CAAC;IACH,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;IACxC,OAAO,IAAI,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,QAAQ,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AAC1E,CAAC,CAAC;AAhBW,QAAA,OAAO,WAgBlB"}
|
package/package.json
CHANGED