@lenne.tech/nest-server 9.0.21 → 9.0.23

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.
Files changed (40) hide show
  1. package/dist/core/common/decorators/restricted.decorator.d.ts +1 -1
  2. package/dist/core/common/helpers/graphql.helper.d.ts +1 -1
  3. package/dist/core/common/helpers/input.helper.d.ts +4 -1
  4. package/dist/core/common/helpers/input.helper.js +19 -4
  5. package/dist/core/common/helpers/input.helper.js.map +1 -1
  6. package/dist/core/common/helpers/model.helper.js +10 -2
  7. package/dist/core/common/helpers/model.helper.js.map +1 -1
  8. package/dist/core/common/helpers/service.helper.d.ts +1 -0
  9. package/dist/core/common/helpers/service.helper.js +10 -0
  10. package/dist/core/common/helpers/service.helper.js.map +1 -1
  11. package/dist/core/common/interfaces/prepare-input-options.interface.d.ts +1 -0
  12. package/dist/core/common/pipes/map-and-validate.pipe.js +1 -1
  13. package/dist/core/common/pipes/map-and-validate.pipe.js.map +1 -1
  14. package/dist/core/common/services/module.service.js +2 -2
  15. package/dist/core/common/services/module.service.js.map +1 -1
  16. package/dist/core/common/types/core-model-constructor.type.d.ts +1 -1
  17. package/dist/core/common/types/falsy.type.d.ts +1 -1
  18. package/dist/core/common/types/field-selection.type.d.ts +1 -1
  19. package/dist/core/common/types/ids.type.d.ts +1 -1
  20. package/dist/core/common/types/maybe-promise.type.d.ts +1 -1
  21. package/dist/core/common/types/plain-input.type.d.ts +1 -1
  22. package/dist/core/common/types/plain-object.type.d.ts +1 -1
  23. package/dist/core/common/types/remove-methods.type.d.ts +1 -1
  24. package/dist/core/common/types/require-only-one.type.d.ts +1 -1
  25. package/dist/core/common/types/required-at-least-one.type.d.ts +1 -1
  26. package/dist/core/common/types/string-or-object-id.type.d.ts +1 -1
  27. package/dist/core/modules/auth/guards/auth.guard.d.ts +1 -1
  28. package/dist/core/modules/file/core-file.service.d.ts +1 -1
  29. package/dist/core/modules/user/core-user.model.d.ts +1 -1
  30. package/dist/server/modules/file/file-info.model.d.ts +1 -1
  31. package/dist/server/modules/user/user.model.d.ts +2 -2
  32. package/dist/test/test.helper.d.ts +1 -1
  33. package/dist/tsconfig.build.tsbuildinfo +1 -1
  34. package/package.json +34 -34
  35. package/src/core/common/helpers/input.helper.ts +32 -7
  36. package/src/core/common/helpers/model.helper.ts +16 -2
  37. package/src/core/common/helpers/service.helper.ts +18 -1
  38. package/src/core/common/interfaces/prepare-input-options.interface.ts +1 -0
  39. package/src/core/common/pipes/map-and-validate.pipe.ts +1 -1
  40. package/src/core/common/services/module.service.ts +2 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "9.0.21",
3
+ "version": "9.0.23",
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",
@@ -60,78 +60,78 @@
60
60
  "node": ">= 16.13.0"
61
61
  },
