@lenne.tech/nest-server 8.6.26 → 8.6.29

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 (50) hide show
  1. package/dist/config.env.js +37 -12
  2. package/dist/config.env.js.map +1 -1
  3. package/dist/core/common/helpers/input.helper.d.ts +10 -1
  4. package/dist/core/common/helpers/input.helper.js +46 -4
  5. package/dist/core/common/helpers/input.helper.js.map +1 -1
  6. package/dist/core/common/helpers/model.helper.d.ts +4 -0
  7. package/dist/core/common/helpers/model.helper.js +22 -15
  8. package/dist/core/common/helpers/model.helper.js.map +1 -1
  9. package/dist/core/common/helpers/service.helper.d.ts +12 -0
  10. package/dist/core/common/helpers/service.helper.js +15 -8
  11. package/dist/core/common/helpers/service.helper.js.map +1 -1
  12. package/dist/core/common/interfaces/server-options.interface.d.ts +1 -0
  13. package/dist/core/common/services/config.service.d.ts +75 -5
  14. package/dist/core/common/services/config.service.js +168 -4
  15. package/dist/core/common/services/config.service.js.map +1 -1
  16. package/dist/core/common/services/email.service.js +2 -2
  17. package/dist/core/common/services/email.service.js.map +1 -1
  18. package/dist/core/common/services/mailjet.service.js +4 -4
  19. package/dist/core/common/services/mailjet.service.js.map +1 -1
  20. package/dist/core/common/services/template.service.js +1 -1
  21. package/dist/core/common/services/template.service.js.map +1 -1
  22. package/dist/core/modules/user/core-user.service.d.ts +5 -3
  23. package/dist/core/modules/user/core-user.service.js +5 -3
  24. package/dist/core/modules/user/core-user.service.js.map +1 -1
  25. package/dist/server/common/services/cron-jobs.service.d.ts +3 -1
  26. package/dist/server/common/services/cron-jobs.service.js +5 -4
  27. package/dist/server/common/services/cron-jobs.service.js.map +1 -1
  28. package/dist/server/modules/auth/auth.service.d.ts +3 -1
  29. package/dist/server/modules/auth/auth.service.js +9 -4
  30. package/dist/server/modules/auth/auth.service.js.map +1 -1
  31. package/dist/server/modules/user/user.service.js +5 -3
  32. package/dist/server/modules/user/user.service.js.map +1 -1
  33. package/dist/server/server.controller.js +2 -2
  34. package/dist/server/server.controller.js.map +1 -1
  35. package/dist/tsconfig.build.tsbuildinfo +1 -1
  36. package/package.json +10 -9
  37. package/src/config.env.ts +39 -12
  38. package/src/core/common/helpers/input.helper.ts +68 -4
  39. package/src/core/common/helpers/model.helper.ts +26 -15
  40. package/src/core/common/helpers/service.helper.ts +27 -8
  41. package/src/core/common/interfaces/server-options.interface.ts +8 -1
  42. package/src/core/common/services/config.service.ts +378 -12
  43. package/src/core/common/services/email.service.ts +2 -2
  44. package/src/core/common/services/mailjet.service.ts +4 -4
  45. package/src/core/common/services/template.service.ts +1 -1
  46. package/src/core/modules/user/core-user.service.ts +7 -4
  47. package/src/server/common/services/cron-jobs.service.ts +3 -3
  48. package/src/server/modules/auth/auth.service.ts +7 -3
  49. package/src/server/modules/user/user.service.ts +5 -3
  50. package/src/server/server.controller.ts +2 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "8.6.26",
3
+ "version": "8.6.29",
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",
@@ -18,7 +18,7 @@
18
18
  "build:pack": "npm pack && echo 'use file:/ROOT_PATH_TO_TGZ_FILE to integrate the package'",
19
19
  "docs": "npm run docs:ci && open ./public/index.html",
20
20
  "docs:bootstrap": "node extras/update-spectaql-version.mjs && npx -y spectaql ./spectaql.yml",
21
- "docs:ci": "ts-node ./scripts/init-server.ts && npm run docs:boostrap",
21
+ "docs:ci": "ts-node ./scripts/init-server.ts && npm run docs:bootstrap",
22
22
  "format": "prettier --write 'src/**/*.ts'",
23
23
  "format:staged": "pretty-quick --staged",
