@lenne.tech/nest-server 9.0.1 → 9.0.2
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/core/common/args/pagination.args.js +2 -2
- package/dist/core/common/args/pagination.args.js.map +1 -1
- package/dist/core/common/helpers/db.helper.d.ts +2 -4
- package/dist/core/common/helpers/db.helper.js +18 -8
- package/dist/core/common/helpers/db.helper.js.map +1 -1
- package/dist/core/common/helpers/filter.helper.d.ts +3 -1
- package/dist/core/common/helpers/filter.helper.js +14 -9
- package/dist/core/common/helpers/filter.helper.js.map +1 -1
- package/dist/core/common/services/crud.service.d.ts +7 -0
- package/dist/core/common/services/crud.service.js +36 -0
- package/dist/core/common/services/crud.service.js.map +1 -1
- package/dist/core/common/services/module.service.d.ts +1 -0
- package/dist/core/common/services/module.service.js +10 -2
- package/dist/core/common/services/module.service.js.map +1 -1
- package/dist/server/modules/file/file-info.model.d.ts +2 -1
- package/dist/server/modules/user/outputs/find-and-count-user-result.output.d.ts +5 -0
- package/dist/server/modules/user/outputs/find-and-count-user-result.output.js +29 -0
- package/dist/server/modules/user/outputs/find-and-count-user-result.output.js.map +1 -0
- package/dist/server/modules/user/user.model.d.ts +2 -1
- package/dist/server/modules/user/user.resolver.d.ts +4 -0
- package/dist/server/modules/user/user.resolver.js +16 -0
- package/dist/server/modules/user/user.resolver.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +21 -21
- package/src/core/common/args/pagination.args.ts +4 -4
- package/src/core/common/helpers/db.helper.ts +16 -8
- package/src/core/common/helpers/filter.helper.ts +20 -10
- package/src/core/common/services/crud.service.ts +64 -1
- package/src/core/common/services/module.service.ts +15 -3
- package/src/server/modules/user/outputs/find-and-count-user-result.output.ts +11 -0
- package/src/server/modules/user/user.resolver.ts +13 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "9.0.
|
|
3
|
+
"version": "9.0.2",
|
|
4
4
|
"description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node",
|
|
@@ -59,17 +59,17 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@apollo/gateway": "2.0.5",
|
|
62
|
-
"@nestjs/apollo": "10.0.
|
|
63
|
-
"@nestjs/common": "9.0.
|
|
64
|
-
"@nestjs/core": "9.0.
|
|
65
|
-
"@nestjs/graphql": "10.0.
|
|
62
|
+
"@nestjs/apollo": "10.0.19",
|
|
63
|
+
"@nestjs/common": "9.0.9",
|
|
64
|
+
"@nestjs/core": "9.0.9",
|
|
65
|
+
"@nestjs/graphql": "10.0.21",
|
|
66
66
|
"@nestjs/jwt": "9.0.0",
|
|
67
67
|
"@nestjs/mongoose": "9.2.0",
|
|
68
68
|
"@nestjs/passport": "9.0.0",
|
|
69
|
-
"@nestjs/platform-express": "9.0.
|
|
69
|
+
"@nestjs/platform-express": "9.0.9",
|
|
70
70
|
"@nestjs/schedule": "2.1.0",
|
|
71
|
-
"apollo-server-core": "3.10.
|
|
72
|
-
"apollo-server-express": "3.10.
|
|
71
|
+
"apollo-server-core": "3.10.1",
|
|
72
|
+
"apollo-server-express": "3.10.1",
|
|
73
73
|
"bcrypt": "5.0.1",
|
|
74
74
|
"class-transformer": "0.5.1",
|
|
75
75
|
"class-validator": "0.13.2",
|
|
@@ -79,14 +79,14 @@
|
|
|
79
79
|
"graphql-upload": "15.0.2",
|
|
80
80
|
"js-sha256": "0.9.0",
|
|
81
81
|
"json-to-graphql-query": "2.2.4",
|
|
82
|
-
"light-my-request": "5.
|
|
82
|
+
"light-my-request": "5.4.0",
|
|
83
83
|
"lodash": "4.17.21",
|
|
84
|
-
"mongodb": "4.8.
|
|
85
|
-
"mongoose": "6.
|
|
84
|
+
"mongodb": "4.8.1",
|
|
85
|
+
"mongoose": "6.5.2",
|
|
86
86
|
"mongoose-gridfs": "1.3.0",
|
|
87
87
|
"multer": "1.4.5-lts.1",
|
|
88
|
-
"node-mailjet": "5.
|
|
89
|
-
"nodemailer": "6.7.
|
|
88
|
+
"node-mailjet": "5.1.1",
|
|
89
|
+
"nodemailer": "6.7.8",
|
|
90
90
|
"nodemon": "2.0.19",
|
|
91
91
|
"passport": "0.6.0",
|
|
92
92
|
"passport-jwt": "4.0.0",
|
|
@@ -96,20 +96,20 @@
|
|
|
96
96
|
"rxjs": "7.5.6"
|
|
97
97
|
},
|
|
98
98
|
"devDependencies": {
|
|
99
|
-
"@nestjs/testing": "9.0.
|
|
99
|
+
"@nestjs/testing": "9.0.9",
|
|
100
100
|
"@types/cron": "2.0.0",
|
|
101
101
|
"@types/ejs": "3.1.1",
|
|
102
102
|
"@types/jest": "28.1.6",
|
|
103
103
|
"@types/lodash": "4.14.182",
|
|
104
104
|
"@types/multer": "1.4.7",
|
|
105
|
-
"@types/node": "18.
|
|
106
|
-
"@types/nodemailer": "6.4.
|
|
107
|
-
"@types/passport": "1.0.
|
|
105
|
+
"@types/node": "18.7.3",
|
|
106
|
+
"@types/nodemailer": "6.4.5",
|
|
107
|
+
"@types/passport": "1.0.10",
|
|
108
108
|
"@types/supertest": "2.0.12",
|
|
109
|
-
"@typescript-eslint/eslint-plugin": "5.
|
|
110
|
-
"@typescript-eslint/parser": "5.
|
|
109
|
+
"@typescript-eslint/eslint-plugin": "5.33.0",
|
|
110
|
+
"@typescript-eslint/parser": "5.33.0",
|
|
111
111
|
"coffeescript": "2.7.0",
|
|
112
|
-
"eslint": "8.
|
|
112
|
+
"eslint": "8.22.0",
|
|
113
113
|
"eslint-config-prettier": "8.5.0",
|
|
114
114
|
"find-file-up": "2.0.1",
|
|
115
115
|
"grunt": "1.5.3",
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
"ts-jest": "28.0.7",
|
|
127
127
|
"ts-morph": "15.1.0",
|
|
128
128
|
"ts-node": "10.9.1",
|
|
129
|
-
"tsconfig-paths": "4.
|
|
129
|
+
"tsconfig-paths": "4.1.0",
|
|
130
130
|
"typescript": "4.7.4"
|
|
131
131
|
},
|
|
132
132
|
"jest": {
|
|
@@ -19,10 +19,10 @@ export class PaginationArgs extends CoreInput {
|
|
|
19
19
|
limit?: number = undefined;
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
22
|
+
* Alias for skip
|
|
23
23
|
*/
|
|
24
24
|
@Field((type) => Int, {
|
|
25
|
-
description: '
|
|
25
|
+
description: 'Alias for skip',
|
|
26
26
|
nullable: true,
|
|
27
27
|
defaultValue: 0,
|
|
28
28
|
})
|
|
@@ -30,10 +30,10 @@ export class PaginationArgs extends CoreInput {
|
|
|
30
30
|
offset?: number = undefined;
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
33
|
+
* Skip for pagination
|
|
34
34
|
*/
|
|
35
35
|
@Field((type) => Int, {
|
|
36
|
-
description: '
|
|
36
|
+
description: 'Skip specifies how many found elements should be skipped on return',
|
|
37
37
|
nullable: true,
|
|
38
38
|
defaultValue: undefined,
|
|
39
39
|
})
|
|
@@ -479,7 +479,7 @@ export async function popAndMap<T extends CoreModel>(
|
|
|
479
479
|
}
|
|
480
480
|
if (queryOrDocument instanceof Query) {
|
|
481
481
|
// Get result
|
|
482
|
-
result = await setPopulates(queryOrDocument, populateOptions, mongooseModel
|
|
482
|
+
result = await setPopulates(queryOrDocument, populateOptions, mongooseModel);
|
|
483
483
|
if (result instanceof Query) {
|
|
484
484
|
result = await result.exec();
|
|
485
485
|
}
|
|
@@ -493,13 +493,13 @@ export async function popAndMap<T extends CoreModel>(
|
|
|
493
493
|
} else {
|
|
494
494
|
// Process documents
|
|
495
495
|
if (Array.isArray(queryOrDocument)) {
|
|
496
|
-
await setPopulates(queryOrDocument, populateOptions, mongooseModel
|
|
496
|
+
await setPopulates(queryOrDocument, populateOptions, mongooseModel);
|
|
497
497
|
result = queryOrDocument.map((item) => (modelClass as any).map(item));
|
|
498
498
|
}
|
|
499
499
|
|
|
500
500
|
// Process document
|
|
501
501
|
else {
|
|
502
|
-
await setPopulates(queryOrDocument, populateOptions, mongooseModel
|
|
502
|
+
await setPopulates(queryOrDocument, populateOptions, mongooseModel);
|
|
503
503
|
result = (modelClass as any).map(queryOrDocument);
|
|
504
504
|
}
|
|
505
505
|
}
|
|
@@ -544,7 +544,7 @@ export function removeIds(source: any[], ids: StringOrObjectId | StringOrObjectI
|
|
|
544
544
|
export async function setPopulates<T = Query<any, any> | Document>(
|
|
545
545
|
queryOrDocument: T,
|
|
546
546
|
populateOptions: string[] | PopulateOptions[] | (string | PopulateOptions)[],
|
|
547
|
-
|
|
547
|
+
mongooseModel: Model<any>
|
|
548
548
|
): Promise<T> {
|
|
549
549
|
// Check parameters
|
|
550
550
|
if (!populateOptions?.length || !queryOrDocument) {
|
|
@@ -552,13 +552,13 @@ export async function setPopulates<T = Query<any, any> | Document>(
|
|
|
552
552
|
}
|
|
553
553
|
|
|
554
554
|
// Filter populate options via model schema paths
|
|
555
|
-
if (
|
|
555
|
+
if (mongooseModel?.schema?.paths) {
|
|
556
556
|
populateOptions = populateOptions.filter((option: string | PopulateOptions) => {
|
|
557
557
|
let key: string = option as string;
|
|
558
558
|
if ((option as PopulateOptions)?.path) {
|
|
559
559
|
key = (option as PopulateOptions)?.path;
|
|
560
560
|
}
|
|
561
|
-
return Object.keys(
|
|
561
|
+
return Object.keys(mongooseModel.schema.paths).includes(key);
|
|
562
562
|
});
|
|
563
563
|
}
|
|
564
564
|
|
|
@@ -573,12 +573,20 @@ export async function setPopulates<T = Query<any, any> | Document>(
|
|
|
573
573
|
// Array with documents
|
|
574
574
|
else if (Array.isArray(queryOrDocument)) {
|
|
575
575
|
const promises = [];
|
|
576
|
-
queryOrDocument.forEach((item) =>
|
|
576
|
+
queryOrDocument.forEach((item) => {
|
|
577
|
+
if (item.populate) {
|
|
578
|
+
promises.push(item.populate(populateOptions));
|
|
579
|
+
} else if (mongooseModel) {
|
|
580
|
+
promises.push(mongooseModel.populate(item, populateOptions as any));
|
|
581
|
+
}
|
|
582
|
+
});
|
|
577
583
|
await Promise.all(promises);
|
|
578
584
|
}
|
|
579
585
|
// Single document
|
|
580
|
-
else {
|
|
586
|
+
else if ((queryOrDocument as any).populate) {
|
|
581
587
|
await (queryOrDocument as any).populate(populateOptions);
|
|
588
|
+
} else {
|
|
589
|
+
return (await mongooseModel.populate(queryOrDocument as any, populateOptions as any)) as any;
|
|
582
590
|
}
|
|
583
591
|
|
|
584
592
|
// Return populated
|
|
@@ -2,6 +2,7 @@ import { FilterQuery, QueryOptions } from 'mongoose';
|
|
|
2
2
|
import { FilterArgs } from '../args/filter.args';
|
|
3
3
|
import { ComparisonOperatorEnum } from '../enums/comparison-operator.enum';
|
|
4
4
|
import { LogicalOperatorEnum } from '../enums/logical-operator.enum';
|
|
5
|
+
import { SortOrderEnum } from '../enums/sort-order.emum';
|
|
5
6
|
import { FilterInput } from '../inputs/filter.input';
|
|
6
7
|
import { SortInput } from '../inputs/sort.input';
|
|
7
8
|
import { getObjectIds } from './db.helper';
|
|
@@ -193,36 +194,45 @@ export function generateFilterQuery<T = any>(filter?: Partial<FilterInput>): Fil
|
|
|
193
194
|
/**
|
|
194
195
|
* Generate find options
|
|
195
196
|
*/
|
|
196
|
-
export function generateFindOptions<T = any>(
|
|
197
|
+
export function generateFindOptions<T = any>(
|
|
198
|
+
filterArgs: Partial<FilterArgs>,
|
|
199
|
+
options?: { maxLimit?: number }
|
|
200
|
+
): QueryOptions {
|
|
197
201
|
// Check filterArgs
|
|
198
202
|
if (!filterArgs) {
|
|
199
203
|
return {};
|
|
200
204
|
}
|
|
201
205
|
|
|
206
|
+
// Config
|
|
207
|
+
const config = {
|
|
208
|
+
maxLimit: 100,
|
|
209
|
+
...options,
|
|
210
|
+
};
|
|
211
|
+
|
|
202
212
|
// Get values
|
|
203
213
|
const { limit, offset, skip, sort, take } = filterArgs;
|
|
204
214
|
|
|
205
215
|
// Init options
|
|
206
|
-
const
|
|
207
|
-
limit: limit
|
|
216
|
+
const queryOptions: QueryOptions = {
|
|
217
|
+
limit: limit || take,
|
|
208
218
|
};
|
|
209
219
|
|
|
210
220
|
if (skip > 0 || offset > 0) {
|
|
211
|
-
|
|
221
|
+
queryOptions.skip = skip || offset;
|
|
212
222
|
}
|
|
213
223
|
|
|
214
|
-
// Check
|
|
215
|
-
if (!
|
|
216
|
-
|
|
224
|
+
// Check limit
|
|
225
|
+
if (!queryOptions.limit || queryOptions.limit > config.maxLimit) {
|
|
226
|
+
queryOptions.limit = 25;
|
|
217
227
|
}
|
|
218
228
|
|
|
219
229
|
// Prepare order
|
|
220
230
|
if (sort) {
|
|
221
|
-
|
|
231
|
+
queryOptions.sort = {};
|
|
222
232
|
sort.forEach((item: SortInput) => {
|
|
223
|
-
|
|
233
|
+
queryOptions.sort[item.field] = item.order === SortOrderEnum.DESC ? -1 : 1;
|
|
224
234
|
});
|
|
225
235
|
}
|
|
226
236
|
|
|
227
|
-
return
|
|
237
|
+
return queryOptions;
|
|
228
238
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NotFoundException } from '@nestjs/common';
|
|
2
|
-
import { FilterQuery, QueryOptions } from 'mongoose';
|
|
2
|
+
import { FilterQuery, PipelineStage, QueryOptions } from 'mongoose';
|
|
3
3
|
import { FilterArgs } from '../args/filter.args';
|
|
4
4
|
import { merge } from '../helpers/config.helper';
|
|
5
5
|
import { getStringIds } from '../helpers/db.helper';
|
|
@@ -59,6 +59,69 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
|
|
|
59
59
|
);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Get items and total count via filter
|
|
64
|
+
*/
|
|
65
|
+
async findAndCount(
|
|
66
|
+
filter?: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions },
|
|
67
|
+
serviceOptions?: ServiceOptions
|
|
68
|
+
): Promise<{ items: T[]; totalCount: number }> {
|
|
69
|
+
return this.process(
|
|
70
|
+
async (data) => {
|
|
71
|
+
// Prepare filter query
|
|
72
|
+
const filterQuery = { filterQuery: data?.input?.filterQuery, queryOptions: data?.input?.queryOptions };
|
|
73
|
+
if (data?.input instanceof FilterArgs) {
|
|
74
|
+
const converted = convertFilterArgsToQuery(data.input);
|
|
75
|
+
filterQuery.filterQuery = converted[0];
|
|
76
|
+
filterQuery.queryOptions = converted[1];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Prepare aggregation (with fixed defined sequence)
|
|
80
|
+
const aggregation: PipelineStage[] = [
|
|
81
|
+
{
|
|
82
|
+
// Add pipeline stage 1: match
|
|
83
|
+
$match: filterQuery.filterQuery,
|
|
84
|
+
},
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
// Prepare $facet
|
|
88
|
+
const facet = {
|
|
89
|
+
items: [],
|
|
90
|
+
totalCount: [{ $count: 'total' }],
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// Prepare query options
|
|
94
|
+
if (filterQuery.queryOptions) {
|
|
95
|
+
// Add pipeline stage 2: sort (optional)
|
|
96
|
+
const options = filterQuery.queryOptions;
|
|
97
|
+
if (options.sort) {
|
|
98
|
+
aggregation.push({ $sort: options.sort });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Prepare skip / offset in facet
|
|
102
|
+
if (options.skip || options.offset) {
|
|
103
|
+
facet.items.push({ $skip: options.skip || options.offset });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Prepare limit / take in facet
|
|
107
|
+
if (options.limit || options.take) {
|
|
108
|
+
facet.items.push({ $limit: options.limit || options.take });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Set pipeline stage 3: facet => items (with skip & limit) and totalCount
|
|
113
|
+
aggregation.push({ $facet: facet });
|
|
114
|
+
|
|
115
|
+
// Find and process db items
|
|
116
|
+
const dbResult = (await this.mainDbModel.aggregate(aggregation).exec())[0];
|
|
117
|
+
dbResult.totalCount = dbResult.totalCount[0].total;
|
|
118
|
+
dbResult.items = dbResult.items.map((item) => this.mainDbModel.hydrate(item));
|
|
119
|
+
return dbResult;
|
|
120
|
+
},
|
|
121
|
+
{ input: filter, outputPath: 'items', serviceOptions }
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
62
125
|
/**
|
|
63
126
|
* Find and update
|
|
64
127
|
*/
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as _ from 'lodash';
|
|
1
2
|
import { Document, Model, Types } from 'mongoose';
|
|
2
3
|
import { ProcessType } from '../enums/process-type.enum';
|
|
3
4
|
import { getStringIds, popAndMap } from '../helpers/db.helper';
|
|
@@ -65,14 +66,20 @@ export abstract class ModuleService<T extends CoreModel = any> {
|
|
|
65
66
|
options?: {
|
|
66
67
|
[key: string]: any;
|
|
67
68
|
dbObject?: string | Types.ObjectId | any;
|
|
69
|
+
outputPath?: string | string[];
|
|
68
70
|
input?: any;
|
|
69
71
|
serviceOptions?: ServiceOptions;
|
|
70
72
|
}
|
|
71
73
|
) {
|
|
72
74
|
// Configuration with default values
|
|
73
|
-
const config: {
|
|
75
|
+
const config: {
|
|
76
|
+
dbObject: string | Types.ObjectId | any;
|
|
77
|
+
outputPath: string | string[];
|
|
78
|
+
input: any;
|
|
79
|
+
} & ServiceOptions = {
|
|
74
80
|
checkRights: true,
|
|
75
81
|
dbObject: options?.dbObject,
|
|
82
|
+
outputPath: options?.outputPath,
|
|
76
83
|
force: false,
|
|
77
84
|
input: options?.input,
|
|
78
85
|
processFieldSelection: {},
|
|
@@ -136,7 +143,8 @@ export abstract class ModuleService<T extends CoreModel = any> {
|
|
|
136
143
|
|
|
137
144
|
// Pop and map main model
|
|
138
145
|
if (config.processFieldSelection && config.fieldSelection && this.processFieldSelection) {
|
|
139
|
-
|
|
146
|
+
const field = config.outputPath ? _.get(result, config.outputPath) : result;
|
|
147
|
+
await this.processFieldSelection(field, config.fieldSelection, config.processFieldSelection);
|
|
140
148
|
}
|
|
141
149
|
|
|
142
150
|
// Prepare output
|
|
@@ -145,7 +153,11 @@ export abstract class ModuleService<T extends CoreModel = any> {
|
|
|
145
153
|
if (!opts.targetModel && config.outputType) {
|
|
146
154
|
opts.targetModel = config.outputType;
|
|
147
155
|
}
|
|
148
|
-
|
|
156
|
+
if (config.outputPath) {
|
|
157
|
+
_.set(result, config.outputPath, await this.prepareOutput(_.get(result, config.outputPath), opts));
|
|
158
|
+
} else {
|
|
159
|
+
result = await this.prepareOutput(result, opts);
|
|
160
|
+
}
|
|
149
161
|
}
|
|
150
162
|
|
|
151
163
|
// Check output rights
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Field, ObjectType } from '@nestjs/graphql';
|
|
2
|
+
import { User } from '../user.model';
|
|
3
|
+
|
|
4
|
+
@ObjectType({ description: 'Result of find and count' })
|
|
5
|
+
export class FindAndCountUserResult {
|
|
6
|
+
@Field(() => [User], { description: 'Found users' })
|
|
7
|
+
items: User[];
|
|
8
|
+
|
|
9
|
+
@Field({ description: 'Total count (skip/offset and limit/take are ignored in the count)' })
|
|
10
|
+
totalCount: number;
|
|
11
|
+
}
|
|
@@ -8,6 +8,7 @@ import { Roles } from '../../../core/common/decorators/roles.decorator';
|
|
|
8
8
|
import { RoleEnum } from '../../../core/common/enums/role.enum';
|
|
9
9
|
import { UserCreateInput } from './inputs/user-create.input';
|
|
10
10
|
import { UserInput } from './inputs/user.input';
|
|
11
|
+
import { FindAndCountUserResult } from './outputs/find-and-count-user-result.output';
|
|
11
12
|
import { User } from './user.model';
|
|
12
13
|
import { UserService } from './user.service';
|
|
13
14
|
|
|
@@ -38,6 +39,18 @@ export class UserResolver {
|
|
|
38
39
|
});
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Get users and total count (via filter)
|
|
44
|
+
*/
|
|
45
|
+
@Roles(RoleEnum.ADMIN)
|
|
46
|
+
@Query(() => FindAndCountUserResult, { description: 'Find users (via filter)' })
|
|
47
|
+
async findAndCountUsers(@Info() info: GraphQLResolveInfo, @Args() args?: FilterArgs) {
|
|
48
|
+
return await this.userService.findAndCount(args, {
|
|
49
|
+
fieldSelection: { info, select: 'findAndCountUsers' },
|
|
50
|
+
inputType: FilterArgs,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
41
54
|
/**
|
|
42
55
|
* Get user via ID
|
|
43
56
|
*/
|