@lenne.tech/nest-server 8.0.2 → 8.3.0

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 (166) hide show
  1. package/dist/config.env.js +3 -2
  2. package/dist/config.env.js.map +1 -1
  3. package/dist/core/common/args/pagination.args.js +1 -1
  4. package/dist/core/common/args/pagination.args.js.map +1 -1
  5. package/dist/core/common/decorators/restricted.decorator.d.ts +3 -0
  6. package/dist/core/common/decorators/restricted.decorator.js +14 -8
  7. package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
  8. package/dist/core/common/enums/role.enum.d.ts +3 -2
  9. package/dist/core/common/enums/role.enum.js +3 -2
  10. package/dist/core/common/enums/role.enum.js.map +1 -1
  11. package/dist/core/common/helpers/config.helper.d.ts +2 -1
  12. package/dist/core/common/helpers/config.helper.js +11 -7
  13. package/dist/core/common/helpers/config.helper.js.map +1 -1
  14. package/dist/core/common/helpers/context.helper.d.ts +7 -1
  15. package/dist/core/common/helpers/context.helper.js +33 -29
  16. package/dist/core/common/helpers/context.helper.js.map +1 -1
  17. package/dist/core/common/helpers/db.helper.d.ts +37 -0
  18. package/dist/core/common/helpers/db.helper.js +356 -0
  19. package/dist/core/common/helpers/db.helper.js.map +1 -0
  20. package/dist/core/common/helpers/file.helper.d.ts +8 -1
  21. package/dist/core/common/helpers/file.helper.js +43 -31
  22. package/dist/core/common/helpers/file.helper.js.map +1 -1
  23. package/dist/core/common/helpers/filter.helper.d.ts +3 -0
  24. package/dist/core/common/helpers/filter.helper.js +93 -81
  25. package/dist/core/common/helpers/filter.helper.js.map +1 -1
  26. package/dist/core/common/helpers/graphql.helper.d.ts +24 -1
  27. package/dist/core/common/helpers/graphql.helper.js +144 -96
  28. package/dist/core/common/helpers/graphql.helper.js.map +1 -1
  29. package/dist/core/common/helpers/input.helper.d.ts +42 -4
  30. package/dist/core/common/helpers/input.helper.js +256 -97
  31. package/dist/core/common/helpers/input.helper.js.map +1 -1
  32. package/dist/core/common/helpers/model.helper.d.ts +11 -0
  33. package/dist/core/common/helpers/model.helper.js +41 -29
  34. package/dist/core/common/helpers/model.helper.js.map +1 -1
  35. package/dist/core/common/helpers/service.helper.d.ts +21 -1
  36. package/dist/core/common/helpers/service.helper.js +80 -72
  37. package/dist/core/common/helpers/service.helper.js.map +1 -1
  38. package/dist/core/common/inputs/combined-filter.input.js +1 -1
  39. package/dist/core/common/inputs/combined-filter.input.js.map +1 -1
  40. package/dist/core/common/inputs/core-input.input.js +1 -1
  41. package/dist/core/common/inputs/core-input.input.js.map +1 -1
  42. package/dist/core/common/interceptors/check-response.interceptor.js +1 -1
  43. package/dist/core/common/interceptors/check-response.interceptor.js.map +1 -1
  44. package/dist/core/common/interfaces/resolve-selector.interface.d.ts +5 -0
  45. package/dist/core/common/interfaces/resolve-selector.interface.js +3 -0
  46. package/dist/core/common/interfaces/resolve-selector.interface.js.map +1 -0
  47. package/dist/core/common/interfaces/service-options.interface.d.ts +36 -0
  48. package/dist/core/common/interfaces/service-options.interface.js +3 -0
  49. package/dist/core/common/interfaces/service-options.interface.js.map +1 -0
  50. package/dist/core/common/models/core-model.model.d.ts +5 -1
  51. package/dist/core/common/models/core-model.model.js +1 -1
  52. package/dist/core/common/models/core-model.model.js.map +1 -1
  53. package/dist/core/common/pipes/check-input.pipe.js +2 -2
  54. package/dist/core/common/pipes/check-input.pipe.js.map +1 -1
  55. package/dist/core/common/pipes/map-and-validate.pipe.js +1 -1
  56. package/dist/core/common/pipes/map-and-validate.pipe.js.map +1 -1
  57. package/dist/core/common/services/crud.service.d.ts +13 -0
  58. package/dist/core/common/services/crud.service.js +57 -0
  59. package/dist/core/common/services/crud.service.js.map +1 -0
  60. package/dist/core/common/services/email.service.js +8 -8
  61. package/dist/core/common/services/email.service.js.map +1 -1
  62. package/dist/core/common/services/module.service.d.ts +40 -0
  63. package/dist/core/common/services/module.service.js +80 -0
  64. package/dist/core/common/services/module.service.js.map +1 -0
  65. package/dist/core/common/types/core-model-constructor.type.d.ts +21 -0
  66. package/dist/core/common/types/core-model-constructor.type.js +3 -0
  67. package/dist/core/common/types/core-model-constructor.type.js.map +1 -0
  68. package/dist/core/common/types/field-selection.type.d.ts +4 -0
  69. package/dist/core/common/types/field-selection.type.js +3 -0
  70. package/dist/core/common/types/field-selection.type.js.map +1 -0
  71. package/dist/core/common/types/ids.type.d.ts +8 -0
  72. package/dist/core/common/types/ids.type.js +3 -0
  73. package/dist/core/common/types/ids.type.js.map +1 -0
  74. package/dist/core/common/types/string-or-object-id.type.d.ts +2 -0
  75. package/dist/core/common/types/string-or-object-id.type.js +3 -0
  76. package/dist/core/common/types/string-or-object-id.type.js.map +1 -0
  77. package/dist/core/modules/auth/core-auth.resolver.d.ts +2 -1
  78. package/dist/core/modules/auth/core-auth.resolver.js +4 -3
  79. package/dist/core/modules/auth/core-auth.resolver.js.map +1 -1
  80. package/dist/core/modules/auth/guards/roles.guard.js +1 -2
  81. package/dist/core/modules/auth/guards/roles.guard.js.map +1 -1
  82. package/dist/core/modules/auth/services/core-auth-user.service.d.ts +3 -1
  83. package/dist/core/modules/auth/services/core-auth-user.service.js.map +1 -1
  84. package/dist/core/modules/auth/services/core-auth.service.d.ts +2 -1
  85. package/dist/core/modules/auth/services/core-auth.service.js +6 -4
  86. package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
  87. package/dist/core/modules/user/core-user.model.js +1 -1
  88. package/dist/core/modules/user/core-user.model.js.map +1 -1
  89. package/dist/core/modules/user/core-user.service.d.ts +16 -25
  90. package/dist/core/modules/user/core-user.service.js +69 -90
  91. package/dist/core/modules/user/core-user.service.js.map +1 -1
  92. package/dist/core.module.js +1 -1
  93. package/dist/core.module.js.map +1 -1
  94. package/dist/index.d.ts +9 -1
  95. package/dist/index.js +9 -1
  96. package/dist/index.js.map +1 -1
  97. package/dist/server/modules/auth/auth.resolver.d.ts +2 -1
  98. package/dist/server/modules/auth/auth.resolver.js +4 -3
  99. package/dist/server/modules/auth/auth.resolver.js.map +1 -1
  100. package/dist/server/modules/file/file.controller.js +1 -1
  101. package/dist/server/modules/file/file.controller.js.map +1 -1
  102. package/dist/server/modules/user/avatar.controller.js +2 -2
  103. package/dist/server/modules/user/avatar.controller.js.map +1 -1
  104. package/dist/server/modules/user/user.model.d.ts +2 -1
  105. package/dist/server/modules/user/user.module.js +7 -3
  106. package/dist/server/modules/user/user.module.js.map +1 -1
  107. package/dist/server/modules/user/user.resolver.d.ts +8 -7
  108. package/dist/server/modules/user/user.resolver.js +85 -49
  109. package/dist/server/modules/user/user.resolver.js.map +1 -1
  110. package/dist/server/modules/user/user.service.d.ts +9 -18
  111. package/dist/server/modules/user/user.service.js +23 -30
  112. package/dist/server/modules/user/user.service.js.map +1 -1
  113. package/dist/test/test.helper.d.ts +1 -2
  114. package/dist/test/test.helper.js +1 -16
  115. package/dist/test/test.helper.js.map +1 -1
  116. package/dist/tsconfig.build.tsbuildinfo +1 -1
  117. package/package.json +58 -59
  118. package/src/config.env.ts +3 -2
  119. package/src/core/common/args/pagination.args.ts +2 -2
  120. package/src/core/common/decorators/restricted.decorator.ts +24 -12
  121. package/src/core/common/enums/role.enum.ts +23 -5
  122. package/src/core/common/helpers/config.helper.ts +26 -6
  123. package/src/core/common/helpers/context.helper.ts +42 -33
  124. package/src/core/common/helpers/db.helper.ts +595 -0
  125. package/src/core/common/helpers/file.helper.ts +76 -49
  126. package/src/core/common/helpers/filter.helper.ts +119 -96
  127. package/src/core/common/helpers/graphql.helper.ts +219 -117
  128. package/src/core/common/helpers/input.helper.ts +349 -108
  129. package/src/core/common/helpers/model.helper.ts +102 -57
  130. package/src/core/common/helpers/service.helper.ts +149 -117
  131. package/src/core/common/inputs/combined-filter.input.ts +2 -2
  132. package/src/core/common/inputs/core-input.input.ts +2 -2
  133. package/src/core/common/interceptors/check-response.interceptor.ts +2 -2
  134. package/src/core/common/interfaces/resolve-selector.interface.ts +9 -0
  135. package/src/core/common/interfaces/service-options.interface.ts +71 -0
  136. package/src/core/common/models/core-model.model.ts +7 -3
  137. package/src/core/common/pipes/check-input.pipe.ts +4 -4
  138. package/src/core/common/pipes/map-and-validate.pipe.ts +2 -2
  139. package/src/core/common/services/crud.service.ts +100 -0
  140. package/src/core/common/services/email.service.ts +9 -9
  141. package/src/core/common/services/module.service.ts +188 -0
  142. package/src/core/common/types/core-model-constructor.type.ts +30 -0
  143. package/src/core/common/types/field-selection.type.ts +8 -0
  144. package/src/core/common/types/ids.type.ts +7 -0
  145. package/src/core/common/types/string-or-object-id.type.ts +3 -0
  146. package/src/core/modules/auth/core-auth.module.ts +1 -1
  147. package/src/core/modules/auth/core-auth.resolver.ts +8 -3
  148. package/src/core/modules/auth/guards/roles.guard.ts +5 -7
  149. package/src/core/modules/auth/services/core-auth-user.service.ts +7 -1
  150. package/src/core/modules/auth/services/core-auth.service.ts +14 -4
  151. package/src/core/modules/user/core-user.model.ts +2 -1
  152. package/src/core/modules/user/core-user.service.ts +115 -185
  153. package/src/core.module.ts +2 -2
  154. package/src/index.ts +9 -1
  155. package/src/main.ts +1 -1
  156. package/src/server/modules/auth/auth.resolver.ts +8 -3
  157. package/src/server/modules/file/file.controller.ts +2 -2
  158. package/src/server/modules/user/avatar.controller.ts +3 -3
  159. package/src/server/modules/user/user.module.ts +7 -3
  160. package/src/server/modules/user/user.resolver.ts +74 -43
  161. package/src/server/modules/user/user.service.ts +30 -53
  162. package/src/test/test.helper.ts +31 -30
  163. package/dist/core/modules/user/core-basic-user.service.d.ts +0 -17
  164. package/dist/core/modules/user/core-basic-user.service.js +0 -73
  165. package/dist/core/modules/user/core-basic-user.service.js.map +0 -1
  166. package/src/core/modules/user/core-basic-user.service.ts +0 -138