24
24
  "lint": "eslint \"{src,tests}/**/*.ts\" --fix",
@@ -82,7 +82,7 @@
82
82
  "light-my-request": "5.0.0",
83
83
  "lodash": "4.17.21",
84
84
  "mongodb": "4.7.0",
85
- "mongoose": "6.4.1",
85
+ "mongoose": "6.4.2",
86
86
  "mongoose-gridfs": "1.3.0",
87
87
  "multer": "1.4.5-lts.1",
88
88
  "node-mailjet": "5.0.1",
@@ -91,6 +91,7 @@
91
91
  "passport": "0.6.0",
92
92
  "passport-jwt": "4.0.0",
93
93
  "reflect-metadata": "0.1.13",
94
+ "rfdc": "1.3.0",
94
95
  "rimraf": "3.0.2",
95
96
  "rxjs": "7.5.5"
96
97
  },
@@ -101,14 +102,14 @@
101
102
  "@types/jest": "28.1.4",
102
103
  "@types/lodash": "4.14.182",
103
104
  "@types/multer": "1.4.7",
104
- "@types/node": "18.0.0",
105
+ "@types/node": "18.0.1",
105
106
  "@types/nodemailer": "6.4.4",
106
107
  "@types/passport": "1.0.9",
107
108
  "@types/supertest": "2.0.12",
108
- "@typescript-eslint/eslint-plugin": "5.30.0",
109
- "@typescript-eslint/parser": "5.30.0",
109
+ "@typescript-eslint/eslint-plugin": "5.30.5",
110
+ "@typescript-eslint/parser": "5.30.5",
110
111
  "coffeescript": "2.7.0",
111
- "eslint": "8.18.0",
112
+ "eslint": "8.19.0",
112
113
  "eslint-config-prettier": "8.5.0",
113
114
  "find-file-up": "2.0.1",
114
115
  "grunt": "1.5.3",
@@ -121,10 +122,10 @@
121
122
  "pm2": "5.2.0",
122
123
  "prettier": "2.7.1",
123
124
  "pretty-quick": "3.1.3",
124
- "supertest": "6.2.3",
125
+ "supertest": "6.2.4",
125
126
  "ts-jest": "28.0.5",
126
127
  "ts-morph": "15.1.0",
127
- "ts-node": "10.8.1",
128
+ "ts-node": "10.8.2",
128
129
  "tsconfig-paths": "4.0.0",
129
130
  "typescript": "4.7.4"
130
131
  },
package/src/config.env.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { CronExpression } from '@nestjs/schedule';
2
2
  import { join } from 'path';
3
+ import { merge } from './core/common/helpers/config.helper';
3
4
  import { IServerOptions } from './core/common/interfaces/server-options.interface';
4
5
 
