@ptc-org/nestjs-query-typeorm 0.32.0 → 0.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/common/index.d.ts +1 -0
- package/src/common/index.js +5 -0
- package/src/common/index.js.map +1 -0
- package/src/common/randomString.d.ts +1 -0
- package/src/common/randomString.js +10 -0
- package/src/common/randomString.js.map +1 -0
- package/src/index.d.ts +2 -0
- package/src/index.js +5 -2
- package/src/index.js.map +1 -0
- package/src/lib/query-typeorm.d.ts +1 -0
- package/src/lib/query-typeorm.js +8 -0
- package/src/lib/query-typeorm.js.map +1 -0
- package/src/module.d.ts +6 -0
- package/src/module.js +19 -0
- package/src/module.js.map +1 -0
- package/src/providers.d.ts +4 -0
- package/src/providers.js +18 -0
- package/src/providers.js.map +1 -0
- package/src/query/aggregate.builder.d.ts +32 -0
- package/src/query/aggregate.builder.js +116 -0
- package/src/query/aggregate.builder.js.map +1 -0
- package/src/query/filter-query.builder.d.ts +129 -0
- package/src/query/filter-query.builder.js +216 -0
- package/src/query/filter-query.builder.js.map +1 -0
- package/src/query/index.d.ts +5 -0
- package/src/query/index.js +9 -0
- package/src/query/index.js.map +1 -0
- package/src/query/relation-query.builder.d.ts +69 -0
- package/src/query/relation-query.builder.js +293 -0
- package/src/query/relation-query.builder.js.map +1 -0
- package/src/query/sql-comparison.builder.d.ts +42 -0
- package/src/query/sql-comparison.builder.js +157 -0
- package/src/query/sql-comparison.builder.js.map +1 -0
- package/src/query/where.builder.d.ts +60 -0
- package/src/query/where.builder.js +102 -0
- package/src/query/where.builder.js.map +1 -0
- package/src/services/index.d.ts +1 -0
- package/src/services/index.js +5 -0
- package/src/services/index.js.map +1 -0
- package/src/services/relation-query.service.d.ts +132 -0
- package/src/services/relation-query.service.js +266 -0
- package/src/services/relation-query.service.js.map +1 -0
- package/src/services/typeorm-query.service.d.ts +179 -0
- package/src/services/typeorm-query.service.js +282 -0
- package/src/services/typeorm-query.service.js.map +1 -0
- package/CHANGELOG.md +0 -527
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ptc-org/nestjs-query-typeorm",
|
|
3
|
-
"version": "0.32.
|
|
3
|
+
"version": "0.32.1",
|
|
4
4
|
"description": "Typeorm adapter for @nestjs-query/core",
|
|
5
5
|
"author": "doug-martin <doug@dougamartin.com>",
|
|
6
6
|
"homepage": "https://github.com/doug-martin/nestjs-query#readme",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"test": "__tests__"
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
|
-
"
|
|
15
|
+
"src/**"
|
|
16
16
|
],
|
|
17
17
|
"publishConfig": {
|
|
18
18
|
"access": "public"
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@nestjs/typeorm": "^8.0.0",
|
|
31
31
|
"class-transformer": "^0.2.3 || 0.3.1 || 0.4",
|
|
32
32
|
"typeorm": "^0.2.25",
|
|
33
|
-
"@ptc-org/nestjs-query-core": "0.30.
|
|
33
|
+
"@ptc-org/nestjs-query-core": "0.30.2"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@nestjs/common": "8.4.0",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './randomString';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/query-typeorm/src/common/index.ts"],"names":[],"mappings":";;;AAAA,8DAA+B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function randomString(): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.randomString = void 0;
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
|
+
const replacer = /-/g;
|
|
6
|
+
function randomString() {
|
|
7
|
+
return (0, uuid_1.v4)().replace(replacer, '');
|
|
8
|
+
}
|
|
9
|
+
exports.randomString = randomString;
|
|
10
|
+
//# sourceMappingURL=randomString.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"randomString.js","sourceRoot":"","sources":["../../../../../packages/query-typeorm/src/common/randomString.ts"],"names":[],"mappings":";;;AAAA,+BAA0B;AAE1B,MAAM,QAAQ,GAAG,IAAI,CAAC;AAEtB,SAAgB,YAAY;IAC1B,OAAO,IAAA,SAAE,GAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AACpC,CAAC;AAFD,oCAEC"}
|
package/src/index.d.ts
ADDED
package/src/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
exports.NestjsQueryTypeOrmModule = exports.TypeOrmQueryService = void 0;
|
|
4
|
+
var services_1 = require("./services");
|
|
5
|
+
Object.defineProperty(exports, "TypeOrmQueryService", { enumerable: true, get: function () { return services_1.TypeOrmQueryService; } });
|
|
6
|
+
var module_1 = require("./module");
|
|
7
|
+
Object.defineProperty(exports, "NestjsQueryTypeOrmModule", { enumerable: true, get: function () { return module_1.NestjsQueryTypeOrmModule; } });
|
|
5
8
|
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/query-typeorm/src/index.ts"],"names":[],"mappings":";;;AAAA,uCAA0E;AAAjE,+GAAA,mBAAmB,OAAA;AAC5B,mCAAoD;AAA3C,kHAAA,wBAAwB,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function queryTypeorm(): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-typeorm.js","sourceRoot":"","sources":["../../../../../packages/query-typeorm/src/lib/query-typeorm.ts"],"names":[],"mappings":";;;AAAA,SAAgB,YAAY;IAC1B,OAAO,eAAe,CAAC;AACzB,CAAC;AAFD,oCAEC"}
|
package/src/module.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Class } from '@ptc-org/nestjs-query-core';
|
|
2
|
+
import { DynamicModule } from '@nestjs/common';
|
|
3
|
+
import { Connection, ConnectionOptions } from 'typeorm';
|
|
4
|
+
export declare class NestjsQueryTypeOrmModule {
|
|
5
|
+
static forFeature(entities: Class<unknown>[], connection?: Connection | ConnectionOptions | string): DynamicModule;
|
|
6
|
+
}
|
package/src/module.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NestjsQueryTypeOrmModule = void 0;
|
|
4
|
+
const typeorm_1 = require("@nestjs/typeorm");
|
|
5
|
+
const providers_1 = require("./providers");
|
|
6
|
+
class NestjsQueryTypeOrmModule {
|
|
7
|
+
static forFeature(entities, connection) {
|
|
8
|
+
const queryServiceProviders = (0, providers_1.createTypeOrmQueryServiceProviders)(entities, connection);
|
|
9
|
+
const typeOrmModule = typeorm_1.TypeOrmModule.forFeature(entities, connection);
|
|
10
|
+
return {
|
|
11
|
+
imports: [typeOrmModule],
|
|
12
|
+
module: NestjsQueryTypeOrmModule,
|
|
13
|
+
providers: [...queryServiceProviders],
|
|
14
|
+
exports: [...queryServiceProviders, typeOrmModule],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.NestjsQueryTypeOrmModule = NestjsQueryTypeOrmModule;
|
|
19
|
+
//# sourceMappingURL=module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.js","sourceRoot":"","sources":["../../../../packages/query-typeorm/src/module.ts"],"names":[],"mappings":";;;AACA,6CAAgD;AAGhD,2CAAiE;AAEjE,MAAa,wBAAwB;IACnC,MAAM,CAAC,UAAU,CAAC,QAA0B,EAAE,UAAoD;QAChG,MAAM,qBAAqB,GAAG,IAAA,8CAAkC,EAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACvF,MAAM,aAAa,GAAG,uBAAa,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACrE,OAAO;YACL,OAAO,EAAE,CAAC,aAAa,CAAC;YACxB,MAAM,EAAE,wBAAwB;YAChC,SAAS,EAAE,CAAC,GAAG,qBAAqB,CAAC;YACrC,OAAO,EAAE,CAAC,GAAG,qBAAqB,EAAE,aAAa,CAAC;SACnD,CAAC;IACJ,CAAC;CACF;AAXD,4DAWC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Class } from '@ptc-org/nestjs-query-core';
|
|
2
|
+
import { FactoryProvider } from '@nestjs/common';
|
|
3
|
+
import { Connection, ConnectionOptions } from 'typeorm';
|
|
4
|
+
export declare const createTypeOrmQueryServiceProviders: (entities: Class<unknown>[], connection?: Connection | ConnectionOptions | string) => FactoryProvider[];
|
package/src/providers.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createTypeOrmQueryServiceProviders = void 0;
|
|
4
|
+
const nestjs_query_core_1 = require("@ptc-org/nestjs-query-core");
|
|
5
|
+
const typeorm_1 = require("@nestjs/typeorm");
|
|
6
|
+
const services_1 = require("./services");
|
|
7
|
+
function createTypeOrmQueryServiceProvider(EntityClass, connection) {
|
|
8
|
+
return {
|
|
9
|
+
provide: (0, nestjs_query_core_1.getQueryServiceToken)(EntityClass),
|
|
10
|
+
useFactory(repo) {
|
|
11
|
+
return new services_1.TypeOrmQueryService(repo);
|
|
12
|
+
},
|
|
13
|
+
inject: [(0, typeorm_1.getRepositoryToken)(EntityClass, connection)],
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const createTypeOrmQueryServiceProviders = (entities, connection) => entities.map((entity) => createTypeOrmQueryServiceProvider(entity, connection));
|
|
17
|
+
exports.createTypeOrmQueryServiceProviders = createTypeOrmQueryServiceProviders;
|
|
18
|
+
//# sourceMappingURL=providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../../../../packages/query-typeorm/src/providers.ts"],"names":[],"mappings":";;;AAAA,kEAAyE;AAEzE,6CAAqD;AAErD,yCAAiD;AAEjD,SAAS,iCAAiC,CACxC,WAA0B,EAC1B,UAAoD;IAEpD,OAAO;QACL,OAAO,EAAE,IAAA,wCAAoB,EAAC,WAAW,CAAC;QAC1C,UAAU,CAAC,IAAwB;YACjC,OAAO,IAAI,8BAAmB,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC;QACD,MAAM,EAAE,CAAC,IAAA,4BAAkB,EAAC,WAAW,EAAE,UAAU,CAAC,CAAC;KACtD,CAAC;AACJ,CAAC;AAEM,MAAM,kCAAkC,GAAG,CAChD,QAA0B,EAC1B,UAAoD,EACjC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,iCAAiC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;AAH3F,QAAA,kCAAkC,sCAGyD"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { SelectQueryBuilder } from 'typeorm';
|
|
2
|
+
import { AggregateQuery, AggregateResponse } from '@ptc-org/nestjs-query-core';
|
|
3
|
+
declare enum AggregateFuncs {
|
|
4
|
+
AVG = "AVG",
|
|
5
|
+
SUM = "SUM",
|
|
6
|
+
COUNT = "COUNT",
|
|
7
|
+
MAX = "MAX",
|
|
8
|
+
MIN = "MIN"
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* @internal
|
|
12
|
+
* Builds a WHERE clause from a Filter.
|
|
13
|
+
*/
|
|
14
|
+
export declare class AggregateBuilder<Entity> {
|
|
15
|
+
static asyncConvertToAggregateResponse<Entity>(responsePromise: Promise<Record<string, unknown>[]>): Promise<AggregateResponse<Entity>[]>;
|
|
16
|
+
static getAggregateSelects<Entity>(query: AggregateQuery<Entity>): string[];
|
|
17
|
+
private static getAggregateGroupBySelects;
|
|
18
|
+
private static getAggregateFuncSelects;
|
|
19
|
+
static getAggregateAlias<Entity>(func: AggregateFuncs, field: keyof Entity): string;
|
|
20
|
+
static getGroupByAlias<Entity>(field: keyof Entity): string;
|
|
21
|
+
static convertToAggregateResponse<Entity>(rawAggregates: Record<string, unknown>[]): AggregateResponse<Entity>[];
|
|
22
|
+
/**
|
|
23
|
+
* Builds a aggregate SELECT clause from a aggregate.
|
|
24
|
+
* @param qb - the `typeorm` SelectQueryBuilder
|
|
25
|
+
* @param aggregate - the aggregates to select.
|
|
26
|
+
* @param alias - optional alias to use to qualify an identifier
|
|
27
|
+
*/
|
|
28
|
+
build<Qb extends SelectQueryBuilder<Entity>>(qb: Qb, aggregate: AggregateQuery<Entity>, alias?: string): Qb;
|
|
29
|
+
private createAggSelect;
|
|
30
|
+
private createGroupBySelect;
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AggregateBuilder = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
const camel_case_1 = require("camel-case");
|
|
6
|
+
var AggregateFuncs;
|
|
7
|
+
(function (AggregateFuncs) {
|
|
8
|
+
AggregateFuncs["AVG"] = "AVG";
|
|
9
|
+
AggregateFuncs["SUM"] = "SUM";
|
|
10
|
+
AggregateFuncs["COUNT"] = "COUNT";
|
|
11
|
+
AggregateFuncs["MAX"] = "MAX";
|
|
12
|
+
AggregateFuncs["MIN"] = "MIN";
|
|
13
|
+
})(AggregateFuncs || (AggregateFuncs = {}));
|
|
14
|
+
const AGG_REGEXP = /(AVG|SUM|COUNT|MAX|MIN|GROUP_BY)_(.*)/;
|
|
15
|
+
/**
|
|
16
|
+
* @internal
|
|
17
|
+
* Builds a WHERE clause from a Filter.
|
|
18
|
+
*/
|
|
19
|
+
class AggregateBuilder {
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
21
|
+
static async asyncConvertToAggregateResponse(responsePromise) {
|
|
22
|
+
const aggResponse = await responsePromise;
|
|
23
|
+
return this.convertToAggregateResponse(aggResponse);
|
|
24
|
+
}
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
26
|
+
static getAggregateSelects(query) {
|
|
27
|
+
return [...this.getAggregateGroupBySelects(query), ...this.getAggregateFuncSelects(query)];
|
|
28
|
+
}
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
30
|
+
static getAggregateGroupBySelects(query) {
|
|
31
|
+
return (query.groupBy ?? []).map((f) => this.getGroupByAlias(f));
|
|
32
|
+
}
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
34
|
+
static getAggregateFuncSelects(query) {
|
|
35
|
+
const aggs = [
|
|
36
|
+
[AggregateFuncs.COUNT, query.count],
|
|
37
|
+
[AggregateFuncs.SUM, query.sum],
|
|
38
|
+
[AggregateFuncs.AVG, query.avg],
|
|
39
|
+
[AggregateFuncs.MAX, query.max],
|
|
40
|
+
[AggregateFuncs.MIN, query.min],
|
|
41
|
+
];
|
|
42
|
+
return aggs.reduce((cols, [func, fields]) => {
|
|
43
|
+
const aliases = (fields ?? []).map((f) => this.getAggregateAlias(func, f));
|
|
44
|
+
return [...cols, ...aliases];
|
|
45
|
+
}, []);
|
|
46
|
+
}
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
48
|
+
static getAggregateAlias(func, field) {
|
|
49
|
+
return `${func}_${field}`;
|
|
50
|
+
}
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
52
|
+
static getGroupByAlias(field) {
|
|
53
|
+
return `GROUP_BY_${field}`;
|
|
54
|
+
}
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
56
|
+
static convertToAggregateResponse(rawAggregates) {
|
|
57
|
+
return rawAggregates.map((response) => {
|
|
58
|
+
return Object.keys(response).reduce((agg, resultField) => {
|
|
59
|
+
const matchResult = AGG_REGEXP.exec(resultField);
|
|
60
|
+
if (!matchResult) {
|
|
61
|
+
throw new Error('Unknown aggregate column encountered.');
|
|
62
|
+
}
|
|
63
|
+
const [matchedFunc, matchedFieldName] = matchResult.slice(1);
|
|
64
|
+
const aggFunc = (0, camel_case_1.camelCase)(matchedFunc.toLowerCase());
|
|
65
|
+
const fieldName = matchedFieldName;
|
|
66
|
+
const aggResult = agg[aggFunc] || {};
|
|
67
|
+
return {
|
|
68
|
+
...agg,
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
70
|
+
[aggFunc]: { ...aggResult, [fieldName]: response[resultField] },
|
|
71
|
+
};
|
|
72
|
+
}, {});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Builds a aggregate SELECT clause from a aggregate.
|
|
77
|
+
* @param qb - the `typeorm` SelectQueryBuilder
|
|
78
|
+
* @param aggregate - the aggregates to select.
|
|
79
|
+
* @param alias - optional alias to use to qualify an identifier
|
|
80
|
+
*/
|
|
81
|
+
build(qb, aggregate, alias) {
|
|
82
|
+
const selects = [
|
|
83
|
+
...this.createGroupBySelect(aggregate.groupBy, alias),
|
|
84
|
+
...this.createAggSelect(AggregateFuncs.COUNT, aggregate.count, alias),
|
|
85
|
+
...this.createAggSelect(AggregateFuncs.SUM, aggregate.sum, alias),
|
|
86
|
+
...this.createAggSelect(AggregateFuncs.AVG, aggregate.avg, alias),
|
|
87
|
+
...this.createAggSelect(AggregateFuncs.MAX, aggregate.max, alias),
|
|
88
|
+
...this.createAggSelect(AggregateFuncs.MIN, aggregate.min, alias),
|
|
89
|
+
];
|
|
90
|
+
if (!selects.length) {
|
|
91
|
+
throw new common_1.BadRequestException('No aggregate fields found.');
|
|
92
|
+
}
|
|
93
|
+
const [head, ...tail] = selects;
|
|
94
|
+
return tail.reduce((acc, [select, selectAlias]) => acc.addSelect(select, selectAlias), qb.select(head[0], head[1]));
|
|
95
|
+
}
|
|
96
|
+
createAggSelect(func, fields, alias) {
|
|
97
|
+
if (!fields) {
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
return fields.map((field) => {
|
|
101
|
+
const col = alias ? `${alias}.${field}` : field;
|
|
102
|
+
return [`${func}(${col})`, AggregateBuilder.getAggregateAlias(func, field)];
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
createGroupBySelect(fields, alias) {
|
|
106
|
+
if (!fields) {
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
return fields.map((field) => {
|
|
110
|
+
const col = alias ? `${alias}.${field}` : field;
|
|
111
|
+
return [`${col}`, AggregateBuilder.getGroupByAlias(field)];
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
exports.AggregateBuilder = AggregateBuilder;
|
|
116
|
+
//# sourceMappingURL=aggregate.builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate.builder.js","sourceRoot":"","sources":["../../../../../packages/query-typeorm/src/query/aggregate.builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { Filter, Paging, Query, SortField, AggregateQuery } from '@ptc-org/nestjs-query-core';
|
|
2
|
+
import { DeleteQueryBuilder, QueryBuilder, Repository, SelectQueryBuilder, UpdateQueryBuilder, WhereExpression, EntityMetadata } from 'typeorm';
|
|
3
|
+
import { SoftDeleteQueryBuilder } from 'typeorm/query-builder/SoftDeleteQueryBuilder';
|
|
4
|
+
import { AggregateBuilder } from './aggregate.builder';
|
|
5
|
+
import { WhereBuilder } from './where.builder';
|
|
6
|
+
/**
|
|
7
|
+
* @internal
|
|
8
|
+
*
|
|
9
|
+
* Interface that for Typeorm query builders that are sortable.
|
|
10
|
+
*/
|
|
11
|
+
interface Sortable<Entity> extends QueryBuilder<Entity> {
|
|
12
|
+
addOrderBy(sort: string, order?: 'ASC' | 'DESC', nulls?: 'NULLS FIRST' | 'NULLS LAST'): this;
|
|
13
|
+
}
|
|
14
|
+
interface Groupable<Entity> extends QueryBuilder<Entity> {
|
|
15
|
+
addGroupBy(groupBy: string): this;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* @internal
|
|
19
|
+
*
|
|
20
|
+
* Interface for `typeorm` query builders that are pageable.
|
|
21
|
+
*/
|
|
22
|
+
interface Pageable<Entity> extends QueryBuilder<Entity> {
|
|
23
|
+
limit(limit?: number): this;
|
|
24
|
+
offset(offset?: number): this;
|
|
25
|
+
skip(skip?: number): this;
|
|
26
|
+
take(take?: number): this;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @internal
|
|
30
|
+
*
|
|
31
|
+
* Nested record type
|
|
32
|
+
*/
|
|
33
|
+
export interface NestedRecord<E = unknown> {
|
|
34
|
+
[keys: string]: NestedRecord<E>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* @internal
|
|
38
|
+
*
|
|
39
|
+
* Class that will convert a Query into a `typeorm` Query Builder.
|
|
40
|
+
*/
|
|
41
|
+
export declare class FilterQueryBuilder<Entity> {
|
|
42
|
+
readonly repo: Repository<Entity>;
|
|
43
|
+
readonly whereBuilder: WhereBuilder<Entity>;
|
|
44
|
+
readonly aggregateBuilder: AggregateBuilder<Entity>;
|
|
45
|
+
constructor(repo: Repository<Entity>, whereBuilder?: WhereBuilder<Entity>, aggregateBuilder?: AggregateBuilder<Entity>);
|
|
46
|
+
/**
|
|
47
|
+
* Create a `typeorm` SelectQueryBuilder with `WHERE`, `ORDER BY` and `LIMIT/OFFSET` clauses.
|
|
48
|
+
*
|
|
49
|
+
* @param query - the query to apply.
|
|
50
|
+
*/
|
|
51
|
+
select(query: Query<Entity>): SelectQueryBuilder<Entity>;
|
|
52
|
+
selectById(id: string | number | (string | number)[], query: Query<Entity>): SelectQueryBuilder<Entity>;
|
|
53
|
+
aggregate(query: Query<Entity>, aggregate: AggregateQuery<Entity>): SelectQueryBuilder<Entity>;
|
|
54
|
+
/**
|
|
55
|
+
* Create a `typeorm` DeleteQueryBuilder with a WHERE clause.
|
|
56
|
+
*
|
|
57
|
+
* @param query - the query to apply.
|
|
58
|
+
*/
|
|
59
|
+
delete(query: Query<Entity>): DeleteQueryBuilder<Entity>;
|
|
60
|
+
/**
|
|
61
|
+
* Create a `typeorm` DeleteQueryBuilder with a WHERE clause.
|
|
62
|
+
*
|
|
63
|
+
* @param query - the query to apply.
|
|
64
|
+
*/
|
|
65
|
+
softDelete(query: Query<Entity>): SoftDeleteQueryBuilder<Entity>;
|
|
66
|
+
/**
|
|
67
|
+
* Create a `typeorm` UpdateQueryBuilder with `WHERE` and `ORDER BY` clauses
|
|
68
|
+
*
|
|
69
|
+
* @param query - the query to apply.
|
|
70
|
+
*/
|
|
71
|
+
update(query: Query<Entity>): UpdateQueryBuilder<Entity>;
|
|
72
|
+
/**
|
|
73
|
+
* Applies paging to a Pageable `typeorm` query builder
|
|
74
|
+
* @param qb - the `typeorm` QueryBuilder
|
|
75
|
+
* @param paging - the Paging options.
|
|
76
|
+
* @param useSkipTake - if skip/take should be used instead of limit/offset.
|
|
77
|
+
*/
|
|
78
|
+
applyPaging<P extends Pageable<Entity>>(qb: P, paging?: Paging, useSkipTake?: boolean): P;
|
|
79
|
+
/**
|
|
80
|
+
* Applies the filter from a Query to a `typeorm` QueryBuilder.
|
|
81
|
+
*
|
|
82
|
+
* @param qb - the `typeorm` QueryBuilder.
|
|
83
|
+
* @param aggregate - the aggregates to select.
|
|
84
|
+
* @param alias - optional alias to use to qualify an identifier
|
|
85
|
+
*/
|
|
86
|
+
applyAggregate<Qb extends SelectQueryBuilder<Entity>>(qb: Qb, aggregate: AggregateQuery<Entity>, alias?: string): Qb;
|
|
87
|
+
/**
|
|
88
|
+
* Applies the filter from a Query to a `typeorm` QueryBuilder.
|
|
89
|
+
*
|
|
90
|
+
* @param qb - the `typeorm` QueryBuilder.
|
|
91
|
+
* @param filter - the filter.
|
|
92
|
+
* @param alias - optional alias to use to qualify an identifier
|
|
93
|
+
*/
|
|
94
|
+
applyFilter<Where extends WhereExpression>(qb: Where, filter?: Filter<Entity>, alias?: string): Where;
|
|
95
|
+
/**
|
|
96
|
+
* Applies the ORDER BY clause to a `typeorm` QueryBuilder.
|
|
97
|
+
* @param qb - the `typeorm` QueryBuilder.
|
|
98
|
+
* @param sorts - an array of SortFields to create the ORDER BY clause.
|
|
99
|
+
* @param alias - optional alias to use to qualify an identifier
|
|
100
|
+
*/
|
|
101
|
+
applySorting<T extends Sortable<Entity>>(qb: T, sorts?: SortField<Entity>[], alias?: string): T;
|
|
102
|
+
applyGroupBy<T extends Groupable<Entity>>(qb: T, groupBy?: (keyof Entity)[], alias?: string): T;
|
|
103
|
+
applyAggregateSorting<T extends Sortable<Entity>>(qb: T, groupBy?: (keyof Entity)[], alias?: string): T;
|
|
104
|
+
/**
|
|
105
|
+
* Create a `typeorm` SelectQueryBuilder which can be used as an entry point to create update, delete or insert
|
|
106
|
+
* QueryBuilders.
|
|
107
|
+
*/
|
|
108
|
+
private createQueryBuilder;
|
|
109
|
+
/**
|
|
110
|
+
* Gets relations referenced in the filter and adds joins for them to the query builder
|
|
111
|
+
* @param qb - the `typeorm` QueryBuilder.
|
|
112
|
+
* @param relationsMap - the relations map.
|
|
113
|
+
*
|
|
114
|
+
* @returns the query builder for chaining
|
|
115
|
+
*/
|
|
116
|
+
applyRelationJoinsRecursive(qb: SelectQueryBuilder<Entity>, relationsMap?: NestedRecord, alias?: string): SelectQueryBuilder<Entity>;
|
|
117
|
+
/**
|
|
118
|
+
* Checks if a filter references any relations.
|
|
119
|
+
* @param filter
|
|
120
|
+
* @private
|
|
121
|
+
*
|
|
122
|
+
* @returns true if there are any referenced relations
|
|
123
|
+
*/
|
|
124
|
+
filterHasRelations(filter?: Filter<Entity>): boolean;
|
|
125
|
+
private getReferencedRelations;
|
|
126
|
+
getReferencedRelationsRecursive(metadata: EntityMetadata, filter?: Filter<unknown>): NestedRecord;
|
|
127
|
+
private get relationNames();
|
|
128
|
+
}
|
|
129
|
+
export {};
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FilterQueryBuilder = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const nestjs_query_core_1 = require("@ptc-org/nestjs-query-core");
|
|
6
|
+
const aggregate_builder_1 = require("./aggregate.builder");
|
|
7
|
+
const where_builder_1 = require("./where.builder");
|
|
8
|
+
const lodash_merge_1 = (0, tslib_1.__importDefault)(require("lodash.merge"));
|
|
9
|
+
/**
|
|
10
|
+
* @internal
|
|
11
|
+
*
|
|
12
|
+
* Class that will convert a Query into a `typeorm` Query Builder.
|
|
13
|
+
*/
|
|
14
|
+
class FilterQueryBuilder {
|
|
15
|
+
constructor(repo, whereBuilder = new where_builder_1.WhereBuilder(), aggregateBuilder = new aggregate_builder_1.AggregateBuilder()) {
|
|
16
|
+
this.repo = repo;
|
|
17
|
+
this.whereBuilder = whereBuilder;
|
|
18
|
+
this.aggregateBuilder = aggregateBuilder;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create a `typeorm` SelectQueryBuilder with `WHERE`, `ORDER BY` and `LIMIT/OFFSET` clauses.
|
|
22
|
+
*
|
|
23
|
+
* @param query - the query to apply.
|
|
24
|
+
*/
|
|
25
|
+
select(query) {
|
|
26
|
+
const hasRelations = this.filterHasRelations(query.filter);
|
|
27
|
+
let qb = this.createQueryBuilder();
|
|
28
|
+
qb = hasRelations
|
|
29
|
+
? this.applyRelationJoinsRecursive(qb, this.getReferencedRelationsRecursive(this.repo.metadata, query.filter))
|
|
30
|
+
: qb;
|
|
31
|
+
qb = this.applyFilter(qb, query.filter, qb.alias);
|
|
32
|
+
qb = this.applySorting(qb, query.sorting, qb.alias);
|
|
33
|
+
qb = this.applyPaging(qb, query.paging, hasRelations);
|
|
34
|
+
return qb;
|
|
35
|
+
}
|
|
36
|
+
selectById(id, query) {
|
|
37
|
+
const hasRelations = this.filterHasRelations(query.filter);
|
|
38
|
+
let qb = this.createQueryBuilder();
|
|
39
|
+
qb = hasRelations
|
|
40
|
+
? this.applyRelationJoinsRecursive(qb, this.getReferencedRelationsRecursive(this.repo.metadata, query.filter))
|
|
41
|
+
: qb;
|
|
42
|
+
qb = qb.andWhereInIds(id);
|
|
43
|
+
qb = this.applyFilter(qb, query.filter, qb.alias);
|
|
44
|
+
qb = this.applySorting(qb, query.sorting, qb.alias);
|
|
45
|
+
qb = this.applyPaging(qb, query.paging, hasRelations);
|
|
46
|
+
return qb;
|
|
47
|
+
}
|
|
48
|
+
aggregate(query, aggregate) {
|
|
49
|
+
let qb = this.createQueryBuilder();
|
|
50
|
+
qb = this.applyAggregate(qb, aggregate, qb.alias);
|
|
51
|
+
qb = this.applyFilter(qb, query.filter, qb.alias);
|
|
52
|
+
qb = this.applyAggregateSorting(qb, aggregate.groupBy, qb.alias);
|
|
53
|
+
qb = this.applyGroupBy(qb, aggregate.groupBy, qb.alias);
|
|
54
|
+
return qb;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Create a `typeorm` DeleteQueryBuilder with a WHERE clause.
|
|
58
|
+
*
|
|
59
|
+
* @param query - the query to apply.
|
|
60
|
+
*/
|
|
61
|
+
delete(query) {
|
|
62
|
+
return this.applyFilter(this.repo.createQueryBuilder().delete(), query.filter);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Create a `typeorm` DeleteQueryBuilder with a WHERE clause.
|
|
66
|
+
*
|
|
67
|
+
* @param query - the query to apply.
|
|
68
|
+
*/
|
|
69
|
+
softDelete(query) {
|
|
70
|
+
return this.applyFilter(this.repo.createQueryBuilder().softDelete(), query.filter);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Create a `typeorm` UpdateQueryBuilder with `WHERE` and `ORDER BY` clauses
|
|
74
|
+
*
|
|
75
|
+
* @param query - the query to apply.
|
|
76
|
+
*/
|
|
77
|
+
update(query) {
|
|
78
|
+
const qb = this.applyFilter(this.repo.createQueryBuilder().update(), query.filter);
|
|
79
|
+
return this.applySorting(qb, query.sorting);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Applies paging to a Pageable `typeorm` query builder
|
|
83
|
+
* @param qb - the `typeorm` QueryBuilder
|
|
84
|
+
* @param paging - the Paging options.
|
|
85
|
+
* @param useSkipTake - if skip/take should be used instead of limit/offset.
|
|
86
|
+
*/
|
|
87
|
+
applyPaging(qb, paging, useSkipTake) {
|
|
88
|
+
if (!paging) {
|
|
89
|
+
return qb;
|
|
90
|
+
}
|
|
91
|
+
if (useSkipTake) {
|
|
92
|
+
return qb.take(paging.limit).skip(paging.offset);
|
|
93
|
+
}
|
|
94
|
+
return qb.limit(paging.limit).offset(paging.offset);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Applies the filter from a Query to a `typeorm` QueryBuilder.
|
|
98
|
+
*
|
|
99
|
+
* @param qb - the `typeorm` QueryBuilder.
|
|
100
|
+
* @param aggregate - the aggregates to select.
|
|
101
|
+
* @param alias - optional alias to use to qualify an identifier
|
|
102
|
+
*/
|
|
103
|
+
applyAggregate(qb, aggregate, alias) {
|
|
104
|
+
return this.aggregateBuilder.build(qb, aggregate, alias);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Applies the filter from a Query to a `typeorm` QueryBuilder.
|
|
108
|
+
*
|
|
109
|
+
* @param qb - the `typeorm` QueryBuilder.
|
|
110
|
+
* @param filter - the filter.
|
|
111
|
+
* @param alias - optional alias to use to qualify an identifier
|
|
112
|
+
*/
|
|
113
|
+
applyFilter(qb, filter, alias) {
|
|
114
|
+
if (!filter) {
|
|
115
|
+
return qb;
|
|
116
|
+
}
|
|
117
|
+
return this.whereBuilder.build(qb, filter, this.getReferencedRelationsRecursive(this.repo.metadata, filter), alias);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Applies the ORDER BY clause to a `typeorm` QueryBuilder.
|
|
121
|
+
* @param qb - the `typeorm` QueryBuilder.
|
|
122
|
+
* @param sorts - an array of SortFields to create the ORDER BY clause.
|
|
123
|
+
* @param alias - optional alias to use to qualify an identifier
|
|
124
|
+
*/
|
|
125
|
+
applySorting(qb, sorts, alias) {
|
|
126
|
+
if (!sorts) {
|
|
127
|
+
return qb;
|
|
128
|
+
}
|
|
129
|
+
return sorts.reduce((prevQb, { field, direction, nulls }) => {
|
|
130
|
+
const col = alias ? `${alias}.${field}` : `${field}`;
|
|
131
|
+
return prevQb.addOrderBy(col, direction, nulls);
|
|
132
|
+
}, qb);
|
|
133
|
+
}
|
|
134
|
+
applyGroupBy(qb, groupBy, alias) {
|
|
135
|
+
if (!groupBy) {
|
|
136
|
+
return qb;
|
|
137
|
+
}
|
|
138
|
+
return groupBy.reduce((prevQb, group) => {
|
|
139
|
+
const col = alias ? `${alias}.${group}` : `${group}`;
|
|
140
|
+
return prevQb.addGroupBy(col);
|
|
141
|
+
}, qb);
|
|
142
|
+
}
|
|
143
|
+
applyAggregateSorting(qb, groupBy, alias) {
|
|
144
|
+
if (!groupBy) {
|
|
145
|
+
return qb;
|
|
146
|
+
}
|
|
147
|
+
return groupBy.reduce((prevQb, field) => {
|
|
148
|
+
const col = alias ? `${alias}.${field}` : `${field}`;
|
|
149
|
+
return prevQb.addOrderBy(col, 'ASC');
|
|
150
|
+
}, qb);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Create a `typeorm` SelectQueryBuilder which can be used as an entry point to create update, delete or insert
|
|
154
|
+
* QueryBuilders.
|
|
155
|
+
*/
|
|
156
|
+
createQueryBuilder() {
|
|
157
|
+
return this.repo.createQueryBuilder();
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Gets relations referenced in the filter and adds joins for them to the query builder
|
|
161
|
+
* @param qb - the `typeorm` QueryBuilder.
|
|
162
|
+
* @param relationsMap - the relations map.
|
|
163
|
+
*
|
|
164
|
+
* @returns the query builder for chaining
|
|
165
|
+
*/
|
|
166
|
+
applyRelationJoinsRecursive(qb, relationsMap, alias) {
|
|
167
|
+
if (!relationsMap) {
|
|
168
|
+
return qb;
|
|
169
|
+
}
|
|
170
|
+
const referencedRelations = Object.keys(relationsMap);
|
|
171
|
+
return referencedRelations.reduce((rqb, relation) => {
|
|
172
|
+
return this.applyRelationJoinsRecursive(rqb.leftJoin(`${alias ?? rqb.alias}.${relation}`, relation), relationsMap[relation], relation);
|
|
173
|
+
}, qb);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Checks if a filter references any relations.
|
|
177
|
+
* @param filter
|
|
178
|
+
* @private
|
|
179
|
+
*
|
|
180
|
+
* @returns true if there are any referenced relations
|
|
181
|
+
*/
|
|
182
|
+
filterHasRelations(filter) {
|
|
183
|
+
if (!filter) {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
return this.getReferencedRelations(filter).length > 0;
|
|
187
|
+
}
|
|
188
|
+
getReferencedRelations(filter) {
|
|
189
|
+
const { relationNames } = this;
|
|
190
|
+
const referencedFields = (0, nestjs_query_core_1.getFilterFields)(filter);
|
|
191
|
+
return referencedFields.filter((f) => relationNames.includes(f));
|
|
192
|
+
}
|
|
193
|
+
getReferencedRelationsRecursive(metadata, filter = {}) {
|
|
194
|
+
const referencedFields = Array.from(new Set(Object.keys(filter)));
|
|
195
|
+
return referencedFields.reduce((prev, curr) => {
|
|
196
|
+
const currFilterValue = filter[curr];
|
|
197
|
+
if ((curr === 'and' || curr === 'or') && currFilterValue) {
|
|
198
|
+
for (const subFilter of currFilterValue) {
|
|
199
|
+
prev = (0, lodash_merge_1.default)(prev, this.getReferencedRelationsRecursive(metadata, subFilter));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const referencedRelation = metadata.relations.find((r) => r.propertyName === curr);
|
|
203
|
+
if (!referencedRelation)
|
|
204
|
+
return prev;
|
|
205
|
+
return {
|
|
206
|
+
...prev,
|
|
207
|
+
[curr]: (0, lodash_merge_1.default)(prev[curr], this.getReferencedRelationsRecursive(referencedRelation.inverseEntityMetadata, currFilterValue)),
|
|
208
|
+
};
|
|
209
|
+
}, {});
|
|
210
|
+
}
|
|
211
|
+
get relationNames() {
|
|
212
|
+
return this.repo.metadata.relations.map((r) => r.propertyName);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
exports.FilterQueryBuilder = FilterQueryBuilder;
|
|
216
|
+
//# sourceMappingURL=filter-query.builder.js.map
|