@lenne.tech/nest-server 9.2.5 → 9.2.6

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 (30) hide show
  1. package/dist/core/common/helpers/input.helper.d.ts +2 -0
  2. package/dist/core/common/helpers/input.helper.js +9 -3
  3. package/dist/core/common/helpers/input.helper.js.map +1 -1
  4. package/dist/core/common/interceptors/check-security.interceptor.js +4 -1
  5. package/dist/core/common/interceptors/check-security.interceptor.js.map +1 -1
  6. package/dist/core/common/models/core-model.model.js.map +1 -1
  7. package/dist/core/common/services/crud.service.d.ts +32 -30
  8. package/dist/core/common/services/crud.service.js +4 -4
  9. package/dist/core/common/services/crud.service.js.map +1 -1
  10. package/dist/core/common/types/is-one-of.type.d.ts +3 -0
  11. package/dist/core/common/types/is-one-of.type.js +3 -0
  12. package/dist/core/common/types/is-one-of.type.js.map +1 -0
  13. package/dist/core/modules/user/core-user.service.d.ts +1 -1
  14. package/dist/core/modules/user/core-user.service.js +1 -1
  15. package/dist/core/modules/user/core-user.service.js.map +1 -1
  16. package/dist/index.d.ts +1 -0
  17. package/dist/index.js +1 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/server/modules/auth/auth.module.js +3 -2
  20. package/dist/server/modules/auth/auth.module.js.map +1 -1
  21. package/dist/tsconfig.build.tsbuildinfo +1 -1
  22. package/package.json +1 -1
  23. package/src/core/common/helpers/input.helper.ts +17 -3
  24. package/src/core/common/interceptors/check-security.interceptor.ts +13 -6
  25. package/src/core/common/models/core-model.model.ts +1 -1
  26. package/src/core/common/services/crud.service.ts +46 -39
  27. package/src/core/common/types/is-one-of.type.ts +26 -0
  28. package/src/core/modules/user/core-user.service.ts +2 -2
  29. package/src/index.ts +1 -0
  30. package/src/server/modules/auth/auth.module.ts +3 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "9.2.5",