5
6
  /**
@@ -22,8 +23,8 @@ const config: { [env: string]: IServerOptions } = {
22
23
  email: {
23
24
  smtp: {
24
25
  auth: {
25
- user: 'rebeca68@ethereal.email',
26
- pass: 'v5WUScAN98AzGbRjpc',
26
+ user: 'sandra98@ethereal.email',
27
+ pass: 'JCQQdz8xJEfBSewahK',
27
28
  },
28
29
  host: 'smtp.ethereal.email',
29
30
  port: 587,
@@ -34,8 +35,8 @@ const config: { [env: string]: IServerOptions } = {
34
35
  api_key_private: 'MAILJET_API_KEY_PRIVATE',
35
36
  },
36
37
  defaultSender: {
37
- email: 'rebeca68@ethereal.email',
38
- name: 'Rebeca Sixtyeight',
38
+ email: 'sandra98@ethereal.email',
39
+ name: 'Sandra Klein',
39
40
  },
40
41
  verificationLink: 'http://localhost:4200/user/verification',
41
42
  passwordResetLink: 'http://localhost:4200/user/password-reset',
@@ -51,6 +52,7 @@ const config: { [env: string]: IServerOptions } = {
51
52
  jwt: {
52
53
  secret: 'SECRET_OR_PRIVATE_KEY_DEV',
53
54
  },
55
+ loadLocalConfig: false,
54
56
  mongoose: {
55
57
  uri: 'mongodb://localhost/nest-server-dev',
56
58
  },
@@ -73,8 +75,8 @@ const config: { [env: string]: IServerOptions } = {
73
75
  email: {
74
76
  smtp: {
75
77
  auth: {
76
- user: 'rebeca68@ethereal.email',
77
- pass: 'v5WUScAN98AzGbRjpc',
78
+ user: 'sandra98@ethereal.email',
79
+ pass: 'JCQQdz8xJEfBSewahK',
78
80
  },
79
81
  host: 'smtp.ethereal.email',
80
82
  port: 587,
@@ -85,8 +87,8 @@ const config: { [env: string]: IServerOptions } = {
85
87
  api_key_private: 'MAILJET_API_KEY_PRIVATE',
86
88
  },
87
89
  defaultSender: {
88
- email: 'rebeca68@ethereal.email',
89
- name: 'Rebeca Sixtyeight',
90
+ email: 'sandra98@ethereal.email',
91
+ name: 'Sandra Klein',
90
92
  },
91
93
  verificationLink: 'http://localhost:4200/user/verification',
92
94
  passwordResetLink: 'http://localhost:4200/user/password-reset',
@@ -102,6 +104,7 @@ const config: { [env: string]: IServerOptions } = {
102
104
  jwt: {
103
105
  secret: 'SECRET_OR_PRIVATE_KEY_DEV',
104
106
  },
107
+ loadLocalConfig: false,
105
108
  mongoose: {
106
109
  uri: 'mongodb://localhost/nest-server-dev',
107
110
  },
@@ -124,8 +127,8 @@ const config: { [env: string]: IServerOptions } = {
124
127
  email: {
125
128
  smtp: {
126
129
  auth: {
127
- user: 'rebeca68@ethereal.email',
128
- pass: 'v5WUScAN98AzGbRjpc',
130
+ user: 'sandra98@ethereal.email',
131
+ pass: 'JCQQdz8xJEfBSewahK',
129
132
  },
130
133
  host: 'smtp.ethereal.email',
131
134
  port: 587,
@@ -136,8 +139,8 @@ const config: { [env: string]: IServerOptions } = {
136
139
  api_key_private: 'MAILJET_API_KEY_PRIVATE',
137
140
  },
138
141
  defaultSender: {
139
- email: 'rebeca68@ethereal.email',
140
- name: 'Rebeca Sixtyeight',
142
+ email: 'sandra98@ethereal.email',
143
+ name: 'Sandra Klein',
141
144
  },
142
145
  verificationLink: 'http://localhost:4200/user/verification',
143
146
  passwordResetLink: 'http://localhost:4200/user/password-reset',
@@ -153,6 +156,7 @@ const config: { [env: string]: IServerOptions } = {
153
156
  jwt: {
154
157
  secret: 'SECRET_OR_PRIVATE_KEY_PROD',
155
158
  },
159
+ loadLocalConfig: false,
156
160
  mongoose: {
157
161
  uri: 'mongodb://localhost/nest-server-prod',
158
162
  },
@@ -178,6 +182,29 @@ const env = process.env['NODE' + '_ENV'] || 'development';
178
182
  const envConfig = config[env] || config.development;
179
183
  console.info('Configured for: ' + envConfig.env + (env !== envConfig.env ? ' (requested: ' + env + ')' : ''));
180
184
 
185
+ // Merge with localConfig (e.g. config.json)
186
+ if (envConfig.loadLocalConfig) {
187
+ let localConfig;
188
+ if (typeof envConfig.loadLocalConfig === 'string') {
189
+ localConfig = require(envConfig.loadLocalConfig);
190
+ merge(envConfig, localConfig);
191
+ } else {
192
+ try {
193
+ // get config from src directory
194
+ localConfig = require(__dirname + '/config.json');
195
+ merge(envConfig, localConfig);
196
+ } catch {
197
+ try {
198
+ // if not found try to find in project directory
199
+ localConfig = require(__dirname + '/../config.json');
200
+ merge(envConfig, localConfig);
201
+ } catch (e) {
202
+ // No config.json found => nothing to do
203
+ }
204
+ }
205
+ }
206
+ }
207
+
181
208
  /**
182
209
  * Export envConfig as default
183
210
  */
@@ -3,6 +3,7 @@ import { plainToInstance } from 'class-transformer';
3
3
  import { validate } from 'class-validator';