62
62
  "dependencies": {
63
- "@apollo/gateway": "2.1.4",
64
- "@nestjs/apollo": "10.1.4",
65
- "@nestjs/common": "9.1.6",
66
- "@nestjs/core": "9.1.6",
67
- "@nestjs/graphql": "10.1.5",
68
- "@nestjs/jwt": "9.0.0",
63
+ "@apollo/gateway": "2.2.3",
64
+ "@nestjs/apollo": "10.1.7",
65
+ "@nestjs/common": "9.2.1",
66
+ "@nestjs/core": "9.2.1",
67
+ "@nestjs/graphql": "10.1.7",
68
+ "@nestjs/jwt": "10.0.1",
69
69
  "@nestjs/mongoose": "9.2.1",
70
70
  "@nestjs/passport": "9.0.0",
71
- "@nestjs/platform-express": "9.1.6",
71
+ "@nestjs/platform-express": "9.2.1",
72
72
  "@nestjs/schedule": "2.1.0",
73
73
  "apollo-server-core": "3.11.1",
74
74
  "apollo-server-express": "3.11.1",
75
75
  "bcrypt": "5.1.0",
76
76
  "class-transformer": "0.5.1",
77
- "class-validator": "0.13.2",
77
+ "class-validator": "0.14.0",
78
78
  "ejs": "3.1.8",
79
79
  "graphql": "16.6.0",
80
80
  "graphql-subscriptions": "2.0.0",
81
81
  "graphql-upload": "15.0.2",
82
82
  "js-sha256": "0.9.0",
83
83
  "json-to-graphql-query": "2.2.4",
84
- "light-my-request": "5.6.1",
84
+ "light-my-request": "5.8.0",
85
85
  "lodash": "4.17.21",
86
- "mongodb": "4.11.0",
87
- "mongoose": "6.7.1",
86
+ "mongodb": "4.13.0",
87
+ "mongoose": "6.8.3",
88
88
  "mongoose-gridfs": "1.3.0",
89
89
  "multer-gridfs-storage": "5.0.2",
90
90
  "multer": "1.4.5-lts.1",
91
- "node-mailjet": "5.1.1",
92
- "nodemailer": "6.8.0",
91
+ "node-mailjet": "6.0.1",
92
+ "nodemailer": "6.9.0",
93
93
  "nodemon": "2.0.20",
94
94
  "passport": "0.6.0",
95
- "passport-jwt": "4.0.0",
95
+ "passport-jwt": "4.0.1",
96
96
  "reflect-metadata": "0.1.13",
97
97
  "rfdc": "1.3.0",
98
- "rimraf": "3.0.2",
99
- "rxjs": "7.5.7"
98
+ "rimraf": "4.0.4",
99
+ "rxjs": "7.8.0"
100
100
  },
101
101
  "devDependencies": {
102
- "@nestjs/testing": "9.1.6",
102
+ "@nestjs/testing": "9.2.1",
103
103
  "@types/cron": "2.0.0",
104
104
  "@types/ejs": "3.1.1",
105
- "@types/jest": "29.2.2",
106
- "@types/lodash": "4.14.188",
105
+ "@types/jest": "29.2.5",
106
+ "@types/lodash": "4.14.191",
107
107
  "@types/multer": "1.4.7",
108
- "@types/node": "18.11.9",
109
- "@types/nodemailer": "6.4.6",
108
+ "@types/node": "18.11.18",
109
+ "@types/nodemailer": "6.4.7",
110
110
  "@types/passport": "1.0.11",
111
111
  "@types/supertest": "2.0.12",
112
- "@typescript-eslint/eslint-plugin": "5.42.0",
113
- "@typescript-eslint/parser": "5.42.0",
112
+ "@typescript-eslint/eslint-plugin": "5.48.1",
113
+ "@typescript-eslint/parser": "5.48.1",
114
114
  "coffeescript": "2.7.0",
115
- "eslint": "8.27.0",
116
- "eslint-config-prettier": "8.5.0",
115
+ "eslint": "8.31.0",
116
+ "eslint-config-prettier": "8.6.0",
117
117
  "find-file-up": "2.0.1",
118
118
  "grunt": "1.5.3",
119
119
  "grunt-bg-shell": "2.3.3",
120
120
  "grunt-contrib-clean": "2.0.1",
121
121
  "grunt-contrib-watch": "1.1.0",
122
122
  "grunt-sync": "0.8.2",
123
- "husky": "8.0.1",
124
- "jest": "29.2.2",
123
+ "husky": "8.0.3",
124
+ "jest": "29.3.1",
125
125
  "npm-watch": "0.11.0",
126
126
  "pm2": "5.2.2",
127
- "prettier": "2.7.1",
127
+ "prettier": "2.8.3",
128
128
  "pretty-quick": "3.1.3",
129
- "supertest": "6.3.1",
130
- "ts-jest": "29.0.3",
131
- "ts-morph": "16.0.0",
129
+ "supertest": "6.3.3",
130
+ "ts-jest": "29.0.5",
131
+ "ts-morph": "17.0.1",
132
132
  "ts-node": "10.9.1",
133
- "tsconfig-paths": "4.1.0",
134
- "typescript": "4.8.4",
133
+ "tsconfig-paths": "4.1.2",
134
+ "typescript": "4.9.4",
135
135
  "yalc": "1.0.0-pre.53"
136
136
  },