3
+ "version": "9.2.6",
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",
@@ -654,14 +654,22 @@ export function processDeep(
654
654
  data: any,
655
655
  func: (data: any) => any,
656
656
  options?: {
657
+ // Remember already processed objects to avoid infinite processes
657
658
  processedObjects?: WeakMap<new () => any, boolean>;
659
+
660
+ // For objects of special classes or objects with special functions or special properties,
661
+ // only the objects themselves are processed with func, not the individual properties of the object additionally
658
662
  specialClasses?: ((new (args: any[]) => any) | string)[];
663
+ specialFunctions?: string[];
664
+ specialProperties?: string[];
659
665
  }
660
666
  ): any {
661
667
  // Set options
662
- const { processedObjects, specialClasses } = {
668
+ const { processedObjects, specialClasses, specialFunctions, specialProperties } = {
663
669
  processedObjects: new WeakMap(),
664
670
  specialClasses: [],
671
+ specialFunctions: [],
672
+ specialProperties: [],
665
673
  ...options,
666
674
  };
667
675
 
@@ -680,11 +688,17 @@ export function processDeep(
680
688
 
681
689
  // Process array
682
690
  if (Array.isArray(data)) {
683
- return data.map((item) => processDeep(item, func, { processedObjects, specialClasses }));
691
+ return func(data.map((item) => processDeep(item, func, { processedObjects, specialClasses })));
684
692
  }
685
693
 
686
694
  // Process object
687
695
  if (typeof data === 'object') {
696
+ if (
697
+ specialFunctions.find((sF) => typeof data[sF] === 'function') ||
698
+ specialProperties.find((sP) => Object.getOwnPropertyNames(data).includes(sP))
699
+ ) {
700
+ return func(data);
701
+ }
688
702
  for (const specialClass of specialClasses) {
689
703
  if (
690
704
  (typeof specialClass === 'string' && specialClass === data.constructor?.name) ||
@@ -696,7 +710,7 @@ export function processDeep(
696
710
  for (const [key, value] of Object.entries(data)) {
697
711
  data[key] = processDeep(value, func, { processedObjects, specialClasses });
698
712
  }
699
- return data;
713
+ return func(data);
700
714
  }
701
715
 
702
716
  // Process others
@@ -40,12 +40,19 @@ export class CheckSecurityInterceptor implements NestInterceptor {
40
40
  }
41
41
 
42
42
  // Check deep
43
- return processDeep(data, (item) => {
44
- if (!item || typeof item !== 'object' || typeof item.securityCheck !== 'function') {
45
- return item;
46
- }
47
- return item.securityCheck(user, force);
48
- });
43
+ return processDeep(
44
+ data,
45
+ (item) => {
46
+ if (!item || typeof item !== 'object' || typeof item.securityCheck !== 'function') {
47
+ if (Array.isArray(item)) {
48
+ return item.filter((i) => i !== undefined);
49
+ }
50
+ return item;
51
+ }
52
+ return item.securityCheck(user, force);
53
+ },
54
+ { specialFunctions: ['securityCheck'] }
55
+ );
49
56
  })
50
57
  );
51
58
  }
@@ -129,7 +129,7 @@ export abstract class CoreModel {
129
129
  /**
130
130
  * Verification of the user's rights to access the properties of this object
131
131
  */
132
- securityCheck(user: any, force?: boolean): this {
132
+ public securityCheck(user: any, force?: boolean): this {
133
133
  return this;
134
134
  }
135
135
  }
@@ -6,14 +6,19 @@ import { convertFilterArgsToQuery } from '../helpers/filter.helper';
6
6
  import { mergePlain, prepareServiceOptionsForCreate } from '../helpers/input.helper';
7
7
  import { ServiceOptions } from '../interfaces/service-options.interface';
8
8
  import { CoreModel } from '../models/core-model.model';
9
+ import { PlainObject } from '../types/plain-object.type';
9
10
  import { ConfigService } from './config.service';
10
11
  import { ModuleService } from './module.service';
11
12
 
12
- export abstract class CrudService<T extends CoreModel = any> extends ModuleService<T> {
13
+ export abstract class CrudService<
14
+ Model extends CoreModel = any,
15
+ CreateInput = any,
16
+ UpdateInput = any
17
+ > extends ModuleService<Model> {
13
18
  /**
14
19
  * Create item
15
20
  */
16
- async create(input: any, serviceOptions?: ServiceOptions): Promise<T> {
21
+ async create(input: PlainObject<CreateInput>, serviceOptions?: ServiceOptions): Promise<Model> {
17
22
  serviceOptions = prepareServiceOptionsForCreate(serviceOptions);
18
23
  return this.process(
19
24
  async (data) => {
@@ -28,7 +33,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
28
33
  * Create item without checks or restrictions
29
34
  * Warning: Disables the handling of rights and restrictions!
30
35
  */
31
- async createForce(input: any, serviceOptions: ServiceOptions = {}): Promise<T> {
36
+ async createForce(input: PlainObject<CreateInput>, serviceOptions: ServiceOptions = {}): Promise<Model> {
32
37
  serviceOptions = serviceOptions || {};
33
38
  serviceOptions.force = true;
34
39
  return this.create(input, serviceOptions);
@@ -38,7 +43,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
38
43
  * Create item without checks, restrictions or preparations
39
44
  * Warning: Disables the handling of rights and restrictions! The raw data may contain secrets (such as passwords).
40
45
  */
41
- async createRaw(input: any, serviceOptions: ServiceOptions = {}): Promise<T> {
46
+ async createRaw(input: PlainObject<CreateInput>, serviceOptions: ServiceOptions = {}): Promise<Model> {
42
47
  serviceOptions = serviceOptions || {};
43
48
  serviceOptions.prepareInput = null;
44
49
  serviceOptions.prepareOutput = null;
@@ -48,7 +53,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
48
53
  /**
49
54
  * Get item by ID
50
55
  */
51
- async get(id: string, serviceOptions?: ServiceOptions): Promise<T> {
56
+ async get(id: string, serviceOptions?: ServiceOptions): Promise<Model> {
52
57
  const dbObject = await this.mainDbModel.findById(id).exec();
53
58
  if (!dbObject) {
54
59
  throw new NotFoundException(`No ${this.mainModelConstructor.name} found with ID: ${id}`);
@@ -60,7 +65,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
60
65
  * Get item by ID without checks or restrictions
61
66
  * Warning: Disables the handling of rights and restrictions!
62
67
  */
63
- async getForce(id: string, serviceOptions: ServiceOptions = {}): Promise<T> {
68
+ async getForce(id: string, serviceOptions: ServiceOptions = {}): Promise<Model> {
64
69
  serviceOptions = serviceOptions || {};
65
70
  serviceOptions.force = true;
66
71
  return this.get(id, serviceOptions);
@@ -70,7 +75,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
70
75
  * Get item by ID without checks, restrictions or preparations
71
76
  * Warning: Disables the handling of rights and restrictions! The raw data may contain secrets (such as passwords).
72
77
  */
73
- async getRaw(id: string, serviceOptions: ServiceOptions = {}): Promise<T> {
78
+ async getRaw(id: string, serviceOptions: ServiceOptions = {}): Promise<Model> {
74
79
  serviceOptions = serviceOptions || {};
75
80
  serviceOptions.prepareInput = null;
76
81
  serviceOptions.prepareOutput = null;
@@ -83,7 +88,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
83
88
  async find(
84
89
  filter?: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions; samples?: number },
85
90
  serviceOptions?: ServiceOptions
86
- ): Promise<T[]> {
91
+ ): Promise<Model[]> {
87
92
  // If filter is not instance of FilterArgs a simple form with filterQuery and queryOptions is set
88
93
  // and should not be processed as FilterArgs
89
94
  if (!(filter instanceof FilterArgs) && serviceOptions?.inputType === FilterArgs) {
@@ -124,7 +129,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
124
129
  async findForce(
125
130
  filter?: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions; samples?: number },
126
131
  serviceOptions: ServiceOptions = {}
127
- ): Promise<T[]> {
132
+ ): Promise<Model[]> {
128
133
  serviceOptions = serviceOptions || {};
129
134
  serviceOptions.force = true;
130
135
  return this.find(filter, serviceOptions);
@@ -137,7 +142,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
137
142
  async findRaw(
138
143
  filter?: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions; samples?: number },
139
144
  serviceOptions: ServiceOptions = {}
140
- ): Promise<T[]> {
145
+ ): Promise<Model[]> {
141
146
  serviceOptions = serviceOptions || {};
142
147
  serviceOptions.prepareInput = null;
143
148
  serviceOptions.prepareOutput = null;
@@ -150,7 +155,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
150
155
  async findAndCount(
151
156
  filter?: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions; samples?: number },
152
157
  serviceOptions?: ServiceOptions
153
- ): Promise<{ items: T[]; totalCount: number }> {
158
+ ): Promise<{ items: Model[]; totalCount: number }> {
154
159
  // If filter is not instance of FilterArgs a simple form with filterQuery and queryOptions is set
155
160
  // and should not be processed as FilterArgs
156
161
  if (!(filter instanceof FilterArgs) && serviceOptions?.inputType === FilterArgs) {
@@ -229,7 +234,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
229
234
  async findAndCountForce(
230
235
  filter?: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions; samples?: number },
231
236
  serviceOptions: ServiceOptions = {}
232
- ): Promise<{ items: T[]; totalCount: number }> {
237
+ ): Promise<{ items: Model[]; totalCount: number }> {
233
238
  serviceOptions = serviceOptions || {};
234
239
  serviceOptions.force = true;
235
240
  return this.findAndCount(filter, serviceOptions);
@@ -242,7 +247,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
242
247
  async findAndCountRaw(
243
248
  filter?: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions; samples?: number },
244
249
  serviceOptions: ServiceOptions = {}
245
- ): Promise<{ items: T[]; totalCount: number }> {
250
+ ): Promise<{ items: Model[]; totalCount: number }> {
246
251
  serviceOptions = serviceOptions || {};
247
252
  serviceOptions.prepareInput = null;
248
253
  serviceOptions.prepareOutput = null;
@@ -253,15 +258,15 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
253
258
  * Find and update
254
259
  */
255
260
  async findAndUpdate(
256
- filter: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions },
257
- update: any,
261
+ filter: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions; samples?: number },
262
+ update: PlainObject<UpdateInput>,
258
263
  serviceOptions?: ServiceOptions
259
- ): Promise<T[]> {
260
- const dbItems: T[] = await this.find(filter, serviceOptions);
264
+ ): Promise<Model[]> {
265
+ const dbItems: Model[] = await this.find(filter, serviceOptions);
261
266
  if (!dbItems?.length) {
262
267
  return [];
263
268
  }
264
- const promises: Promise<T>[] = [];
269
+ const promises: Promise<Model>[] = [];
265
270
  for (const dbItem of dbItems) {
266
271
  promises.push(
267
272
  new Promise(async (resolve, reject) => {
@@ -282,12 +287,13 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
282
287
  * Warning: Disables the handling of rights and restrictions!
283
288
  */
284
289
  async findAndUpdateForce(
285
- filter?: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions; samples?: number },
290
+ filter: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions; samples?: number },
291
+ update: PlainObject<UpdateInput>,
286
292
  serviceOptions: ServiceOptions = {}
287
- ): Promise<T[]> {
293
+ ): Promise<Model[]> {
288
294
  serviceOptions = serviceOptions || {};
289
295
  serviceOptions.force = true;
290
- return this.findAndUpdate(filter, serviceOptions);
296
+ return this.findAndUpdate(filter, update, serviceOptions);
291
297
  }
292
298
 
293
299
  /**
@@ -295,19 +301,20 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
295
301
  * Warning: Disables the handling of rights and restrictions! The raw data may contain secrets (such as passwords).
296
302
  */
297
303
  async findAndUpdateRaw(
298
- filter?: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions; samples?: number },
304
+ filter: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions; samples?: number },
305
+ update: PlainObject<UpdateInput>,
299
306
  serviceOptions: ServiceOptions = {}
300
- ): Promise<T[]> {
307
+ ): Promise<Model[]> {
301
308
  serviceOptions = serviceOptions || {};
302
309
  serviceOptions.prepareInput = null;
303
310
  serviceOptions.prepareOutput = null;
304
- return this.findAndUpdateForce(filter, serviceOptions);
311
+ return this.findAndUpdateForce(filter, update, serviceOptions);
305
312
  }
306
313
 
307
314
  /**
308
315
  * CRUD alias for get
309
316
  */
310
- async read(id: string, serviceOptions?: ServiceOptions): Promise<T>;
317
+ async read(id: string, serviceOptions?: ServiceOptions): Promise<Model>;
311
318
 
312
319
  /**
313
320
  * CRUD alias for find
@@ -315,7 +322,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
315
322
  async read(
316
323
  filter: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions },
317
324
  serviceOptions?: ServiceOptions
318
- ): Promise<T[]>;
325
+ ): Promise<Model[]>;
319
326
 
320
327
  /**
321
328
  * CRUD alias for get or find
@@ -323,7 +330,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
323
330
  async read(
324
331
  input: string | FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions },
325
332
  serviceOptions?: ServiceOptions
326
- ): Promise<T | T[]> {
333
+ ): Promise<Model | Model[]> {
327
334
  if (typeof input === 'string') {
328
335
  return this.get(input, serviceOptions);
329
336
  } else {
@@ -335,7 +342,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
335
342
  * CRUD alias for getForce
336
343
  * Warning: Disables the handling of rights and restrictions!
337
344
  */
338
- async readForce(id: string, serviceOptions?: ServiceOptions): Promise<T>;
345
+ async readForce(id: string, serviceOptions?: ServiceOptions): Promise<Model>;
339
346
 
340
347
  /**
341
348
  * CRUD alias for findForce
@@ -344,7 +351,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
344
351
  async readForce(
345
352
  filter: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions },
346
353
  serviceOptions?: ServiceOptions
347
- ): Promise<T[]>;
354
+ ): Promise<Model[]>;
348
355
 
349
356
  /**
350
357
  * CRUD alias for getForce or findForce
@@ -353,7 +360,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
353
360
  async readForce(
354
361
  input: string | FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions },
355
362
  serviceOptions?: ServiceOptions
356
- ): Promise<T | T[]> {
363
+ ): Promise<Model | Model[]> {
357
364
  if (typeof input === 'string') {
358
365
  return this.getForce(input, serviceOptions);
359
366
  } else {
@@ -365,7 +372,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
365
372
  * CRUD alias for getRaw
366
373
  * Warning: Disables the handling of rights and restrictions! The raw data may contain secrets (such as passwords).
367
374
  */
368
- async readRaw(id: string, serviceOptions?: ServiceOptions): Promise<T>;
375
+ async readRaw(id: string, serviceOptions?: ServiceOptions): Promise<Model>;
369
376
 
370
377
  /**
371
378
  * CRUD alias for findRaw
@@ -374,7 +381,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
374
381
  async readRaw(
375
382
  filter: FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions },
376
383
  serviceOptions?: ServiceOptions
377
- ): Promise<T[]>;
384
+ ): Promise<Model[]>;
378
385
 
379
386
  /**
380
387
  * CRUD alias for getRaw or findRaw
@@ -383,7 +390,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
383
390
  async readRaw(
384
391
  input: string | FilterArgs | { filterQuery?: FilterQuery<any>; queryOptions?: QueryOptions },
385
392
  serviceOptions?: ServiceOptions
386
- ): Promise<T | T[]> {
393
+ ): Promise<Model | Model[]> {
387
394
  if (typeof input === 'string') {
388
395
  return this.getRaw(input, serviceOptions);
389
396
  } else {
@@ -394,7 +401,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
394
401
  /**
395
402
  * Update item via ID
396
403
  */
397
- async update(id: string, input: any, serviceOptions?: ServiceOptions): Promise<T> {
404
+ async update(id: string, input: PlainObject<UpdateInput>, serviceOptions?: ServiceOptions): Promise<Model> {
398
405
  const dbObject = await this.mainDbModel.findById(id).lean();
399
406
  if (!dbObject) {
400
407
  throw new NotFoundException(`No ${this.mainModelConstructor.name} found with ID: ${id}`);
@@ -413,7 +420,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
413
420
  * Update item via ID without checks or restrictions
414
421
  * Warning: Disables the handling of rights and restrictions!
415
422
  */
416
- async updateForce(id: string, input: any, serviceOptions?: ServiceOptions): Promise<T> {
423
+ async updateForce(id: string, input: PlainObject<UpdateInput>, serviceOptions?: ServiceOptions): Promise<Model> {
417
424
  serviceOptions = serviceOptions || {};
418
425
  serviceOptions.force = true;
419
426
  return this.update(id, input, serviceOptions);
@@ -423,7 +430,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
423
430
  * Update item via ID without checks, restrictions or preparations
424
431
  * Warning: Disables the handling of rights and restrictions! The raw data may contain secrets (such as passwords).
425
432
  */
426
- async updateRaw(id: string, input: any, serviceOptions?: ServiceOptions): Promise<T> {
433
+ async updateRaw(id: string, input: PlainObject<UpdateInput>, serviceOptions?: ServiceOptions): Promise<Model> {
427
434
  serviceOptions = serviceOptions || {};
428
435
  serviceOptions.prepareInput = null;
429
436
  serviceOptions.prepareOutput = null;
@@ -433,7 +440,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
433
440
  /**
434
441
  * Delete item via ID
435
442
  */
436
- async delete(id: string, serviceOptions?: ServiceOptions): Promise<T> {
443
+ async delete(id: string, serviceOptions?: ServiceOptions): Promise<Model> {
437
444
  const dbObject = await this.mainDbModel.findById(id).exec();
438
445
  if (!dbObject) {
439
446
  throw new NotFoundException(`No ${this.mainModelConstructor.name} found with ID: ${id}`);
@@ -451,7 +458,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
451
458
  * Delete item via ID without checks or restrictions
452
459
  * Warning: Disables the handling of rights and restrictions!
453
460
  */
454
- async deleteForce(id: string, serviceOptions?: ServiceOptions): Promise<T> {
461
+ async deleteForce(id: string, serviceOptions?: ServiceOptions): Promise<Model> {
455
462
  serviceOptions = serviceOptions || {};
456
463
  serviceOptions.force = true;
457
464
  return this.delete(id, serviceOptions);
@@ -461,7 +468,7 @@ export abstract class CrudService<T extends CoreModel = any> extends ModuleServi
461
468
  * Delete item via ID without checks, restrictions or preparations
462
469
  * Warning: Disables the handling of rights and restrictions! The raw data may contain secrets (such as passwords).
463
470
  */
464
- async deleteRaw(id: string, serviceOptions?: ServiceOptions): Promise<T> {
471
+ async deleteRaw(id: string, serviceOptions?: ServiceOptions): Promise<Model> {
465
472
  serviceOptions = serviceOptions || {};
466
473
  serviceOptions.prepareInput = null;
467
474
  serviceOptions.prepareOutput = null;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Type that ensures that the property or method is of a specific class
3
+ *
4
+ * Example (see https://stackoverflow.com/a/66202968):
5
+ *
6
+ * interface myFunctions{
7
+ * one: () => number;
8
+ * two: () => number;
9
+ * echo: (str: string) => string;
10
+ * }
11
+ *
12
+ * const myFunctions: myFunctions = {
13
+ * one: () => 1,
14
+ * two: () => 2,
15
+ * echo: (str: string) => str
16
+ * }
17
+ *
18
+ * const wrapper = <U extends (...args: any[]) => any>(func: U extends IsOneOf<myFunctions, U> ? U : never) => (...args: Parameters<U>) : ReturnType<U> => func(...args);
19
+ *
20
+ * const one = wrapper(myFunctions.one);
21
+ * const two = wrapper(myFunctions.two);
22
+ * const echo = wrapper(myFunctions.echo);
23
+ * const rand = wrapper((a:string,b:number,c:boolean) => {}); //not assignable to parameter of type 'never'.
24
+ * const hm = wrapper(() => 'a'); //also error
25
+ */
26
+ export type IsOneOf<T, F> = { [P in keyof T]: F extends T[P] ? (T[P] extends F ? T[P] : never) : never }[keyof T];
@@ -20,7 +20,7 @@ export abstract class CoreUserService<
20
20
  TUser extends CoreUserModel,
21
21
  TUserInput extends CoreUserInput,
22
22
  TUserCreateInput extends CoreUserCreateInput
23
- > extends CrudService<TUser> {
23
+ > extends CrudService<TUser, TUserCreateInput, TUserInput> {
24
24
  protected constructor(
25
25
  protected override readonly configService: ConfigService,
26
26
  protected readonly emailService: EmailService,
@@ -54,7 +54,7 @@ export abstract class CoreUserService<
54
54
  try {
55
55
  await createdUser.save();
56
56
  } catch (error) {
57
- if (error.code === 11000) {
57
+ if (error?.errors?.email?.kind === 'unique') {
58
58
  throw new BadRequestException('Email address already in use');
59
59
  } else {
60
60
  throw new UnprocessableEntityException();
package/src/index.ts CHANGED
@@ -64,6 +64,7 @@ export * from './core/common/types/core-model-constructor.type';
64
64
  export * from './core/common/types/falsy.type';
65
65
  export * from './core/common/types/field-selection.type';
66
66
  export * from './core/common/types/ids.type';
67
+ export * from './core/common/types/is-one-of.type';
67
68
  export * from './core/common/types/maybe-promise.type';
68
69
  export * from './core/common/types/plain-input.type';
69
70
  export * from './core/common/types/plain-object.type';
@@ -4,6 +4,7 @@ import { EmailService } from '../../../core/common/services/email.service';
4
4
  import { CoreAuthModule } from '../../../core/modules/auth/core-auth.module';
5
5
  import { UserModule } from '../user/user.module';
6
6
  import { UserService } from '../user/user.service';
7
+ import { AuthController } from './auth.controller';
7
8
  import { AuthResolver } from './auth.resolver';
8
9
  import { AuthService } from './auth.service';
9
10
 
@@ -28,8 +29,8 @@ export class AuthModule {
28
29
  },
29
30
  }),
30
31
  ],
31
- providers: [AuthResolver, AuthService, EmailService],
32
- exports: [AuthResolver, CoreAuthModule],
32
+ providers: [AuthController, AuthResolver, AuthService, EmailService],
33
+ exports: [AuthController, AuthResolver, CoreAuthModule],
33
34
  };
34
35
  }
35
36
  }