4
4
  import { ValidatorOptions } from 'class-validator/types/validation/ValidatorOptions';
5
5
  import * as _ from 'lodash';
6
+ import * as rfdc from 'rfdc';
6
7
  import { checkRestricted } from '../decorators/restricted.decorator';
7
8
  import { ProcessType } from '../enums/process-type.enum';
8
9
  import { RoleEnum } from '../enums/role.enum';
@@ -196,7 +197,7 @@ export function assignPlain(target: Record<any, any>, ...args: Record<any, any>[
196
197
  ? // Return item if not an object
197
198
  item
198
199
  : // Return cloned record with undefined properties removed
199
- filterProperties(JSON.parse(JSON.stringify(item)), (prop) => prop !== undefined)
200
+ filterProperties(clone(item, { circles: false }), (prop) => prop !== undefined)
200
201
  )
201
202
  );
202
203
  }
@@ -297,6 +298,44 @@ export async function check(
297
298
  return value;
298
299
  }
299
300
 
301
+ /**
302
+ * Clone object
303
+ * @param object Any object
304
+ * @param options Finetuning of rfdc cloning
305
+ * @param options.proto Copy prototype properties as well as own properties into the new object.
306
+ * It's marginally faster to allow enumerable properties on the prototype to be copied into the
307
+ * cloned object (not onto it's prototype, directly onto the object).
308
+ * @param options.circles Keeping track of circular references will slow down performance with an additional 25% overhead.
309
+ * Even if an object doesn't have any circular references, the tracking overhead is the cost.
310
+ * By default if an object with a circular reference is passed to rfdc, it will throw
311
+ * (similar to how JSON.stringify would throw). Use the circles option to detect and preserve
312
+ * circular references in the object. If performance is important, try removing the circular
313
+ * reference from the object (set to undefined) and then add it back manually after cloning
314
+ * instead of using this option.
315
+ */
316
+ export function clone(object: any, options?: { proto?: boolean; circles?: boolean }) {
317
+ const config = {
318
+ proto: false,
319
+ circles: true,
320
+ ...options,
321
+ };
322
+ try {
323
+ return rfdc(config)(object);
324
+ } catch (e) {
325
+ console.debug(e);
326
+ if (!config.circles) {
327
+ try {
328
+ return rfdc({ ...config, ...{ circles: true } })(object);
329
+ } catch (e) {
330
+ console.debug(e);
331
+ return _.clone(object);
332
+ }
333
+ } else {
334
+ return _.clone(object);
335
+ }
336
+ }
337
+ }
338
+
300
339
  /**
301
340
  * Combines objects to a new single plain object and ignores undefined
302
341
  */
@@ -304,6 +343,19 @@ export function combinePlain(...args: Record<any, any>[]): any {
304
343
  return assignPlain({}, ...args);
305
344
  }
306
345
 
346
+ /**
347
+ * Get deep frozen object
348
+ */
349
+ export function deepFreeze(object: any) {
350
+ if (typeof object !== 'object') {
351
+ return object;
352
+ }
353
+ for (const [key, value] of Object.entries(object)) {
354
+ object[key] = deepFreeze(value);
355
+ }
356
+ return Object.freeze(object);
357
+ }
358
+
307
359
  /**
308
360
  * Standard error function
309
361
  */