137
137
  "overrides": {
@@ -222,6 +222,7 @@ export async function check(
222
222
  throwError: true,
223
223
  ...options,
224
224
  validatorOptions: {
225
+ forbidUnknownValues: false,
225
226
  skipUndefinedProperties: true,
226
227
  ...options?.validatorOptions,
227
228
  },
@@ -648,13 +649,29 @@ export function instanceofArray(arr: any[], strict = false): string {
648
649
 
649
650
  /**
650
651
  * Process data via function deep
651
- * @param data
652
- * @param func
653
- * @param processedObjects
654
652
  */
655
- export function processDeep(data: any, func: (data: any) => any, processedObjects = new WeakMap()): any {
653
+ export function processDeep(
654
+ data: any,
655
+ func: (data: any) => any,
656
+ options?: {
657
+ processedObjects?: WeakMap<new () => any, boolean>;
658
+ specialClasses?: ((new (args: any[]) => any) | string)[];
659
+ }
660
+ ): any {
661
+ // Set options
662
+ const { processedObjects, specialClasses } = {
663
+ processedObjects: new WeakMap(),
664
+ specialClasses: [],
665
+ ...options,
666
+ };
667
+
668
+ // Check for falsifiable values
669
+ if (!data) {
670
+ return func(data);
671
+ }
672
+
656
673
  // Prevent circular processing
657
- if (typeof data === 'object') {
674
+ else if (typeof data === 'object') {
658
675
  if (processedObjects.get(data)) {
659
676
  return data;
660
677
  }
@@ -663,13 +680,21 @@ export function processDeep(data: any, func: (data: any) => any, processedObject
663
680
 
664
681
  // Process array
665
682
  if (Array.isArray(data)) {
666
- return data.map((item) => processDeep(item, func));
683
+ return data.map((item) => processDeep(item, func, { processedObjects, specialClasses }));
667
684
  }
668
685
 
669
686
  // Process object
670
687
  if (typeof data === 'object') {
688
+ for (const specialClass of specialClasses) {
689
+ if (
690
+ (typeof specialClass === 'string' && specialClass === data.constructor.name) ||
691
+ (typeof specialClass !== 'string' && data instanceof specialClass)
692
+ ) {
693
+ return func(data);
694
+ }
695
+ }
671
696
  for (const [key, value] of Object.entries(data)) {
672
- data[key] = processDeep(value, func, processedObjects);
697
+ data[key] = processDeep(value, func, { processedObjects, specialClasses });
673
698
  }
674
699
  return data;
675
700
  }
@@ -164,6 +164,7 @@ export function maps<T = Record<string, any>>(
164
164
  * @param input - The input object to map
165
165
  * @param mapping - A mapping of property names to classes
166
166
  * @param [target] - The object to map the input to. If not provided, a new object will be created
167
+ * @param [options] - Additional settings for processing
167
168
  * @returns Record with mapped objects
168
169
  */
169
170
  export function mapClasses<T = Record<string, any>>(
@@ -193,8 +194,14 @@ export function mapClasses<T = Record<string, any>>(
193
194
  const targetClass = mapTarget as any;
194
195
  const value = input[prop];
195
196
 
197
+ // Do not process null (undefined is removed at the end)
198
+ if (value === null) {
199
+ target[prop] = null;
200
+ continue;
201
+ }
202
+
196
203
  // Process array
197
- if (Array.isArray(value)) {
204
+ else if (Array.isArray(value)) {
198
205
  const arr = [];
199
206
  for (const item of value) {
200
207
  if (item instanceof targetClass) {
@@ -248,6 +255,7 @@ export function mapClasses<T = Record<string, any>>(
248
255
  * @param input - The input object to map
249
256
  * @param mapping - A mapping of property names to classes
250
257
  * @param [target] - The object to map the input to. If not provided, a new object will be created
258
+ * @param [options] - Additional settings for processing
251
259
  * @returns Record with mapped objects
252
260
  */
253
261
  export async function mapClassesAsync<T = Record<string, any>>(
@@ -277,8 +285,14 @@ export async function mapClassesAsync<T = Record<string, any>>(
277
285
  const targetClass = mapTarget as any;
278
286
  const value = input[prop];
279
287
 
288
+ // Do not process zero (undefined is removed at the end)
289
+ if (value === null) {
290
+ target[prop] = null;
291
+ continue;
292
+ }
293
+
280
294
  // Process array
281
- if (Array.isArray(value)) {
295
+ else if (Array.isArray(value)) {
282
296
  const arr = [];
283
297
  for (const item of value) {
284
298
  if (item instanceof targetClass) {
@@ -10,7 +10,8 @@ import { PrepareOutputOptions } from '../interfaces/prepare-output-options.inter
10
10
  import { ResolveSelector } from '../interfaces/resolve-selector.interface';
11
11
  import { ServiceOptions } from '../interfaces/service-options.interface';
12
12
  import { ConfigService } from '../services/config.service';
13
- import { clone } from './input.helper';
13
+ import { getStringIds } from './db.helper';
14
+ import { clone, processDeep } from './input.helper';
14
15
 
15
16
  /**
16
17
  * Helper class for services
@@ -66,6 +67,7 @@ export async function prepareInput<T = any>(
66
67
  [key: string]: any;
67
68
  checkRoles?: boolean;
68
69
  circles?: boolean;
70
+ convertObjectIdsToString?: boolean;
69
71
  create?: boolean;
70
72
  clone?: boolean;
71
73
  getNewArray?: boolean;
@@ -80,6 +82,7 @@ export async function prepareInput<T = any>(
80
82
  checkRoles: false,
81
83
  clone: false,
82
84
  circles: false,
85
+ convertObjectIdsToString: true,
83
86
  create: false,
84
87
  getNewArray: false,
85
88
  proto: false,
@@ -114,6 +117,20 @@ export async function prepareInput<T = any>(
114
117
  }
115
118
  }
116
119
 
120
+ // Convert ObjectIds to string
121
+ if (config.convertObjectIdsToString) {
122
+ input = processDeep(
123
+ input,
124
+ (property) => {
125
+ if (property instanceof Types.ObjectId) {
126
+ property = getStringIds(property);
127
+ }
128
+ return property;
129
+ },
130
+ { specialClasses: ['ObjectId'] }
131
+ );
132
+ }
133
+
117
134
  // Map input if target model exist
118
135
  if (config.targetModel && !(input instanceof config.targetModel)) {
119
136
  if ((config.targetModel as any)?.map) {
@@ -4,6 +4,7 @@
4
4
  export interface PrepareInputOptions {
5
5
  [key: string]: any;
6
6
  checkRoles?: boolean;
7
+ convertObjectIdsToString?: boolean;
7
8
  create?: boolean;
8
9
  clone?: boolean;
9
10
  getNewArray?: boolean;
@@ -22,7 +22,7 @@ export class MapAndValidatePipe implements PipeTransform {
22
22
  }
23
23
 
24
24
  // Validate
25
- const errors = await validate(value);
25
+ const errors = await validate(value, { forbidUnknownValues: false });
26
26
  if (errors.length > 0) {
27
27
  throw new BadRequestException('Input validation failed:' + errors.join('; '));
28
28
  }
@@ -111,7 +111,7 @@ export abstract class ModuleService<T extends CoreModel = any> {
111
111
  if (!opts.targetModel && config.inputType) {
112
112
  opts.targetModel = config.inputType;
113
113
  }
114
- config.input = await this.prepareInput(config.input, opts);
114
+ config.input = await this.prepareInput(config.input, config);
115
115
  }
116
116
 
117
117
  // Get DB object
@@ -156,7 +156,7 @@ export abstract class ModuleService<T extends CoreModel = any> {
156
156
  if (config.outputPath) {
157
157
  _.set(result, config.outputPath, await this.prepareOutput(_.get(result, config.outputPath), opts));
158
158
  } else {
159
- result = await this.prepareOutput(result, opts);
159
+ result = await this.prepareOutput(result, config);
160
160
  }
161
161
  }
162
162