@lenne.tech/nest-server 9.0.20 → 9.0.21

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "9.0.20",
3
+ "version": "9.0.21",
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",
@@ -30,7 +30,7 @@
30
30
  "start": "npm run start:local",
31
31
  "stop": "./node_modules/.bin/pm2 delete nest",
32
32
  "start:pm2": "./node_modules/.bin/grunt",
33
- "start:prod": "./node_modules/.bin/grunt productive",
33
+ "start:prod": "./node_modules/.bin/grunt production",
34
34
  "start:nodemon": "ts-node -r tsconfig-paths/register src/main.ts",
35
35
  "start:debug": "nodemon --config nodemon-debug.json",
36
36
  "start:dev": "nodemon",
package/src/config.env.ts CHANGED
@@ -160,7 +160,7 @@ const config: { [env: string]: IServerOptions } = {
160
160
  verificationLink: 'http://localhost:4200/user/verification',
161
161
  passwordResetLink: 'http://localhost:4200/user/password-reset',
162
162
  },
163
- env: 'productive',
163
+ env: 'production',
164
164
  execAfterInit: 'npm run docs:bootstrap',
165
165
  filter: {
166
166
  maxLimit: null,
@@ -44,6 +44,9 @@ export const Restricted = (...rolesOrMember: RestrictedType): ClassDecorator & P
44
44
  * Get restricted data for (property of) object
45
45
  */
46
46
  export const getRestricted = (object: unknown, propertyKey?: string): RestrictedType => {
47
+ if (!object) {
48
+ return null;
49
+ }
47
50
  if (!propertyKey) {
48
51
  return Reflect.getMetadata(restrictedMetaKey, object);
49
52
  }
@@ -7,6 +7,7 @@ import * as rfdc from 'rfdc';
7
7
  import { checkRestricted } from '../decorators/restricted.decorator';
8
8
  import { ProcessType } from '../enums/process-type.enum';
9
9
  import { RoleEnum } from '../enums/role.enum';
10
+ import { merge } from './config.helper';
10
11
  import { equalIds } from './db.helper';
11
12
 
12
13
  /**
@@ -537,6 +538,24 @@ export function isString(parameter: string, falseFunction: (...params) => any =
537
538
  return typeof parameter === 'string' ? true : falseFunction(isString);
538
539
  }
539
540
 
541
+ /**
542
+ * Merge plain objects deep into target object and ignores undefined
543
+ */
544
+ export function mergePlain(target: Record<any, any>, ...args: Record<any, any>[]): any {
545
+ return merge(
546
+ target,
547
+ ...args.map(
548
+ // Prepare records
549
+ (item) =>
550
+ !item
551
+ ? // Return item if not an object
552
+ item
553
+ : // Return cloned record with undefined properties removed
554
+ filterProperties(clone(item, { circles: false }), (prop) => prop !== undefined)
555
+ )
556
+ );
557
+ }
558
+
540
559
  /**
541
560
  * Alternative for errorFunction
542
561
  */
@@ -9,9 +9,6 @@ import { clone } from './input.helper';
9
9
  export class ModelHelper {
10
10
  /**
11
11
  * Remove all properties from source which are not in target
12
- * @param source
13
- * @param target
14
- * @param options
15
12
  */
16
13
  public static prepareMap<T = Record<string, any>>(
17
14
  source: Partial<T> | Record<string, any>,
@@ -54,9 +51,6 @@ export class ModelHelper {
54
51
 
55
52
  /**
56
53
  * Remove all properties from source which are not in target
57
- * @param source
58
- * @param target
59
- * @param options
60
54
  */
61
55
  export function prepareMap<T = Record<string, any>>(
62
56
  source: Partial<T> | Record<string, any>,
@@ -176,7 +170,7 @@ export function mapClasses<T = Record<string, any>>(
176
170
  input: Record<string, any>,
177
171
  mapping: Record<string, new (...args: any[]) => any>,
178
172
  target?: T,
179
- options?: { objectIdsToString?: boolean }
173
+ options?: { objectIdsToString?: boolean; removeUndefinedProperties?: boolean }
180
174
  ): T {
181
175
  // Check params
182
176
  if (!target) {
@@ -189,6 +183,7 @@ export function mapClasses<T = Record<string, any>>(
189
183
  // Get config
190
184
  const config = {
191
185
  objectIdsToString: true,
186
+ removeUndefinedProperties: false,
192
187
  ...options,
193
188
  };
194
189
 
@@ -238,7 +233,7 @@ export function mapClasses<T = Record<string, any>>(
238
233
  }
239
234
 
240
235
  // Others
241
- else {
236
+ else if (!config.removeUndefinedProperties || value !== undefined) {
242
237
  target[prop] = value;
243
238
  }
244
239
  }
@@ -259,7 +254,7 @@ export async function mapClassesAsync<T = Record<string, any>>(
259
254
  input: Record<string, any>,
260
255
  mapping: Record<string, new (...args: any[]) => any>,
261
256
  target?: T,
262
- options?: { objectIdsToString?: boolean }
257
+ options?: { objectIdsToString?: boolean; removeUndefinedProperties?: boolean }
263
258
  ): Promise<T> {
264
259
  // Check params
265
260
  if (!target) {
@@ -272,6 +267,7 @@ export async function mapClassesAsync<T = Record<string, any>>(
272
267
  // Get config
273
268
  const config = {
274
269
  objectIdsToString: true,
270
+ removeUndefinedProperties: false,
275
271
  ...options,
276
272
  };
277
273
 
@@ -321,7 +317,7 @@ export async function mapClassesAsync<T = Record<string, any>>(
321
317
  }
322
318
 
323
319
  // Others
324
- else {
320
+ else if (!config.removeUndefinedProperties || value !== undefined) {
325
321
  target[prop] = value;
326
322
  }
327
323
  }
@@ -329,3 +325,37 @@ export async function mapClassesAsync<T = Record<string, any>>(
329
325
 
330
326
  return target;
331
327
  }
328
+
329
+ /**
330
+ * Same as mapClasses but with option removeUndefinedProperties = true as default
331
+ */
332
+ export function mapInputClasses<T = Record<string, any>>(
333
+ input: Record<string, any>,
334
+ mapping: Record<string, new (...args: any[]) => any>,
335
+ target?: T,
336
+ options?: { objectIdsToString?: boolean; removeUndefinedProperties?: boolean }
337
+ ) {
338
+ // Get config
339
+ const config = {
340
+ removeUndefinedProperties: true,
341
+ ...options,
342
+ };
343
+ return mapClasses(input, mapping, target, options);
344
+ }
345
+
346
+ /**
347
+ * Same as mapClassesAsync but with option removeUndefinedProperties = true as default
348
+ */
349
+ export function mapInputClassesAsync<T = Record<string, any>>(
350
+ input: Record<string, any>,
351
+ mapping: Record<string, new (...args: any[]) => any>,
352
+ target?: T,
353
+ options?: { objectIdsToString?: boolean; removeUndefinedProperties?: boolean }
354
+ ) {
355
+ // Get config
356
+ const config = {
357
+ removeUndefinedProperties: true,
358
+ ...options,
359
+ };
360
+ return mapClassesAsync(input, mapping, target, options);
361
+ }
@@ -4,7 +4,7 @@ import { FilterArgs } from '../args/filter.args';
4
4
  import { merge } from '../helpers/config.helper';
5
5
  import { getStringIds } from '../helpers/db.helper';
6
6
  import { convertFilterArgsToQuery } from '../helpers/filter.helper';
7
- import { assignPlain } from '../helpers/input.helper';
7
+ import { mergePlain } from '../helpers/input.helper';
8
8
  import { ServiceOptions } from '../interfaces/service-options.interface';
9
9
  import { CoreModel } from '../models/core-model.model';
10
10
  import { ConfigService } from './config.service';
@@ -388,7 +388,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
388
388
  return this.process(
389
389
  async (data) => {
390
390
  const currentUserId = serviceOptions?.currentUser?.id;
391
- return await assignPlain(dbObject, data.input, { updatedBy: currentUserId }).save();
391
+ return await mergePlain(dbObject, data.input, { updatedBy: currentUserId }).save();
392
392
  },
393
393
  { dbObject, input, serviceOptions }
394
394
  );