@@ -327,7 +379,6 @@ export function filterProperties<T = Record<string, any>>(
327
379
 
328
380
  /**
329
381
  * Get plain copy of object
330
- * @param element
331
382
  */
332
383
  export function getPlain(object: any) {
333
384
  return JSON.parse(JSON.stringify(object));
@@ -512,11 +563,24 @@ export function match(expression: any, cases: Record<any, any>): any {
512
563
  /**
513
564
  * Map values into specific type
514
565
  */
515
- export function mapClass<T>(values: Partial<T>, ctor: new () => T, cloneDeep = true): T {
566
+ export function mapClass<T>(
567
+ values: Partial<T>,
568
+ ctor: new () => T,
569
+ options?: {
570
+ cloneDeep?: boolean;
571
+ circle?: boolean;
572
+ proto?: boolean;
573
+ }
574
+ ): T {
575
+ const config = {
576
+ cloneDeep: true,
577
+ circles: false,
578
+ proto: false,
579
+ };
516
580
  const instance = new ctor();
517
581
 
518
582
  return Object.keys(instance).reduce((obj, key) => {
519
- obj[key] = cloneDeep ? _.cloneDeep(values[key]) : values[key];
583
+ obj[key] = config.cloneDeep ? clone(values[key], { circles: config.circles, proto: config.proto }) : values[key];
520
584
  return obj;
521
585
  }, instance);
522
586
  }
@@ -1,6 +1,6 @@
1
1
  import { plainToInstance } from 'class-transformer';
2
- import * as _ from 'lodash';
3
2
  import { Types } from 'mongoose';
3
+ import { clone } from './input.helper';
4
4
 
5
5
  /**
6
6
  * Helper class for models
@@ -63,15 +63,19 @@ export function prepareMap<T = Record<string, any>>(
63
63
  target: T,
64
64
  options: {
65
65
  cloneDeep?: boolean;
66
+ circles?: boolean;
66
67
  funcAllowed?: boolean;
67
68
  mapId?: boolean;
69
+ proto?: boolean;
68
70
  } = {}
69
71
  ): Partial<T> | Record<string, any> {
70
72
  // Set config
71
73
  const config = {
72
74
  cloneDeep: true,
75
+ circles: true,
73
76
  funcAllowed: false,
74
77
  mapId: false,
78
+ proto: false,
75
79
  ...options,
76
80
  };
77
81
 
@@ -85,7 +89,10 @@ export function prepareMap<T = Record<string, any>>(
85
89
  source[key] !== undefined &&
86
90
  (config.funcAllowed || typeof (source[key] !== 'function'))
87
91
  ) {
88
- result[key] = source[key] !== 'function' && config.cloneDeep ? _.cloneDeep(source[key]) : source[key];
92
+ result[key] =
93
+ source[key] !== 'function' && config.cloneDeep
94
+ ? clone(source[key], { circles: config.circles, proto: config.proto })
95
+ : source[key];
89
96
  } else if (key === 'id' && !config.mapId) {
90
97
  result['id'] = source[key];
91
98
  }
@@ -102,21 +109,25 @@ export function map<T = Record<string, any>>(
102
109
  target: T,
103
110
  options: {
104
111
  cloneDeep?: boolean;
112
+ circles?: boolean;
105
113
  funcAllowed?: boolean;
106
114
  mapId?: boolean;
115
+ proto?: boolean;
107
116
  } = {}
108
117
  ): T {
109
118
  // Set config
110
119
  const config = {
111
120
  cloneDeep: true,
121
+ circles: false,
112
122
  funcAllowed: false,
113
123
  mapId: false,
124
+ proto: false,
114
125
  ...options,
115
126
  };
116
127
 
117
128
  // Check source
118
129
  if (!source || typeof source !== 'object' || Array.isArray(source)) {
119
- return config.cloneDeep ? _.cloneDeep(target) : target;
130
+ return config.cloneDeep ? clone(target, { circles: config.circles, proto: config.proto }) : target;
120
131
  }
121
132
 
122
133
  // Prepare source
@@ -191,18 +202,18 @@ export function mapClasses<T = Record<string, any>>(
191
202
  if (Array.isArray(value)) {
192
203
  const arr = [];
193
204
  for (const item of value) {
194
- if (value instanceof targetClass) {
195
- arr.push(value);
196
- } else if (value instanceof Types.ObjectId) {
197
- config.objectIdsToString ? arr.push(value.toHexString()) : arr.push(value);
198
- } else if (typeof value === 'object') {
205
+ if (item instanceof targetClass) {
206
+ arr.push(item);
207
+ } else if (item instanceof Types.ObjectId) {
208
+ config.objectIdsToString ? arr.push(item.toHexString()) : arr.push(item);
209
+ } else if (typeof item === 'object') {
199
210
  if (targetClass.map) {
200
211
  arr.push(targetClass.map(item));
201
212
  } else {
202
213
  arr.push(plainToInstance(targetClass, item));
203
214
  }
204
215
  } else {
205
- arr.push(value);
216
+ arr.push(item);
206
217
  }
207
218
  }
208
219
  target[prop] = arr as any;
@@ -274,18 +285,18 @@ export async function mapClassesAsync<T = Record<string, any>>(
274
285
  if (Array.isArray(value)) {
275
286
  const arr = [];
276
287
  for (const item of value) {
277
- if (value instanceof targetClass) {
278
- arr.push(value);
279
- } else if (value instanceof Types.ObjectId) {
280
- config.objectIdsToString ? arr.push(value.toHexString()) : arr.push(value);
281
- } else if (typeof value === 'object') {
288
+ if (item instanceof targetClass) {
289
+ arr.push(item);
290
+ } else if (item instanceof Types.ObjectId) {
291
+ config.objectIdsToString ? arr.push(item.toHexString()) : arr.push(item);
292
+ } else if (typeof item === 'object') {
282
293
  if (targetClass.map) {
283
294
  arr.push(await targetClass.map(item));
284
295
  } else {
285
296
  arr.push(plainToInstance(targetClass, item));
286
297
  }
287
298
  } else {
288
- arr.push(value);
299
+ arr.push(item);
289
300
  }
290
301
  }
291
302
  target[prop] = arr as any;
@@ -4,12 +4,13 @@ import { plainToInstance } from 'class-transformer';
4
4
  import { sha256 } from 'js-sha256';
5
5
  import * as _ from 'lodash';
6
6
  import { Types } from 'mongoose';
7
- import envConfig from '../../../config.env';
8
7
  import { RoleEnum } from '../enums/role.enum';
9
8
  import { PrepareInputOptions } from '../interfaces/prepare-input-options.interface';
10
9
  import { PrepareOutputOptions } from '../interfaces/prepare-output-options.interface';
11
10
  import { ResolveSelector } from '../interfaces/resolve-selector.interface';
12
11
  import { ServiceOptions } from '../interfaces/service-options.interface';
12
+ import { ConfigService } from '../services/config.service';
13
+ import { clone } from './input.helper';
13
14
 
14
15
  /**
15
16
  * Helper class for services
@@ -24,10 +25,13 @@ export default class ServiceHelper {
24
25
  currentUser: { [key: string]: any; id: string },
25
26
  options: {
26
27
  [key: string]: any;
28
+ checkRoles?: boolean;
27
29
  create?: boolean;
28
30
  clone?: boolean;
29
31
  getNewArray?: boolean;
30
32
  removeUndefined?: boolean;
33
+ sha256?: boolean;
34
+ targetModel?: new (...args: any[]) => T;
31
35
  } = {}
32
36
  ): Promise<T> {
33
37
  return prepareInput(input, currentUser, options);
@@ -42,6 +46,8 @@ export default class ServiceHelper {
42
46
  [key: string]: any;
43
47
  clone?: boolean;
44
48
  getNewArray?: boolean;
49
+ objectIdsToStrings?: boolean;
50
+ removeSecrets?: boolean;
45
51
  removeUndefined?: boolean;
46
52
  targetModel?: new (...args: any[]) => T;
47
53
  } = {}
@@ -59,10 +65,13 @@ export async function prepareInput<T = any>(
59
65
  options: {
60
66
  [key: string]: any;
61
67
  checkRoles?: boolean;
68
+ circles?: boolean;
62
69
  create?: boolean;
63
70
  clone?: boolean;
64
71
  getNewArray?: boolean;
72
+ proto?: boolean;
65
73
  removeUndefined?: boolean;
74
+ sha256?: boolean;
66
75
  targetModel?: new (...args: any[]) => T;
67
76
  } = {}
68
77
  ): Promise<T> {
@@ -70,9 +79,12 @@ export async function prepareInput<T = any>(
70
79
  const config = {
71
80
  checkRoles: false,
72
81
  clone: false,
82
+ circles: false,
73
83
  create: false,
74
84
  getNewArray: false,
85
+ proto: false,
75
86
  removeUndefined: true,
87
+ sha256: ConfigService.configFastButReadOnly.sha256,
76
88
  ...options,
77
89
  };
78
90
 
@@ -98,7 +110,7 @@ export async function prepareInput<T = any>(
98
110
  if ((input as Record<string, any>).mapDeep && typeof (input as any).mapDeep === 'function') {
99
111
  input = await Object.getPrototypeOf(input).mapDeep(input);
100
112
  } else {
101
- input = _.cloneDeep(input);
113
+ input = clone(input, { circles: config.circles, proto: config.proto });
102
114
  }
103
115
  }
104
116
 
@@ -134,10 +146,9 @@ export async function prepareInput<T = any>(
134
146
  if ((input as any).password) {
135
147
  // Check if the password was transmitted encrypted
136
148
  // If not, the password is encrypted to enable future encrypted and unencrypted transmissions
137
- (input as any).password =
138
- !envConfig.sha256 || /^[a-f0-9]{64}$/i.test((input as any).password)
139
- ? (input as any).password
140
- : sha256((input as any).password);
149
+ if (config.sha256 && !/^[a-f0-9]{64}$/i.test((input as any).password)) {
150
+ (input as any).password = sha256((input as any).password);
151
+ }
141
152
 
142
153
  // Hash password
143
154
  (input as any).password = await bcrypt.hash((input as any).password, 10);
@@ -165,8 +176,10 @@ export async function prepareOutput<T = { [key: string]: any; map: (...args: any
165
176
  options: {
166
177
  [key: string]: any;
167
178
  clone?: boolean;
179
+ circles?: boolean;
168
180
  getNewArray?: boolean;
169
181
  objectIdsToStrings?: boolean;
182
+ proto?: boolean;
170
183
  removeSecrets?: boolean;
171
184
  removeUndefined?: boolean;
172
185
  targetModel?: new (...args: any[]) => T;
@@ -175,8 +188,10 @@ export async function prepareOutput<T = { [key: string]: any; map: (...args: any
175
188
  // Configuration
176
189
  const config = {
177
190
  clone: false,
191
+ circles: false,
178
192
  getNewArray: false,
179
193
  objectIdsToStrings: true,
194
+ proto: false,
180
195
  removeSecrets: true,
181
196
  removeUndefined: false,
182
197
  targetModel: undefined,
@@ -205,7 +220,7 @@ export async function prepareOutput<T = { [key: string]: any; map: (...args: any
205
220
  if (output.mapDeep && typeof output.mapDeep === 'function') {
206
221
  output = await Object.getPrototypeOf(output).mapDeep(output);
207
222
  } else {
208
- output = _.cloneDeep(output);
223
+ output = clone(output, { circles: config.circles, proto: config.proto });
209
224
  }
210
225
  }
211
226
 
@@ -260,9 +275,11 @@ export function prepareServiceOptions(
260
275
  serviceOptions: ServiceOptions,
261
276
  options?: {
262
277
  clone?: boolean;
278
+ circles?: boolean;
263
279
  inputType?: any;
264
280
  outputType?: any;
265
281
  subFieldSelection?: string;
282
+ proto?: boolean;
266
283
  prepareInput?: PrepareInputOptions;
267
284
  prepareOutput?: PrepareOutputOptions;
268
285
  }
@@ -270,12 +287,14 @@ export function prepareServiceOptions(
270
287
  // Set default values
271
288
  const config = {
272
289
  clone: true,
290
+ circles: true,
291
+ proto: false,
273
292
  ...options,
274
293
  };
275
294
 
276
295
  // Clone
277
296
  if (serviceOptions && config.clone) {
278
- serviceOptions = _.cloneDeep(serviceOptions);
297
+ serviceOptions = clone(serviceOptions, { circles: config.circles, proto: config.proto });
279
298
  }
280
299
 
281
300
  // Init if not exists
@@ -4,7 +4,6 @@ import { JwtModuleOptions } from '@nestjs/jwt';
4
4
  import { MongooseModuleOptions } from '@nestjs/mongoose';
5
5
  import { ServeStaticOptions } from '@nestjs/platform-express/interfaces/serve-static-options.interface';
6
6
  import { CronExpression } from '@nestjs/schedule';
7
- import { sha256 } from 'js-sha256';
8
7
  import * as SMTPTransport from 'nodemailer/lib/smtp-transport';
9
8
  import { Falsy } from '../types/falsy.type';
10
9
  import { CronJobConfig } from './cron-job-config.interface';
@@ -129,6 +128,14 @@ export interface IServerOptions {
129
128
  secretOrPrivateKey?: string;
130
129
  } & JwtModuleOptions;
131
130
 
131
+ /**
132
+ * Load local configuration
133
+ * false: no local configuration is loaded,
134
+ * true: it tries to load ./config.json or ../config.json,
135
+ * string: path to configuration
136
+ */
137
+ loadLocalConfig?: boolean | string;
138
+
132
139
  /**
133
140
  * Configuration for Mongoose
134
141
  */