@@ -2,6 +2,7 @@ import * as _ from 'lodash';
2
2
 
3
3
  /**
4
4
  * Helper class for models
5
+ * @deprecated use functions directly
5
6
  */
6
7
  export class ModelHelper {
7
8
  /**
@@ -19,31 +20,7 @@ export class ModelHelper {
19
20
  mapId?: boolean;
20
21
  } = {}
21
22
  ): Partial<T> | Record<string, any> {
22
- // Set config
23
- const config = {
24
- cloneDeep: true,
25
- funcAllowed: false,
26
- mapId: false,
27
- ...options,
28
- };
29
-
30
- // Initializations
31
- const result = {};
32
-
33
- // Update properties
34
- for (const key of Object.keys(target)) {
35
- if (
36
- (!['id', '_id'].includes(key) || config.mapId) &&
37
- source[key] !== undefined &&
38
- (config.funcAllowed || typeof (source[key] !== 'function'))
39
- ) {
40
- result[key] = source[key] !== 'function' && config.cloneDeep ? _.cloneDeep(source[key]) : source[key];
41
- } else if (key === 'id' && !config.mapId) {
42
- result['id'] = source[key];
43
- }
44
- }
45
-
46
- return result;
23
+ return prepareMap(source, target, options);
47
24
  }
48
25
 
49
26
  /**
@@ -58,27 +35,7 @@ export class ModelHelper {
58
35
  mapId?: boolean;
59
36
  } = {}
60
37
  ): T {
61
- // Set config
62
- const config = {
63
- cloneDeep: true,
64
- funcAllowed: false,
65
- mapId: false,
66
- ...options,
67
- };
68
-
69
- // Check source
70
- if (!source || typeof source !== 'object' || Array.isArray(source)) {
71
- return config.cloneDeep ? _.cloneDeep(target) : target;
72
- }
73
-
74
- // Prepare source
75
- const preparedSource = ModelHelper.prepareMap(source, target, config);
76
-
77
- // Merge target with prepared source
78
- Object.assign(target, preparedSource);
79
-
80
- // Return target
81
- return target;
38
+ return map(source, target, options);
82
39
  }
83
40
 
84
41
  /**
@@ -89,19 +46,107 @@ export class ModelHelper {
89
46
  targetClass: new (...args: any[]) => T,
90
47
  cloneDeep = true
91
48
  ): T[] {
92
- // Check data
93
- if (!data || typeof data !== 'object') {
94
- return undefined;
95
- }
49
+ return maps(data, targetClass, cloneDeep);
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Remove all properties from source which are not in target
55
+ * @param source
56
+ * @param target
57
+ * @param options
58
+ */
59
+ export function prepareMap<T = Record<string, any>>(
60
+ source: Partial<T> | Record<string, any>,
61
+ target: T,
62
+ options: {
63
+ cloneDeep?: boolean;
64
+ funcAllowed?: boolean;
65
+ mapId?: boolean;
66
+ } = {}
67
+ ): Partial<T> | Record<string, any> {
68
+ // Set config
69
+ const config = {
70
+ cloneDeep: true,
71
+ funcAllowed: false,
72
+ mapId: false,
73
+ ...options,
74
+ };
96
75
 
97
- // Check array
98
- if (!Array.isArray(data)) {
99
- data = [data];
76
+ // Initializations
77
+ const result = {};
78
+
79
+ // Update properties
80
+ for (const key of Object.keys(target)) {
81
+ if (
82
+ (!['id', '_id'].includes(key) || config.mapId) &&
83
+ source[key] !== undefined &&
84
+ (config.funcAllowed || typeof (source[key] !== 'function'))
85
+ ) {
86
+ result[key] = source[key] !== 'function' && config.cloneDeep ? _.cloneDeep(source[key]) : source[key];
87
+ } else if (key === 'id' && !config.mapId) {
88
+ result['id'] = source[key];
100
89
  }
90
+ }
101
91
 
102
- // Map
103
- return (data as any[]).map((item) => {
104
- return (targetClass as any).map(item, { cloneDeep });
105
- });
92
+ return result;
93
+ }
94
+
95
+ /**
96
+ * Simple map function
97
+ */
98
+ export function map<T = Record<string, any>>(
99
+ source: Partial<T> | Record<string, any>,
100
+ target: T,
101
+ options: {
102
+ cloneDeep?: boolean;
103
+ funcAllowed?: boolean;
104
+ mapId?: boolean;
105
+ } = {}
106
+ ): T {
107
+ // Set config
108
+ const config = {
109
+ cloneDeep: true,
110
+ funcAllowed: false,
111
+ mapId: false,
112
+ ...options,
113
+ };
114
+
115
+ // Check source
116
+ if (!source || typeof source !== 'object' || Array.isArray(source)) {
117
+ return config.cloneDeep ? _.cloneDeep(target) : target;
118
+ }
119
+
120
+ // Prepare source
121
+ const preparedSource = prepareMap(source, target, config);
122
+
123
+ // Merge target with prepared source
124
+ Object.assign(target, preparedSource);
125
+
126
+ // Return target
127
+ return target;
128
+ }
129
+
130
+ /**
131
+ * Create Object or Objects of specified type with specified data
132
+ */
133
+ export function maps<T = Record<string, any>>(
134
+ data: Partial<T> | Partial<T>[] | Record<string, any> | Record<string, any>[],
135
+ targetClass: new (...args: any[]) => T,
136
+ cloneDeep = true
137
+ ): T[] {
138
+ // Check data
139
+ if (!data || typeof data !== 'object') {
140
+ return undefined;
141
+ }
142
+
143
+ // Check array
144
+ if (!Array.isArray(data)) {
145
+ data = [data];
106
146
  }
147
+
148
+ // Map
149
+ return (data as any[]).map((item) => {
150
+ return (targetClass as any).map(item, { cloneDeep });
151
+ });
107
152
  }
@@ -5,8 +5,9 @@ import { RoleEnum } from '../enums/role.enum';
5
5
 
6
6
  /**
7
7
  * Helper class for services
8
+ * @deprecated use functions directly
8
9
  */
9
- export class ServiceHelper {
10
+ export default class ServiceHelper {
10
11
  /**
11
12
  * Prepare input before save
12
13
  */
@@ -21,78 +22,7 @@ export class ServiceHelper {
21
22
  removeUndefined?: boolean;
22
23
  } = {}
23
24
  ): Promise<T> {
24
- // Configuration
25
- const config = {
26
- checkRoles: false,
27
- clone: false,
28
- create: false,
29
- getNewArray: false,
30
- removeUndefined: false,
31
- ...options,
32
- };
33
-
34
- // Check input
35
- if (typeof input !== 'object') {
36
- return input;
37
- }
38
-
39
- // Process array
40
- if (Array.isArray(input)) {
41
- const processedArray = input.map(
42
- async (item) => await ServiceHelper.prepareInput(item, currentUser, options)
43
- ) as any;
44
- return config.getNewArray ? processedArray : input;
45
- }
46
-
47
- // Clone input
48
- if (config.clone) {
49
- if ((input as Record<string, any>).mapDeep && typeof (input as any).mapDeep === 'function') {
50
- input = await Object.getPrototypeOf(input).mapDeep(input);
51
- } else {
52
- input = _.cloneDeep(input);
53
- }
54
- }
55
-
56
- // Remove undefined properties to avoid unwanted overwrites
57
- if (config.removeUndefined) {
58
- Object.keys(input).forEach((key) => input[key] === undefined && delete input[key]);
59
- }
60
-
61
- // Process roles
62
- if (
63
- config.checkRoles &&
64
- (input as Record<string, any>).roles &&
65
- (!currentUser?.hasRole || !currentUser.hasRole(RoleEnum.ADMIN))
66
- ) {
67
- if (!(currentUser as any)?.roles) {
68
- throw new UnauthorizedException('Missing roles of current user');
69
- } else {
70
- const allowedRoles = _.intersection((input as Record<string, any>).roles, (currentUser as any).roles);
71
- if (allowedRoles.length !== (input as Record<string, any>).roles.length) {
72
- const missingRoles = _.difference((input as Record<string, any>).roles, (currentUser as any).roles);
73
- throw new UnauthorizedException('Current user not allowed setting roles: ' + missingRoles);
74
- }
75
- (input as Record<string, any>).roles = allowedRoles;
76
- }
77
- }
78
-
79
- // Hash password
80
- if ((input as Record<string, any>).password) {
81
- (input as Record<string, any>).password = await bcrypt.hash((input as any).password, 10);
82
- }
83
-
84
- // Set creator
85
- if (config.create && currentUser) {
86
- (input as Record<string, any>).createdBy = currentUser.id;
87
- }
88
-
89
- // Set updater
90
- if (currentUser) {
91
- (input as Record<string, any>).updatedBy = currentUser.id;
92
- }
93
-
94
- // Return prepared input
95
- return input;
25
+ return prepareInput(input, currentUser, options);
96
26
  }
97
27
 
98
28
  /**
@@ -108,61 +38,163 @@ export class ServiceHelper {
108
38
  targetModel?: new (...args: any[]) => T;
109
39
  } = {}
110
40
  ): Promise<T | T[] | any> {
111
- // Configuration
112
- const config = {
113
- clone: false,
114
- getNewArray: false,
115
- removeUndefined: false,
116
- targetModel: undefined,
117
- ...options,
118
- };
119
-
120
- // Check output
121
- if (typeof output !== 'object') {
122
- return output;
123
- }
41
+ return prepareOutput(output, options);
42
+ }
43
+ }
124
44
 
125
- // Process array
126
- if (Array.isArray(output)) {
127
- const processedArray = output.map(async (item) => await ServiceHelper.prepareOutput(item, options)) as any;
128
- return config.getNewArray ? processedArray : output;
45
+ /**
46
+ * Prepare input before save
47
+ */
48
+ export async function prepareInput<T = any>(
49
+ input: T,
50
+ currentUser: { [key: string]: any; id: string },
51
+ options: {
52
+ [key: string]: any;
53
+ create?: boolean;
54
+ clone?: boolean;
55
+ getNewArray?: boolean;
56
+ removeUndefined?: boolean;
57
+ } = {}
58
+ ): Promise<T> {
59
+ // Configuration
60
+ const config = {
61
+ checkRoles: false,
62
+ clone: false,
63
+ create: false,
64
+ getNewArray: false,
65
+ removeUndefined: false,
66
+ ...options,
67
+ };
68
+
69
+ // Check input
70
+ if (typeof input !== 'object') {
71
+ return input;
72
+ }
73
+
74
+ // Process array
75
+ if (Array.isArray(input)) {
76
+ const processedArray = input.map(async (item) => await prepareInput(item, currentUser, options)) as any;
77
+ return config.getNewArray ? processedArray : input;
78
+ }
79
+
80
+ // Clone input
81
+ if (config.clone) {
82
+ if ((input as Record<string, any>).mapDeep && typeof (input as any).mapDeep === 'function') {
83
+ input = await Object.getPrototypeOf(input).mapDeep(input);
84
+ } else {
85
+ input = _.cloneDeep(input);
129
86
  }
87
+ }
130
88
 
131
- // Clone output
132
- if (config.clone) {
133
- if (output.mapDeep && typeof output.mapDeep === 'function') {
134
- output = await Object.getPrototypeOf(output).mapDeep(output);
135
- } else {
136
- output = _.cloneDeep(output);
89
+ // Remove undefined properties to avoid unwanted overwrites
90
+ if (config.removeUndefined) {
91
+ Object.keys(input).forEach((key) => input[key] === undefined && delete input[key]);
92
+ }
93
+
94
+ // Process roles
95
+ if (
96
+ config.checkRoles &&
97
+ (input as Record<string, any>).roles &&
98
+ (!currentUser?.hasRole || !currentUser.hasRole(RoleEnum.ADMIN))
99
+ ) {
100
+ if (!(currentUser as any)?.roles) {
101
+ throw new UnauthorizedException('Missing roles of current user');
102
+ } else {
103
+ const allowedRoles = _.intersection((input as Record<string, any>).roles, (currentUser as any).roles);
104
+ if (allowedRoles.length !== (input as Record<string, any>).roles.length) {
105
+ const missingRoles = _.difference((input as Record<string, any>).roles, (currentUser as any).roles);
106
+ throw new UnauthorizedException('Current user not allowed setting roles: ' + missingRoles);
137
107
  }
108
+ (input as Record<string, any>).roles = allowedRoles;
138
109
  }
110
+ }
139
111
 
140
- // Map output if target model exist
141
- if (config.targetModel) {
142
- output = await (config.targetModel as any).map(output);
143
- }
112
+ // Hash password
113
+ if ((input as Record<string, any>).password) {
114
+ (input as Record<string, any>).password = await bcrypt.hash((input as any).password, 10);
115
+ }
144
116
 
145
- // Remove password if exists
146
- if (output.password) {
147
- output.password = undefined;
148
- }
117
+ // Set creator
118
+ if (config.create && currentUser) {
119
+ (input as Record<string, any>).createdBy = currentUser.id;
120
+ }
149
121
 
150
- // Remove verification token if exists
151
- if (output.verificationToken) {
152
- output.verificationToken = undefined;
153
- }
122
+ // Set updater
123
+ if (currentUser) {
124
+ (input as Record<string, any>).updatedBy = currentUser.id;
125
+ }
154
126
 
155
- // Remove password reset token if exists
156
- if (output.passwordResetToken) {
157
- output.passwordResetToken = undefined;
158
- }
127
+ // Return prepared input
128
+ return input;
129
+ }
159
130
 
160
- // Remove undefined properties to avoid unwanted overwrites
161
- if (config.removeUndefined) {
162
- Object.keys(output).forEach((key) => output[key] === undefined && delete output[key]);
131
+ /**
132
+ * Prepare output before return
133
+ */
134
+ export async function prepareOutput<T = { [key: string]: any; map: (...args: any[]) => any }>(
135
+ output: any,
136
+ options: {
137
+ [key: string]: any;
138
+ clone?: boolean;
139
+ getNewArray?: boolean;
140
+ removeUndefined?: boolean;
141
+ targetModel?: new (...args: any[]) => T;
142
+ } = {}
143
+ ): Promise<T | T[] | any> {
144
+ // Configuration
145
+ const config = {
146
+ clone: false,
147
+ getNewArray: false,
148
+ removeUndefined: false,
149
+ targetModel: undefined,
150
+ ...options,
151
+ };
152
+
153
+ // Check output
154
+ if (typeof output !== 'object') {
155
+ return output;
156
+ }
157
+
158
+ // Process array
159
+ if (Array.isArray(output)) {
160
+ const processedArray = output.map(async (item) => await prepareOutput(item, options)) as any;
161
+ return config.getNewArray ? processedArray : output;
162
+ }
163
+
164
+ // Clone output
165
+ if (config.clone) {
166
+ if (output.mapDeep && typeof output.mapDeep === 'function') {
167
+ output = await Object.getPrototypeOf(output).mapDeep(output);
168
+ } else {
169
+ output = _.cloneDeep(output);
163
170
  }
171
+ }
164
172
 
165
- // Return prepared output
166
- return output;
173
+ // Map output if target model exist
174
+ if (config.targetModel) {
175
+ output = await (config.targetModel as any).map(output);
176
+ }
177
+
178
+ // Remove password if exists
179
+ if (output.password) {
180
+ output.password = undefined;
167
181
  }
182
+
183
+ // Remove verification token if exists
184
+ if (output.verificationToken) {
185
+ output.verificationToken = undefined;
186
+ }
187
+
188
+ // Remove password reset token if exists
189
+ if (output.passwordResetToken) {
190
+ output.passwordResetToken = undefined;
191
+ }
192
+
193
+ // Remove undefined properties to avoid unwanted overwrites
194
+ if (config.removeUndefined) {
195
+ Object.keys(output).forEach((key) => output[key] === undefined && delete output[key]);
196
+ }
197
+
198
+ // Return prepared output
199
+ return output;
168
200
  }
@@ -1,6 +1,6 @@
1
1
  import { Field, InputType } from '@nestjs/graphql';
2
2
  import { LogicalOperatorEnum } from '../enums/logical-operator.enum';
3
- import { ModelHelper } from '../helpers/model.helper';
3
+ import { maps } from '../helpers/model.helper';
4
4
  import { CoreInput } from './core-input.input';
5
5
  import { FilterInput } from './filter.input';
6
6
 
@@ -40,7 +40,7 @@ export class CombinedFilterInput extends CoreInput {
40
40
  } = {}
41
41
  ): this {
42
42
  super.map(data, options);
43
- this.filters = ModelHelper.maps(data.filters, FilterInput, options.cloneDeep);
43
+ this.filters = maps(data.filters, FilterInput, options.cloneDeep);
44
44
  Object.keys(this).forEach((key) => this[key] === undefined && delete this[key]);
45
45
  return this;
46
46
  }
@@ -1,4 +1,4 @@
1
- import { ModelHelper } from '../helpers/model.helper';
1
+ import { map } from '../helpers/model.helper';
2
2
  import { CoreModel } from '../models/core-model.model';
3
3
 
4
4
  /**
@@ -29,7 +29,7 @@ export abstract class CoreInput extends CoreModel {
29
29
  mapId: false,
30
30
  ...options,
31
31
  };
32
- const coreInput = ModelHelper.map(data, this, config);
32
+ const coreInput = map(data, this, config);
33
33
  Object.keys(coreInput).forEach((key) => coreInput[key] === undefined && delete coreInput[key]);
34
34
  return coreInput;
35
35
  }
@@ -2,7 +2,7 @@ import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nes
2
2
  import { Observable } from 'rxjs';
3
3
  import { map } from 'rxjs/operators';
4
4
  import { checkRestricted } from '../decorators/restricted.decorator';
5
- import { Context } from '../helpers/context.helper';
5
+ import { getContextData } from '../helpers/context.helper';
6
6
 
7
7
  /**
8
8
  * Interceptor to check the response data for current user
@@ -14,7 +14,7 @@ export class CheckResponseInterceptor implements NestInterceptor {
14
14
  */
15
15
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
16
16
  // Get current user
17
- const { currentUser }: any = Context.getData(context);
17
+ const { currentUser }: any = getContextData(context);
18
18
 
19
19
  // Response interception
20
20
  return next.handle().pipe(
@@ -0,0 +1,9 @@
1
+ import { GraphQLResolveInfo } from 'graphql';
2
+
3
+ /**
4
+ * Resolve selector to get requested fields from GraphQL resolve info
5
+ */
6
+ export interface ResolveSelector {
7
+ info: GraphQLResolveInfo;
8
+ select?: string;
9
+ }
@@ -0,0 +1,71 @@
1
+ import { Model, Types } from 'mongoose';
2
+ import { FieldSelection } from '../types/field-selection.type';
3
+ import { IdsType } from '../types/ids.type';
4
+
5
+ /**
6
+ * General service options
7
+ */
8
+ export interface ServiceOptions {
9
+ // All fields are allowed to be compatible as far as possible
10
+ [key: string]: any;
11
+
12
+ // Check rights for input data (see check function in InputHelper)
13
+ // If falsy: input data will not be checked
14
+ // If truly (default): input data will be checked
15
+ checkRights?: boolean;
16
+
17
+ // Current user to set ownership, check roles and other things
18
+ currentUser?: {
19
+ [key: string]: any;
20
+ id: string;
21
+ roles?: string[];
22
+ };
23
+
24
+ // Field selection for results
25
+ fieldSelection?: FieldSelection;
26
+
27
+ // Overwrites type of input (array items)
28
+ inputType?: new (...params: any[]) => any;
29
+
30
+ // Owner IDs
31
+ ownerIds?: IdsType;
32
+
33
+ // Process field selection
34
+ // If {} or not set, then the field selection runs with defaults
35
+ // If falsy, then the field selection will not be automatically executed
36
+ processFieldSelection?: {
37
+ model?: new (...args: any[]) => any;
38
+ dbModel?: Model<any>;
39
+ };
40
+
41
+ // Prepare input configuration:
42
+ // If {} or not set, then the prepareInput function will run with defaults
43
+ // If falsy, then the prepareInput function is not executed
44
+ prepareInput?: {
45
+ [key: string]: any;
46
+ create?: boolean;
47
+ clone?: boolean;
48
+ getNewArray?: boolean;
49
+ removeUndefined?: boolean;
50
+ };
51
+
52
+ // Prepare output configuration:
53
+ // If {} or not set, then the prepareInput function will run with defaults
54
+ // If falsy, then the prepareInput function is not executed
55
+ prepareOutput?: {
56
+ [key: string]: any;
57
+ clone?: boolean;
58
+ getNewArray?: boolean;
59
+ removeUndefined?: boolean;
60
+ targetModel?: new (...args: any[]) => any;
61
+ };
62
+
63
+ // Whether to publish action via GraphQL subscription
64
+ pubSub?: boolean;
65
+
66
+ // Overwrites type of result (array items)
67
+ resultType?: new (...params: any[]) => any;
68
+
69
+ // Roles (as string) to check
70
+ roles?: string | string[];
71
+ }
@@ -1,4 +1,4 @@
1
- import { ModelHelper } from '../helpers/model.helper';
1
+ import { map } from '../helpers/model.helper';
2
2
 
3
3
  /**
4
4
  * Core Model
@@ -26,6 +26,7 @@ export abstract class CoreModel {
26
26
  this: new (...args: any[]) => T,
27
27
  data: Partial<T> | Record<string, any>,
28
28
  options: {
29
+ [key: string]: any;
29
30
  cloneDeep?: boolean;
30
31
  funcAllowed?: boolean;
31
32
  init?: any;
@@ -55,6 +56,7 @@ export abstract class CoreModel {
55
56
  this: new (...args: any[]) => T,
56
57
  data: Partial<T> | Record<string, any>,
57
58
  options: {
59
+ [key: string]: any;
58
60
  cloneDeep?: boolean;
59
61
  funcAllowed?: boolean;
60
62
  init?: any;
@@ -76,7 +78,7 @@ export abstract class CoreModel {
76
78
  * Initialize instance with default values instead of undefined
77
79
  * Should be overwritten in child class to organize the defaults
78
80
  */
79
- public init<T extends CoreModel>(...args: any[]): this {
81
+ public init(...args: any[]): this {
80
82
  return this;
81
83
  }
82
84
 
@@ -86,6 +88,7 @@ export abstract class CoreModel {
86
88
  public map(
87
89
  data: Partial<this> | Record<string, any>,
88
90
  options: {
91
+ [key: string]: any;
89
92
  cloneDeep?: boolean;
90
93
  funcAllowed?: boolean;
91
94
  init?: any;
@@ -99,7 +102,7 @@ export abstract class CoreModel {
99
102
  mapId: false,
100
103
  ...options,
101
104
  };
102
- return config.init ? ModelHelper.map(data, this, config).init(config.init) : ModelHelper.map(data, this, config);
105
+ return config.init ? map(data, this, config).init(config.init) : map(data, this, config);
103
106
  }
104
107
 
105
108
  /**
@@ -113,6 +116,7 @@ export abstract class CoreModel {
113
116
  public mapDeep(
114
117
  data: Partial<this> | Record<string, any>,
115
118
  options: {
119
+ [key: string]: any;
116
120
  cloneDeep?: boolean;
117
121
  funcAllowed?: boolean;
118
122
  init?: any;
@@ -1,7 +1,7 @@
1
1
  import { ArgumentMetadata, Inject, Injectable, PipeTransform } from '@nestjs/common';
2
2
  import { CONTEXT } from '@nestjs/graphql';
3
- import { Context } from '../helpers/context.helper';
4
- import { InputHelper } from '../helpers/input.helper';
3
+ import { getContextData } from '../helpers/context.helper';
4
+ import { check } from '../helpers/input.helper';
5
5
 
6
6
  /**
7
7
  * The CheckInputPipe checks the permissibility of individual properties of inputs for the resolvers
@@ -25,9 +25,9 @@ export class CheckInputPipe implements PipeTransform {
25
25
  const metatype = metadata?.metatype;
26
26
 
27
27
  // Get user
28
- const { user }: any = Context.getData(this.context);
28
+ const { user }: any = getContextData(this.context);
29
29
 
30
30
  // Check and return
31
- return InputHelper.check(value, user, metatype);
31
+ return check(value, user, { metatype });
32
32
  }
33
33
  }