@ballistix.digital/odata-query-builder 0.4.0 → 0.6.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 +6 -7
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/module/query/domain/chain/chain.model.d.ts +28 -5
- package/dist/module/query/domain/chain/expandChain.model.d.ts +6 -3
- package/dist/module/query/domain/chain/itemChain.model.d.ts +6 -3
- package/dist/module/query/domain/exceptionCode.model.js.map +1 -0
- package/dist/module/query/domain/exceptionDetail.model.js.map +1 -0
- package/dist/module/query/domain/filter/castable.model.d.ts +10 -1
- package/dist/module/{common/domain → query/domain/filter}/scalar.model.d.ts +4 -7
- package/dist/module/query/domain/filter/scalar.model.js +11 -0
- package/dist/module/query/domain/filter/scalar.model.js.map +1 -0
- package/dist/module/query/domain/filter/scope.model.d.ts +17 -1
- package/dist/module/query/exception/invalidFilter.exception.d.ts +1 -1
- package/dist/module/query/exception/invalidFilter.exception.js +2 -2
- package/dist/module/query/exception/invalidFilter.exception.js.map +1 -1
- package/dist/module/{common → query}/exception/queryBuilder.exception.d.ts +3 -2
- package/dist/module/{common → query}/exception/queryBuilder.exception.js +3 -2
- package/dist/module/{common → query}/exception/queryBuilder.exception.js.map +1 -1
- package/dist/module/query/exception/reservedName.exception.d.ts +1 -1
- package/dist/module/query/exception/reservedName.exception.js +2 -2
- package/dist/module/query/exception/reservedName.exception.js.map +1 -1
- package/dist/module/query/service/emit/emit.facade.d.ts +8 -0
- package/dist/module/query/service/emit/emit.facade.js +1 -9
- package/dist/module/query/service/emit/emit.facade.js.map +1 -1
- package/dist/module/query/service/filter/filter.facade.d.ts +15 -0
- package/dist/module/query/service/filter/filter.facade.js +19 -22
- package/dist/module/query/service/filter/filter.facade.js.map +1 -1
- package/dist/module/query/service/queryChain.service.d.ts +6 -5
- package/dist/module/query/service/queryChain.service.js +6 -2
- package/dist/module/query/service/queryChain.service.js.map +1 -1
- package/dist/module/{common/util → query/util/filter}/escape.util.d.ts +2 -3
- package/dist/module/{common/util → query/util/filter}/escape.util.js +2 -3
- package/dist/module/query/util/filter/escape.util.js.map +1 -0
- package/dist/module/query/util/filter/literal.util.js +1 -1
- package/dist/module/query/util/filter/literal.util.js.map +1 -1
- package/package.json +1 -1
- package/dist/module/common/domain/exceptionCode.model.js.map +0 -1
- package/dist/module/common/domain/exceptionDetail.model.js.map +0 -1
- package/dist/module/common/domain/scalar.model.js +0 -14
- package/dist/module/common/domain/scalar.model.js.map +0 -1
- package/dist/module/common/util/escape.util.js.map +0 -1
- package/dist/module/query/domain/chain/expandNamespace.model.d.ts +0 -72
- package/dist/module/query/domain/chain/expandNamespace.model.js +0 -3
- package/dist/module/query/domain/chain/expandNamespace.model.js.map +0 -1
- /package/dist/module/{common → query}/domain/exceptionCode.model.d.ts +0 -0
- /package/dist/module/{common → query}/domain/exceptionCode.model.js +0 -0
- /package/dist/module/{common → query}/domain/exceptionDetail.model.d.ts +0 -0
- /package/dist/module/{common → query}/domain/exceptionDetail.model.js +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -6,14 +6,11 @@
|
|
|
6
6
|
* 400 is deliberately absent, so it is a compile error rather than a runtime
|
|
7
7
|
* failure.
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
10
|
-
import type { ExceptionDetail } from './module/common/domain/exceptionDetail.model';
|
|
11
|
-
import type { Scalar, Unwrap } from './module/common/domain/scalar.model';
|
|
12
|
-
import { QueryBuilderException } from './module/common/exception/queryBuilder.exception';
|
|
13
|
-
import type { Chain, QueryParams } from './module/query/domain/chain/chain.model';
|
|
9
|
+
import type { Chain, ExpandKey, ExpandNamespace, QueryParams } from './module/query/domain/chain/chain.model';
|
|
14
10
|
import type { ExpandChain } from './module/query/domain/chain/expandChain.model';
|
|
15
|
-
import type { EmbeddedPathKeys, ExpandKey, ExpandNamespace, FieldKey, OrderKey } from './module/query/domain/chain/expandNamespace.model';
|
|
16
11
|
import type { ItemChain } from './module/query/domain/chain/itemChain.model';
|
|
12
|
+
import { QueryBuilderExceptionCode } from './module/query/domain/exceptionCode.model';
|
|
13
|
+
import type { ExceptionDetail } from './module/query/domain/exceptionDetail.model';
|
|
17
14
|
import type { BooleanExpr } from './module/query/domain/filter/booleanExpr.model';
|
|
18
15
|
import type { Castable, CastResult, EdmTarget } from './module/query/domain/filter/castable.model';
|
|
19
16
|
import type { Comparable } from './module/query/domain/filter/comparable.model';
|
|
@@ -21,11 +18,13 @@ import type { DateExpr, DateInput } from './module/query/domain/filter/dateExpr.
|
|
|
21
18
|
import type { Node, Predicate } from './module/query/domain/filter/node.model';
|
|
22
19
|
import type { NumberExpr } from './module/query/domain/filter/numberExpr.model';
|
|
23
20
|
import type { Operators } from './module/query/domain/filter/operators.model';
|
|
21
|
+
import type { Scalar, Unwrap } from './module/query/domain/filter/scalar.model';
|
|
24
22
|
import type { EmbeddedObjectKeys, EmbeddedOf, ExprFor, LambdaNamespace, OwnKeys, PrimitiveArrayKeys, PrimitiveLambdaNamespace, Relation, ScalarFieldKeys, Scope, ToManyKeys, ToOneKeys } from './module/query/domain/filter/scope.model';
|
|
25
23
|
import type { StringExpr } from './module/query/domain/filter/stringExpr.model';
|
|
26
24
|
import { InvalidFilterError } from './module/query/exception/invalidFilter.exception';
|
|
25
|
+
import { QueryBuilderException } from './module/query/exception/queryBuilder.exception';
|
|
27
26
|
import { ReservedNameError } from './module/query/exception/reservedName.exception';
|
|
28
27
|
import { and, maxdatetime, mindatetime, not, now, or, raw } from './module/query/service/filter/filter.facade';
|
|
29
28
|
import { odataItem, odataQuery } from './module/query/service/queryChain.service';
|
|
30
29
|
export { InvalidFilterError, QueryBuilderException, QueryBuilderExceptionCode, ReservedNameError, and, maxdatetime, mindatetime, not, now, odataItem, odataQuery, or, raw, };
|
|
31
|
-
export type { BooleanExpr, CastResult, Castable, Chain, Comparable, DateExpr, DateInput, EdmTarget, EmbeddedObjectKeys, EmbeddedOf,
|
|
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, };
|
package/dist/index.js
CHANGED
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
*/
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
11
|
exports.raw = exports.or = exports.odataQuery = exports.odataItem = exports.now = exports.not = exports.mindatetime = exports.maxdatetime = exports.and = exports.ReservedNameError = exports.QueryBuilderExceptionCode = exports.QueryBuilderException = exports.InvalidFilterError = void 0;
|
|
12
|
-
const exceptionCode_model_1 = require("./module/
|
|
12
|
+
const exceptionCode_model_1 = require("./module/query/domain/exceptionCode.model");
|
|
13
13
|
Object.defineProperty(exports, "QueryBuilderExceptionCode", { enumerable: true, get: function () { return exceptionCode_model_1.QueryBuilderExceptionCode; } });
|
|
14
|
-
const queryBuilder_exception_1 = require("./module/common/exception/queryBuilder.exception");
|
|
15
|
-
Object.defineProperty(exports, "QueryBuilderException", { enumerable: true, get: function () { return queryBuilder_exception_1.QueryBuilderException; } });
|
|
16
14
|
const invalidFilter_exception_1 = require("./module/query/exception/invalidFilter.exception");
|
|
17
15
|
Object.defineProperty(exports, "InvalidFilterError", { enumerable: true, get: function () { return invalidFilter_exception_1.InvalidFilterError; } });
|
|
16
|
+
const queryBuilder_exception_1 = require("./module/query/exception/queryBuilder.exception");
|
|
17
|
+
Object.defineProperty(exports, "QueryBuilderException", { enumerable: true, get: function () { return queryBuilder_exception_1.QueryBuilderException; } });
|
|
18
18
|
const reservedName_exception_1 = require("./module/query/exception/reservedName.exception");
|
|
19
19
|
Object.defineProperty(exports, "ReservedNameError", { enumerable: true, get: function () { return reservedName_exception_1.ReservedNameError; } });
|
|
20
20
|
const filter_facade_1 = require("./module/query/service/filter/filter.facade");
|
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;;;AAUH,mFAAsF;AAoDrF,0GApDQ,+CAAyB,OAoDR;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"}
|
|
@@ -3,23 +3,46 @@
|
|
|
3
3
|
*
|
|
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
|
+
*
|
|
7
|
+
* `ExpandNamespace` is the type of the `expand` member of all three chain
|
|
8
|
+
* types. It holds one function per relation of the DTO, typed from
|
|
9
|
+
* `_embedded`: `q.expand.` lists exactly the relations `_embedded` declares,
|
|
10
|
+
* and each callback is typed to the entity that relation reaches. There is no
|
|
11
|
+
* build step and no `$metadata` document.
|
|
6
12
|
*/
|
|
7
13
|
import type { Predicate } from '../filter/node.model';
|
|
8
14
|
import type { Operators } from '../filter/operators.model';
|
|
9
|
-
import type { Scope } from '../filter/scope.model';
|
|
15
|
+
import type { ColumnExpr, Relation, ScalarFieldKeys, Scope, SelectScope, ToManyKeys, ToOneKeys } from '../filter/scope.model';
|
|
10
16
|
import type { StringExpr } from '../filter/stringExpr.model';
|
|
11
|
-
import type {
|
|
17
|
+
import type { ExpandChain } from './expandChain.model';
|
|
12
18
|
/** A flat `{ $option: value }` map, for a caller that serialises its own URL. */
|
|
13
19
|
export type QueryParams = Record<string, string>;
|
|
20
|
+
/** Every expandable relation name of a DTO. A real allowlist. */
|
|
21
|
+
export type ExpandKey<T> = ToOneKeys<T> | ToManyKeys<T>;
|
|
22
|
+
/**
|
|
23
|
+
* `Self` is the chain the call returns, so `expand.a(...).expand.b(...)`
|
|
24
|
+
* chains at whatever level it is written.
|
|
25
|
+
*/
|
|
26
|
+
export type ExpandNamespace<T, Self> = {
|
|
27
|
+
readonly [K in ExpandKey<T>]: (build?: (chain: ExpandChain<Relation<T, K>>) => unknown) => Self;
|
|
28
|
+
};
|
|
14
29
|
export interface Chain<T> {
|
|
15
30
|
readonly expand: ExpandNamespace<T, Chain<T>>;
|
|
16
|
-
|
|
31
|
+
/** Own columns, by name. */
|
|
32
|
+
select(...keys: ScalarFieldKeys<T>[]): Chain<T>;
|
|
33
|
+
/** Own columns and embedded leaves: `select((v) => [v.id, v.address.city])`. */
|
|
34
|
+
select(columns: (scope: SelectScope<T>) => ColumnExpr | readonly ColumnExpr[]): Chain<T>;
|
|
17
35
|
/** Repeated calls AND together. */
|
|
18
36
|
filter(build: (scope: Scope<T>, operators: Operators) => Predicate): Chain<T>;
|
|
19
37
|
/** `$search` + its mandatory `$searchColumns`, as one verb. */
|
|
20
38
|
search(term: string, columns: (scope: Scope<T>) => StringExpr | readonly StringExpr[]): Chain<T>;
|
|
21
|
-
/** Sorts on an own column,
|
|
22
|
-
orderBy(key:
|
|
39
|
+
/** Sorts on an own column, by name. */
|
|
40
|
+
orderBy(key: ScalarFieldKeys<T>, direction?: 'asc' | 'desc'): Chain<T>;
|
|
41
|
+
/**
|
|
42
|
+
* Sorts on the column the callback reads: an embedded leaf, or a column at
|
|
43
|
+
* any depth of to-one relations: `orderBy((v) => v.owner.organisation.code)`.
|
|
44
|
+
*/
|
|
45
|
+
orderBy(column: (scope: Scope<T>) => ColumnExpr, direction?: 'asc' | 'desc'): Chain<T>;
|
|
23
46
|
top(count: number): Chain<T>;
|
|
24
47
|
skip(count: number): Chain<T>;
|
|
25
48
|
count(on?: boolean): Chain<T>;
|
|
@@ -15,11 +15,14 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import type { Predicate } from '../filter/node.model';
|
|
17
17
|
import type { Operators } from '../filter/operators.model';
|
|
18
|
-
import type { Scope } from '../filter/scope.model';
|
|
19
|
-
import type { ExpandNamespace
|
|
18
|
+
import type { ColumnExpr, ScalarFieldKeys, Scope, SelectScope } from '../filter/scope.model';
|
|
19
|
+
import type { ExpandNamespace } from './chain.model';
|
|
20
20
|
export interface ExpandChain<T> {
|
|
21
21
|
readonly expand: ExpandNamespace<T, ExpandChain<T>>;
|
|
22
|
-
|
|
22
|
+
/** Own columns, by name. */
|
|
23
|
+
select(...keys: ScalarFieldKeys<T>[]): ExpandChain<T>;
|
|
24
|
+
/** Own columns and embedded leaves: `select((v) => [v.id, v.address.city])`. */
|
|
25
|
+
select(columns: (scope: SelectScope<T>) => ColumnExpr | readonly ColumnExpr[]): ExpandChain<T>;
|
|
23
26
|
/**
|
|
24
27
|
* `$expand=rel($filter=…)`. The scope is the EXPANDED entity, so paths are
|
|
25
28
|
* written relative to it, not to the root. Repeated calls AND together.
|
|
@@ -5,11 +5,14 @@
|
|
|
5
5
|
* `$count` and `$search` have nothing to act on. Only the shaping options are
|
|
6
6
|
* offered.
|
|
7
7
|
*/
|
|
8
|
-
import type {
|
|
9
|
-
import type { ExpandNamespace,
|
|
8
|
+
import type { ColumnExpr, ScalarFieldKeys, SelectScope } from '../filter/scope.model';
|
|
9
|
+
import type { ExpandNamespace, QueryParams } from './chain.model';
|
|
10
10
|
export interface ItemChain<T> {
|
|
11
11
|
readonly expand: ExpandNamespace<T, ItemChain<T>>;
|
|
12
|
-
|
|
12
|
+
/** Own columns, by name. */
|
|
13
|
+
select(...keys: ScalarFieldKeys<T>[]): ItemChain<T>;
|
|
14
|
+
/** Own columns and embedded leaves: `select((v) => [v.id, v.address.city])`. */
|
|
15
|
+
select(columns: (scope: SelectScope<T>) => ColumnExpr | readonly ColumnExpr[]): ItemChain<T>;
|
|
13
16
|
toQueryString(): string;
|
|
14
17
|
/**
|
|
15
18
|
* The same query as separate parts, with the transport escaping undone, for
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exceptionCode.model.js","sourceRoot":"","sources":["../../../../src/module/query/domain/exceptionCode.model.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAEH,IAAY,yBAGX;AAHD,WAAY,yBAAyB;IACpC,4DAA+B,CAAA;IAC/B,8DAAiC,CAAA;AAClC,CAAC,EAHW,yBAAyB,yCAAzB,yBAAyB,QAGpC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exceptionDetail.model.js","sourceRoot":"","sources":["../../../../src/module/query/domain/exceptionDetail.model.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG"}
|
|
@@ -9,7 +9,16 @@ import type { BooleanExpr } from './booleanExpr.model';
|
|
|
9
9
|
import type { DateExpr } from './dateExpr.model';
|
|
10
10
|
import type { NumberExpr } from './numberExpr.model';
|
|
11
11
|
import type { StringExpr } from './stringExpr.model';
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* The 13 Edm targets the server maps onto a Postgres type: the OData v4
|
|
14
|
+
* primitive type names that typeorm-extensions can cast to (`CAST_TARGETS`).
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* odataQuery<ProjectDto>().filter((v) => v.budget.cast('Edm.Int64').gt(1000)).toQueryString();
|
|
18
|
+
* // $filter=cast(budget,Edm.Int64) gt 1000
|
|
19
|
+
* ```
|
|
20
|
+
* The server runs it as `CAST(budget AS bigint) > 1000`.
|
|
21
|
+
*/
|
|
13
22
|
export type EdmTarget = 'Edm.String' | 'Edm.Int16' | 'Edm.Int32' | 'Edm.Int64' | 'Edm.Single' | 'Edm.Double' | 'Edm.Decimal' | 'Edm.Boolean' | 'Edm.Date' | 'Edm.DateTimeOffset' | 'Edm.TimeOfDay' | 'Edm.Guid' | 'Edm.Duration';
|
|
14
23
|
export type CastResult<T extends EdmTarget> = T extends 'Edm.Boolean' ? BooleanExpr : T extends 'Edm.Int16' | 'Edm.Int32' | 'Edm.Int64' | 'Edm.Single' | 'Edm.Double' | 'Edm.Decimal' ? NumberExpr : T extends 'Edm.Date' | 'Edm.DateTimeOffset' ? DateExpr : StringExpr;
|
|
15
24
|
export interface Castable {
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The two type primitives
|
|
3
|
-
*
|
|
4
|
-
* They live in `common` because both the filter module (which turns a DTO into
|
|
5
|
-
* a filter scope) and the query module (which turns a DTO into a select/expand
|
|
6
|
-
* namespace) need the same answer to "is this a column or a relation".
|
|
2
|
+
* The two type primitives `Scope` (in `scope.model.ts`) reads a DTO with, to
|
|
3
|
+
* answer "is this a column or a relation".
|
|
7
4
|
*
|
|
8
5
|
* `Scalar` admits only the five shapes the dialect can compare, sort or
|
|
9
|
-
* select directly; an object or array field never matches it, so
|
|
10
|
-
*
|
|
6
|
+
* select directly; an object or array field never matches it, so `Scope`
|
|
7
|
+
* routes it through `Unwrap` and the embedding types instead.
|
|
11
8
|
*/
|
|
12
9
|
/** A DTO property this dialect can compare, sort or select. */
|
|
13
10
|
export type Scalar = string | number | boolean | bigint | Date;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The two type primitives `Scope` (in `scope.model.ts`) reads a DTO with, to
|
|
4
|
+
* answer "is this a column or a relation".
|
|
5
|
+
*
|
|
6
|
+
* `Scalar` admits only the five shapes the dialect can compare, sort or
|
|
7
|
+
* select directly; an object or array field never matches it, so `Scope`
|
|
8
|
+
* routes it through `Unwrap` and the embedding types instead.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
//# sourceMappingURL=scalar.model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scalar.model.js","sourceRoot":"","sources":["../../../../../src/module/query/domain/filter/scalar.model.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG"}
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
* keeps every self-reference in a mapped type's value position, where
|
|
13
13
|
* instantiation is deferred until a property is actually read.
|
|
14
14
|
*/
|
|
15
|
-
import type { Scalar, Unwrap } from '../../../common/domain/scalar.model';
|
|
16
15
|
import type { BooleanExpr } from './booleanExpr.model';
|
|
17
16
|
import type { DateExpr } from './dateExpr.model';
|
|
18
17
|
import type { Predicate } from './node.model';
|
|
19
18
|
import type { NumberExpr } from './numberExpr.model';
|
|
19
|
+
import type { Scalar, Unwrap } from './scalar.model';
|
|
20
20
|
import type { StringExpr } from './stringExpr.model';
|
|
21
21
|
/** The expression type a column of type `V` is read as. */
|
|
22
22
|
export type ExprFor<V> = [NonNullable<V>] extends [never] ? never : NonNullable<V> extends boolean ? BooleanExpr : NonNullable<V> extends Date ? DateExpr : NonNullable<V> extends number | bigint ? NumberExpr<NonNullable<V>> : NonNullable<V> extends string ? StringExpr<NonNullable<V>> : never;
|
|
@@ -92,3 +92,19 @@ export type Scope<T> = {
|
|
|
92
92
|
} & {
|
|
93
93
|
readonly [K in Exclude<ToManyKeys<T>, OwnKeys<T>>]: LambdaNamespace<Relation<T, K>>;
|
|
94
94
|
};
|
|
95
|
+
/**
|
|
96
|
+
* One column, as a `select` or `orderBy` callback returns it. A to-one
|
|
97
|
+
* relation reads as a `Scope` and a to-many as a `LambdaNamespace`, so neither
|
|
98
|
+
* fits.
|
|
99
|
+
*/
|
|
100
|
+
export type ColumnExpr = StringExpr<string> | NumberExpr<number | bigint> | DateExpr | BooleanExpr;
|
|
101
|
+
/**
|
|
102
|
+
* What a `select` callback reads: own columns and embedded objects, never a
|
|
103
|
+
* relation. A relation column comes through `$expand`, so `owner/email` is
|
|
104
|
+
* not a `$select` path.
|
|
105
|
+
*/
|
|
106
|
+
export type SelectScope<T> = {
|
|
107
|
+
readonly [K in ScalarFieldKeys<T>]: ExprFor<T[K]>;
|
|
108
|
+
} & {
|
|
109
|
+
readonly [K in EmbeddedObjectKeys<T>]: SelectScope<NonNullable<T[K]>>;
|
|
110
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { QueryBuilderException } from '
|
|
1
|
+
import { QueryBuilderException } from './queryBuilder.exception';
|
|
2
2
|
export declare class InvalidFilterError extends QueryBuilderException {
|
|
3
3
|
constructor(reason: string, subject?: string);
|
|
4
4
|
}
|
|
@@ -8,8 +8,8 @@ exports.InvalidFilterError = void 0;
|
|
|
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
10
|
*/
|
|
11
|
-
const exceptionCode_model_1 = require("
|
|
12
|
-
const queryBuilder_exception_1 = require("
|
|
11
|
+
const exceptionCode_model_1 = require("../domain/exceptionCode.model");
|
|
12
|
+
const queryBuilder_exception_1 = require("./queryBuilder.exception");
|
|
13
13
|
class InvalidFilterError extends queryBuilder_exception_1.QueryBuilderException {
|
|
14
14
|
constructor(reason, subject) {
|
|
15
15
|
super(exceptionCode_model_1.QueryBuilderExceptionCode.INVALID_FILTER, reason, [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invalidFilter.exception.js","sourceRoot":"","sources":["../../../../src/module/query/exception/invalidFilter.exception.ts"],"names":[],"mappings":";;;AAAA;;;;;;GAMG;AACH,
|
|
1
|
+
{"version":3,"file":"invalidFilter.exception.js","sourceRoot":"","sources":["../../../../src/module/query/exception/invalidFilter.exception.ts"],"names":[],"mappings":";;;AAAA;;;;;;GAMG;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"}
|
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
* type: that package exports its own, unrelated `LibraryException` and
|
|
10
10
|
* `ExceptionCode`, so this class is never an `instanceof` that one.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* Every error class in `exception/` extends it. It imports only its two
|
|
13
|
+
* envelope types, `QueryBuilderExceptionCode` and `ExceptionDetail`, and
|
|
14
|
+
* depends on no framework.
|
|
14
15
|
*/
|
|
15
16
|
import type { QueryBuilderExceptionCode } from '../domain/exceptionCode.model';
|
|
16
17
|
import type { ExceptionDetail } from '../domain/exceptionDetail.model';
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
* type: that package exports its own, unrelated `LibraryException` and
|
|
11
11
|
* `ExceptionCode`, so this class is never an `instanceof` that one.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* Every error class in `exception/` extends it. It imports only its two
|
|
14
|
+
* envelope types, `QueryBuilderExceptionCode` and `ExceptionDetail`, and
|
|
15
|
+
* depends on no framework.
|
|
15
16
|
*/
|
|
16
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
18
|
exports.QueryBuilderException = void 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryBuilder.exception.js","sourceRoot":"","sources":["../../../../src/module/
|
|
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,qEAAqE;IAC5D,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;AAtBD,sDAsBC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { QueryBuilderException } from '
|
|
1
|
+
import { QueryBuilderException } from './queryBuilder.exception';
|
|
2
2
|
export declare class ReservedNameError extends QueryBuilderException {
|
|
3
3
|
readonly reservedName: string;
|
|
4
4
|
constructor(reservedName: string);
|
|
@@ -8,8 +8,8 @@ exports.ReservedNameError = void 0;
|
|
|
8
8
|
* thenable and hang; reading `toJSON` would make `JSON.stringify(q)` produce
|
|
9
9
|
* silent nonsense. Both throw instead of returning a value.
|
|
10
10
|
*/
|
|
11
|
-
const exceptionCode_model_1 = require("
|
|
12
|
-
const queryBuilder_exception_1 = require("
|
|
11
|
+
const exceptionCode_model_1 = require("../domain/exceptionCode.model");
|
|
12
|
+
const queryBuilder_exception_1 = require("./queryBuilder.exception");
|
|
13
13
|
class ReservedNameError extends queryBuilder_exception_1.QueryBuilderException {
|
|
14
14
|
reservedName;
|
|
15
15
|
constructor(reservedName) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reservedName.exception.js","sourceRoot":"","sources":["../../../../src/module/query/exception/reservedName.exception.ts"],"names":[],"mappings":";;;AAAA;;;;;;GAMG;AACH,
|
|
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,wDAAwD;YACvE,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"}
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The only file that other code imports from the emit stage: a `QueryState`
|
|
3
|
+
* in, the query text out.
|
|
4
|
+
*
|
|
5
|
+
* Both entry functions read the same ordered parts, so the string form and the
|
|
6
|
+
* map form can never disagree about what the query says — they differ only in
|
|
7
|
+
* the transport escaping each one leaves in place.
|
|
8
|
+
*/
|
|
1
9
|
import type { QueryState } from '../../domain/queryState.model';
|
|
2
10
|
export declare const emitQueryString: (queryState: QueryState) => string;
|
|
3
11
|
/**
|
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.emitQueryParams = exports.emitQueryString = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* The only file that other code imports from the emit stage: a `QueryState`
|
|
6
|
-
* in, the query text out.
|
|
7
|
-
*
|
|
8
|
-
* Both entry functions read the same ordered parts, so the string form and the
|
|
9
|
-
* map form can never disagree about what the query says — they differ only in
|
|
10
|
-
* the transport escaping each one leaves in place.
|
|
11
|
-
*/
|
|
12
|
-
const escape_util_1 = require("../../../common/util/escape.util");
|
|
13
4
|
const queryParts_util_1 = require("../../util/emit/queryParts.util");
|
|
5
|
+
const escape_util_1 = require("../../util/filter/escape.util");
|
|
14
6
|
const emitQueryString = (queryState) => (0, queryParts_util_1.toQueryParts)(queryState)
|
|
15
7
|
.map(([key, value]) => `${key}=${value}`)
|
|
16
8
|
.join('&');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.facade.js","sourceRoot":"","sources":["../../../../../src/module/query/service/emit/emit.facade.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"emit.facade.js","sourceRoot":"","sources":["../../../../../src/module/query/service/emit/emit.facade.ts"],"names":[],"mappings":";;;AASA,qEAA+D;AAC/D,+DAAmE;AAE5D,MAAM,eAAe,GAAG,CAAC,UAAsB,EAAU,EAAE,CACjE,IAAA,8BAAY,EAAC,UAAU,CAAC;KACtB,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;KACxC,IAAI,CAAC,GAAG,CAAC,CAAC;AAHA,QAAA,eAAe,mBAGf;AAEb;;;;GAIG;AACI,MAAM,eAAe,GAAG,CAC9B,UAAsB,EACG,EAAE;IAC3B,MAAM,WAAW,GAA2B,EAAE,CAAC;IAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAA,8BAAY,EAAC,UAAU,CAAC,EAAE,CAAC;QACrD,WAAW,CAAC,GAAG,CAAC,GAAG,IAAA,gCAAkB,EAAC,KAAK,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,WAAW,CAAC;AACpB,CAAC,CAAC;AARW,QAAA,eAAe,mBAQ1B"}
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The only file that other code imports from the filter stage: the combinators
|
|
3
|
+
* a caller writes, and the four entry functions that run a caller's callback
|
|
4
|
+
* against a fresh scope.
|
|
5
|
+
*
|
|
6
|
+
* A scope proxy never leaves this stage as itself. `buildFilterPredicate`
|
|
7
|
+
* hands one to the callback and returns the predicate that comes back;
|
|
8
|
+
* `pickSearchColumns`, `pickOrderColumn` and `pickSelectColumns` hand one out
|
|
9
|
+
* and return plain text. Nothing outside the stage therefore has to know that
|
|
10
|
+
* a scope is a Proxy at all.
|
|
11
|
+
*/
|
|
1
12
|
import type { Node, Predicate } from '../../domain/filter/node.model';
|
|
2
13
|
import type { DateExpr } from '../../domain/filter/dateExpr.model';
|
|
3
14
|
import type { Operators } from '../../domain/filter/operators.model';
|
|
@@ -20,3 +31,7 @@ export declare const buildFilterPredicate: (build: (scope: unknown, operators: O
|
|
|
20
31
|
* so an empty column list is rejected before the query is ever emitted.
|
|
21
32
|
*/
|
|
22
33
|
export declare const pickSearchColumns: (term: string, columns: (scope: unknown) => Node | readonly Node[]) => SearchState;
|
|
34
|
+
/** Run one `.orderBy()` callback and return the path of the column it picks. */
|
|
35
|
+
export declare const pickOrderColumn: (column: (scope: unknown) => unknown) => string;
|
|
36
|
+
/** Run one `.select()` callback and return the paths of the columns it picks. */
|
|
37
|
+
export declare const pickSelectColumns: (columns: (scope: unknown) => unknown) => string[];
|
|
@@ -1,18 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.pickSearchColumns = exports.buildFilterPredicate = exports.raw = exports.mindatetime = exports.maxdatetime = exports.now = exports.not = exports.or = exports.and = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* The only file that other code imports from the filter stage: the combinators
|
|
6
|
-
* a caller writes, and the two entry functions that run a caller's callback
|
|
7
|
-
* against a fresh scope.
|
|
8
|
-
*
|
|
9
|
-
* A scope proxy never leaves this stage as itself. `buildFilterPredicate`
|
|
10
|
-
* hands one to the callback and returns the predicate that comes back;
|
|
11
|
-
* `pickSearchColumns` hands one out and returns plain text. Nothing outside
|
|
12
|
-
* the stage therefore has to know that a scope is a Proxy at all.
|
|
13
|
-
*/
|
|
14
|
-
const escape_util_1 = require("../../../common/util/escape.util");
|
|
3
|
+
exports.pickSelectColumns = exports.pickOrderColumn = exports.pickSearchColumns = exports.buildFilterPredicate = exports.raw = exports.mindatetime = exports.maxdatetime = exports.now = exports.not = exports.or = exports.and = void 0;
|
|
15
4
|
const invalidFilter_exception_1 = require("../../exception/invalidFilter.exception");
|
|
5
|
+
const escape_util_1 = require("../../util/filter/escape.util");
|
|
16
6
|
const literal_util_1 = require("../../util/filter/literal.util");
|
|
17
7
|
const predicate_util_1 = require("../../util/filter/predicate.util");
|
|
18
8
|
const scopeProxy_util_1 = require("../../util/filter/scopeProxy.util");
|
|
@@ -59,21 +49,28 @@ exports.buildFilterPredicate = buildFilterPredicate;
|
|
|
59
49
|
* so an empty column list is rejected before the query is ever emitted.
|
|
60
50
|
*/
|
|
61
51
|
const pickSearchColumns = (term, columns) => {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
if (list.length === 0)
|
|
52
|
+
const paths = columnPaths(columns((0, scopeProxy_util_1.rootScope)()), '$searchColumns');
|
|
53
|
+
if (paths.length === 0)
|
|
65
54
|
throw new invalidFilter_exception_1.InvalidFilterError('$search needs at least one column');
|
|
66
|
-
return {
|
|
67
|
-
term: (0, escape_util_1.escapeBareValue)(term),
|
|
68
|
-
columns: list.map(searchColumnPath),
|
|
69
|
-
};
|
|
55
|
+
return { term: (0, escape_util_1.escapeBareValue)(term), columns: paths };
|
|
70
56
|
};
|
|
71
57
|
exports.pickSearchColumns = pickSearchColumns;
|
|
72
|
-
/**
|
|
73
|
-
const
|
|
58
|
+
/** Run one `.orderBy()` callback and return the path of the column it picks. */
|
|
59
|
+
const pickOrderColumn = (column) => columnPath(column((0, scopeProxy_util_1.rootScope)()), '$orderby');
|
|
60
|
+
exports.pickOrderColumn = pickOrderColumn;
|
|
61
|
+
/** Run one `.select()` callback and return the paths of the columns it picks. */
|
|
62
|
+
const pickSelectColumns = (columns) => columnPaths(columns((0, scopeProxy_util_1.rootScope)()), '$select');
|
|
63
|
+
exports.pickSelectColumns = pickSelectColumns;
|
|
64
|
+
/** One column or a list of them, as a callback returns it. */
|
|
65
|
+
const columnPaths = (picked, option) => (Array.isArray(picked) ? picked : [picked]).map((column) => columnPath(column, option));
|
|
66
|
+
/**
|
|
67
|
+
* `$searchColumns`, `$orderby` and `$select` take plain property paths: a
|
|
68
|
+
* function call is a 400.
|
|
69
|
+
*/
|
|
70
|
+
const columnPath = (value, option) => {
|
|
74
71
|
const node = (0, scopeProxy_util_1.nodeOf)(value);
|
|
75
72
|
if (node === undefined || node.text === '' || /[(),']/.test(node.text))
|
|
76
|
-
throw new invalidFilter_exception_1.InvalidFilterError(
|
|
73
|
+
throw new invalidFilter_exception_1.InvalidFilterError(`${option} takes property paths only, not expressions`);
|
|
77
74
|
return node.text;
|
|
78
75
|
};
|
|
79
76
|
//# sourceMappingURL=filter.facade.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.facade.js","sourceRoot":"","sources":["../../../../../src/module/query/service/filter/filter.facade.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"filter.facade.js","sourceRoot":"","sources":["../../../../../src/module/query/service/filter/filter.facade.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
* one member per OData system query option. This file also exports the two
|
|
4
4
|
* factories a caller starts from: `odataQuery()` and `odataItem()`.
|
|
5
5
|
*
|
|
6
|
-
* Each member only writes to `this.queryState`. `buildFilterPredicate()
|
|
7
|
-
* `pickSearchColumns()`
|
|
8
|
-
*
|
|
6
|
+
* Each member only writes to `this.queryState`. `buildFilterPredicate()`,
|
|
7
|
+
* `pickSearchColumns()`, `pickOrderColumn()` and `pickSelectColumns()` in
|
|
8
|
+
* `service/filter/filter.facade.ts` build the filter, search, sort and select
|
|
9
|
+
* text. `emitQueryString()` and `emitQueryParams()` in
|
|
9
10
|
* `service/emit/emit.facade.ts` print the state. A change to the printed
|
|
10
11
|
* query therefore does not change this class, and a change to this class does
|
|
11
12
|
* not change how the query is printed.
|
|
@@ -37,10 +38,10 @@ export declare class QueryChainService {
|
|
|
37
38
|
* `Proxy` works here.
|
|
38
39
|
*/
|
|
39
40
|
get expand(): unknown;
|
|
40
|
-
select(...keys: string[]): this;
|
|
41
|
+
select(...keys: string[] | [(scope: unknown) => unknown]): this;
|
|
41
42
|
filter(build: (scope: unknown, operators: Operators) => Predicate): this;
|
|
42
43
|
search(term: string, columns: (scope: unknown) => Node | readonly Node[]): this;
|
|
43
|
-
orderBy(key: string, direction?: 'asc' | 'desc'): this;
|
|
44
|
+
orderBy(key: string | ((scope: unknown) => unknown), direction?: 'asc' | 'desc'): this;
|
|
44
45
|
top(count: number): this;
|
|
45
46
|
skip(count: number): this;
|
|
46
47
|
count(on?: boolean): this;
|
|
@@ -47,7 +47,10 @@ class QueryChainService {
|
|
|
47
47
|
});
|
|
48
48
|
}
|
|
49
49
|
select(...keys) {
|
|
50
|
-
|
|
50
|
+
const [first] = keys;
|
|
51
|
+
this.queryState.select.push(...(typeof first === 'function'
|
|
52
|
+
? (0, filter_facade_1.pickSelectColumns)(first)
|
|
53
|
+
: keys));
|
|
51
54
|
return this;
|
|
52
55
|
}
|
|
53
56
|
filter(build) {
|
|
@@ -59,7 +62,8 @@ class QueryChainService {
|
|
|
59
62
|
return this;
|
|
60
63
|
}
|
|
61
64
|
orderBy(key, direction = 'asc') {
|
|
62
|
-
|
|
65
|
+
const path = typeof key === 'string' ? key : (0, filter_facade_1.pickOrderColumn)(key);
|
|
66
|
+
this.queryState.orderBy.push(`${path} ${direction}`);
|
|
63
67
|
return this;
|
|
64
68
|
}
|
|
65
69
|
top(count) {
|
|
@@ -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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"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Literal escaping: the one mechanism that makes a value safe inside a query
|
|
3
|
-
* string.
|
|
4
|
-
*
|
|
5
|
-
* `toParams()`.
|
|
3
|
+
* string. The filter stage quotes literals and search terms with it, and
|
|
4
|
+
* `emit.facade.ts` undoes its escapes for `toParams()`. It imports nothing.
|
|
6
5
|
*
|
|
7
6
|
* These seven rules are EMITTER GUARANTEES, each one measured by feeding the
|
|
8
7
|
* emitted string back through the server's own parser and reading the literal
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
3
|
* Literal escaping: the one mechanism that makes a value safe inside a query
|
|
4
|
-
* string.
|
|
5
|
-
*
|
|
6
|
-
* `toParams()`.
|
|
4
|
+
* string. The filter stage quotes literals and search terms with it, and
|
|
5
|
+
* `emit.facade.ts` undoes its escapes for `toParams()`. It imports nothing.
|
|
7
6
|
*
|
|
8
7
|
* These seven rules are EMITTER GUARANTEES, each one measured by feeding the
|
|
9
8
|
* emitted string back through the server's own parser and reading the literal
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escape.util.js","sourceRoot":"","sources":["../../../../../src/module/query/util/filter/escape.util.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;;;AAEH,MAAM,uBAAuB,GAAG,CAAC,KAAa,EAAU,EAAE,CACzD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;KACf,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;IAClB,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACrC,gDAAgD;IAChD,OAAO,IAAI,GAAG,IAAI,IAAI,IAAI,KAAK,IAAI;QAClC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;QACxD,CAAC,CAAC,SAAS,CAAC;AACd,CAAC,CAAC;KACD,IAAI,CAAC,EAAE,CAAC,CAAC;AAEZ,wFAAwF;AACjF,MAAM,eAAe,GAAG,CAAC,KAAa,EAAU,EAAE,CACxD,uBAAuB,CACtB,KAAK;KACH,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;KACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;KACrB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;KACpB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;KACpB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CACtB,CAAC;AARU,QAAA,eAAe,mBAQzB;AAEH;;;GAGG;AACI,MAAM,aAAa,GAAG,CAAC,KAAa,EAAU,EAAE,CACtD,IAAA,uBAAe,EAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAD/B,QAAA,aAAa,iBACkB;AAErC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,IAAI,IAAA,qBAAa,EAAC,KAAK,CAAC,GAAG,CAAC;AAA/D,QAAA,KAAK,SAA0D;AAE5E;;;;;;;GAOG;AACI,MAAM,kBAAkB,GAAG,CAAC,KAAa,EAAU,EAAE,CAC3D,KAAK;KACH,OAAO,CACP,qCAAqC,EACrC,CAAC,MAAM,EAAE,SAAiB,EAAE,EAAE,CAC7B,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAC7C;KACA,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;KACpB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;KACpB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;KACpB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;KACpB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAXX,QAAA,kBAAkB,sBAWP"}
|
|
@@ -10,8 +10,8 @@ exports.literal = exports.parenthesiseArithmetic = exports.ExpressionNode = void
|
|
|
10
10
|
* (`mul`), so `(a add 1) mul 2` parses the way the caller wrote it rather than
|
|
11
11
|
* as `a add (1 mul 2)`.
|
|
12
12
|
*/
|
|
13
|
-
const escape_util_1 = require("../../../common/util/escape.util");
|
|
14
13
|
const invalidFilter_exception_1 = require("../../exception/invalidFilter.exception");
|
|
14
|
+
const escape_util_1 = require("./escape.util");
|
|
15
15
|
const scopeProxy_util_1 = require("./scopeProxy.util");
|
|
16
16
|
class ExpressionNode {
|
|
17
17
|
text;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"literal.util.js","sourceRoot":"","sources":["../../../../../src/module/query/util/filter/literal.util.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;GAQG;AACH,
|
|
1
|
+
{"version":3,"file":"literal.util.js","sourceRoot":"","sources":["../../../../../src/module/query/util/filter/literal.util.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;GAQG;AACH,qFAA6E;AAC7E,+CAAsC;AACtC,uDAA2C;AAE3C,MAAa,cAAc;IAEhB;IAEA;IAEA;IALV,YACU,IAAY;IACrB,4DAA4D;IACnD,KAAa;IACtB,oEAAoE;IAC3D,aAAsB,KAAK;QAJ3B,SAAI,GAAJ,IAAI,CAAQ;QAEZ,UAAK,GAAL,KAAK,CAAQ;QAEb,eAAU,GAAV,UAAU,CAAiB;IAClC,CAAC;CACJ;AARD,wCAQC;AAED,qEAAqE;AAC9D,MAAM,sBAAsB,GAAG,CAAC,IAAoB,EAAU,EAAE,CACtE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;AADnC,QAAA,sBAAsB,0BACa;AAEhD,MAAM,WAAW,GAAG,CAAC,KAAc,EAAuC,EAAE,CAC3E,OAAO,KAAK,KAAK,QAAQ;IACzB,KAAK,KAAK,IAAI;IACd,OAAQ,KAA6B,CAAC,KAAK,KAAK,UAAU,CAAC;AAE5D;;;;;;;GAOG;AACI,MAAM,OAAO,GAAG,CAAC,KAAc,EAAE,SAAS,GAAG,KAAK,EAAU,EAAE;IACpE,IAAI,KAAK,KAAK,SAAS;QACtB,MAAM,IAAI,4CAAkB,CAC3B,+GAA+G,CAC/G,CAAC;IACH,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACpB,IAAI,SAAS;YAAE,OAAO,MAAM,CAAC;QAC7B,MAAM,IAAI,4CAAkB,CAC3B,mHAAmH,CACnH,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,IAAA,wBAAM,EAAC,KAAK,CAAC,CAAC;IAC3B,IAAI,IAAI;QAAE,OAAO,IAAA,8BAAsB,EAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAA,mBAAK,EAAC,KAAK,CAAC,CAAC;IACnD,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAChE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;IACvD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YAC1B,MAAM,IAAI,4CAAkB,CAC3B,GAAG,KAAK,iCAAiC,EACzC,MAAM,CAAC,KAAK,CAAC,CACb,CAAC;QACH,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IACD,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QAC3B,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAChC,MAAM,IAAI,4CAAkB,CAAC,oCAAoC,CAAC,CAAC;QACpE,OAAO,IAAA,mBAAK,EAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,OAAO,KAAK,IAAI;YACnB,MAAM,IAAI,4CAAkB,CAAC,wCAAwC,CAAC,CAAC;QACxE,OAAO,IAAA,mBAAK,EAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IACD,MAAM,IAAI,4CAAkB,CAC3B,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAClE,CAAC;AACH,CAAC,CAAC;AAtCW,QAAA,OAAO,WAsClB"}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"exceptionCode.model.js","sourceRoot":"","sources":["../../../../src/module/common/domain/exceptionCode.model.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAEH,IAAY,yBAGX;AAHD,WAAY,yBAAyB;IACpC,4DAA+B,CAAA;IAC/B,8DAAiC,CAAA;AAClC,CAAC,EAHW,yBAAyB,yCAAzB,yBAAyB,QAGpC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"exceptionDetail.model.js","sourceRoot":"","sources":["../../../../src/module/common/domain/exceptionDetail.model.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* The two type primitives every other module reads a DTO with.
|
|
4
|
-
*
|
|
5
|
-
* They live in `common` because both the filter module (which turns a DTO into
|
|
6
|
-
* a filter scope) and the query module (which turns a DTO into a select/expand
|
|
7
|
-
* namespace) need the same answer to "is this a column or a relation".
|
|
8
|
-
*
|
|
9
|
-
* `Scalar` admits only the five shapes the dialect can compare, sort or
|
|
10
|
-
* select directly; an object or array field never matches it, so those two
|
|
11
|
-
* modules route it through `Unwrap` and the embedding types instead.
|
|
12
|
-
*/
|
|
13
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
//# sourceMappingURL=scalar.model.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scalar.model.js","sourceRoot":"","sources":["../../../../src/module/common/domain/scalar.model.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"escape.util.js","sourceRoot":"","sources":["../../../../src/module/common/util/escape.util.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;;;AAEH,MAAM,uBAAuB,GAAG,CAAC,KAAa,EAAU,EAAE,CACzD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;KACf,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;IAClB,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACrC,gDAAgD;IAChD,OAAO,IAAI,GAAG,IAAI,IAAI,IAAI,KAAK,IAAI;QAClC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;QACxD,CAAC,CAAC,SAAS,CAAC;AACd,CAAC,CAAC;KACD,IAAI,CAAC,EAAE,CAAC,CAAC;AAEZ,wFAAwF;AACjF,MAAM,eAAe,GAAG,CAAC,KAAa,EAAU,EAAE,CACxD,uBAAuB,CACtB,KAAK;KACH,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;KACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;KACrB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;KACpB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;KACpB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CACtB,CAAC;AARU,QAAA,eAAe,mBAQzB;AAEH;;;GAGG;AACI,MAAM,aAAa,GAAG,CAAC,KAAa,EAAU,EAAE,CACtD,IAAA,uBAAe,EAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAD/B,QAAA,aAAa,iBACkB;AAErC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,IAAI,IAAA,qBAAa,EAAC,KAAK,CAAC,GAAG,CAAC;AAA/D,QAAA,KAAK,SAA0D;AAE5E;;;;;;;GAOG;AACI,MAAM,kBAAkB,GAAG,CAAC,KAAa,EAAU,EAAE,CAC3D,KAAK;KACH,OAAO,CACP,qCAAqC,EACrC,CAAC,MAAM,EAAE,SAAiB,EAAE,EAAE,CAC7B,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAC7C;KACA,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;KACpB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;KACpB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;KACpB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;KACpB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAXX,QAAA,kBAAkB,sBAWP"}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The `expand` namespace: one call signature per relation of a DTO.
|
|
3
|
-
*
|
|
4
|
-
* This mapped type is the whole "codegen". `q.expand.` lists exactly the
|
|
5
|
-
* relations `_embedded` declares, each callback typed to the entity that
|
|
6
|
-
* relation reaches, with no build step and no `$metadata` document.
|
|
7
|
-
*/
|
|
8
|
-
import type { EmbeddedObjectKeys, Relation, ScalarFieldKeys, ToManyKeys, ToOneKeys } from '../filter/scope.model';
|
|
9
|
-
import type { ExpandChain } from './expandChain.model';
|
|
10
|
-
/** Every expandable relation name of a DTO. A real allowlist. */
|
|
11
|
-
export type ExpandKey<T> = ToOneKeys<T> | ToManyKeys<T>;
|
|
12
|
-
/**
|
|
13
|
-
* The budget a path type spends, one unit per segment it descends.
|
|
14
|
-
*
|
|
15
|
-
* A DTO graph is cyclic — `ProjectDto` reaches itself through `parent` — so a
|
|
16
|
-
* path type that recursed freely would never terminate and TypeScript would
|
|
17
|
-
* answer TS2589. Indexing `Down` with the remaining budget yields the budget
|
|
18
|
-
* one segment deeper; `[D] extends [0]` stops the descent.
|
|
19
|
-
*
|
|
20
|
-
* The budget also sets what a caller can write. `OrderKey` (default 3) admits
|
|
21
|
-
* up to three to-one hops; `EmbeddedPathKeys` (default 2) admits three object
|
|
22
|
-
* segments before the leaf. A deeper path is a compile error, which
|
|
23
|
-
* `test/types/err/orderBy.err.ts` pins.
|
|
24
|
-
*
|
|
25
|
-
* ```ts
|
|
26
|
-
* orderBy('owner/organisation/code') // 2 to-one hops: compiles
|
|
27
|
-
* orderBy('parent/parent/parent/name') // 3 to-one hops: compiles, the default budget
|
|
28
|
-
* orderBy('parent/parent/parent/parent/name') // 4 to-one hops: TS2345, past the budget
|
|
29
|
-
* // Down[3] is 2, Down[1] is 0, and at 0 the path stops.
|
|
30
|
-
* ```
|
|
31
|
-
*
|
|
32
|
-
* To allow a deeper path, raise the default `D` and move the pinned case to
|
|
33
|
-
* `test/types/ok/`. Each extra unit multiplies the key strings TypeScript
|
|
34
|
-
* builds, so compile time grows.
|
|
35
|
-
*/
|
|
36
|
-
type Budget = 0 | 1 | 2 | 3;
|
|
37
|
-
type Down = [never, 0, 1, 2, 3];
|
|
38
|
-
/**
|
|
39
|
-
* Every leaf path an embedded object of a DTO exposes: `address/city`,
|
|
40
|
-
* `address/geo/lat`, `address/supplier/name`.
|
|
41
|
-
*
|
|
42
|
-
* The budget admits three object segments before the leaf, which is one more
|
|
43
|
-
* than any embedded the dialect models nests.
|
|
44
|
-
*/
|
|
45
|
-
export type EmbeddedPathKeys<T, D extends Budget = 2> = {
|
|
46
|
-
[K in EmbeddedObjectKeys<T>]: `${K}/${ScalarFieldKeys<NonNullable<T[K]>>}` | ([D] extends [0] ? never : `${K}/${EmbeddedPathKeys<NonNullable<T[K]>, Down[D]>}`);
|
|
47
|
-
}[EmbeddedObjectKeys<T>];
|
|
48
|
-
/**
|
|
49
|
-
* Every selectable column of a DTO: its own scalar columns, plus the leaf paths
|
|
50
|
-
* of its embedded objects. `_embedded` is excluded, and an embedded object is
|
|
51
|
-
* not selectable on its own — only its leaves are.
|
|
52
|
-
*/
|
|
53
|
-
export type FieldKey<T> = ScalarFieldKeys<T> | EmbeddedPathKeys<T>;
|
|
54
|
-
/**
|
|
55
|
-
* Every sortable key of a DTO: everything `FieldKey` admits, plus the same set
|
|
56
|
-
* reached across up to three to-one relation hops (`owner/email`,
|
|
57
|
-
* `owner/organisation/code`, `parent/parent/parent/name`).
|
|
58
|
-
*
|
|
59
|
-
* A to-many relation is never a sort key — the server has no single row to sort
|
|
60
|
-
* by — so only `ToOneKeys` opens a hop.
|
|
61
|
-
*/
|
|
62
|
-
export type OrderKey<T, D extends Budget = 3> = FieldKey<T> | ([D] extends [0] ? never : {
|
|
63
|
-
[K in ToOneKeys<T>]: `${K}/${OrderKey<Relation<T, K>, Down[D]>}`;
|
|
64
|
-
}[ToOneKeys<T>]);
|
|
65
|
-
/**
|
|
66
|
-
* `Self` is the chain the call returns, so `expand.a(...).expand.b(...)`
|
|
67
|
-
* chains at whatever level it is written.
|
|
68
|
-
*/
|
|
69
|
-
export type ExpandNamespace<T, Self> = {
|
|
70
|
-
readonly [K in ExpandKey<T>]: (build?: (chain: ExpandChain<Relation<T, K>>) => unknown) => Self;
|
|
71
|
-
};
|
|
72
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"expandNamespace.model.js","sourceRoot":"","sources":["../../../../../src/module/query/domain/chain/expandNamespace.model.ts"],"names":[],"mappings":""}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|