@futdevpro/nts-dynamo 1.9.15 → 1.9.16

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 (117) hide show
  1. package/.copilot/patterns.json +7 -7
  2. package/.github/workflows/main.yml +206 -0
  3. package/HOWTO.md +15 -15
  4. package/README.md +140 -140
  5. package/build/_models/control-models/endpoint-params.control-model.d.ts.map +1 -1
  6. package/build/_models/control-models/endpoint-params.control-model.js +2 -0
  7. package/build/_models/control-models/endpoint-params.control-model.js.map +1 -1
  8. package/build/_models/control-models/socket-event.control-model.js +1 -1
  9. package/build/_services/core/global.service.d.ts.map +1 -1
  10. package/build/_services/core/global.service.js +1 -0
  11. package/build/_services/core/global.service.js.map +1 -1
  12. package/build/_services/route/routing-module.service.d.ts +1 -0
  13. package/build/_services/route/routing-module.service.d.ts.map +1 -1
  14. package/build/_services/route/routing-module.service.js +17 -23
  15. package/build/_services/route/routing-module.service.js.map +1 -1
  16. package/build/_services/server/app.server.d.ts.map +1 -1
  17. package/build/_services/server/app.server.js +4 -1
  18. package/build/_services/server/app.server.js.map +1 -1
  19. package/build/_services/socket/socket-client.service.d.ts.map +1 -1
  20. package/build/_services/socket/socket-client.service.js +1 -0
  21. package/build/_services/socket/socket-client.service.js.map +1 -1
  22. package/nodemon.json +17 -15
  23. package/package.json +5 -5
  24. package/src/_constants/global-settings.const.ts +27 -27
  25. package/src/_constants/index.ts +2 -2
  26. package/src/_constants/mocks/app-extended-server.mock.ts +198 -198
  27. package/src/_constants/mocks/app-params.mock.ts +9 -9
  28. package/src/_constants/mocks/app-server.mock.ts +185 -185
  29. package/src/_constants/mocks/auth-service.mock.ts +28 -28
  30. package/src/_constants/mocks/controller.mock.ts +16 -16
  31. package/src/_constants/mocks/data-model.mock.ts +83 -83
  32. package/src/_constants/mocks/email-service-collection.mock.ts +13 -13
  33. package/src/_constants/mocks/email-service.mock.ts +19 -19
  34. package/src/_constants/mocks/email-template.mock.html +14 -14
  35. package/src/_constants/mocks/endpoint.mock.ts +90 -90
  36. package/src/_constants/mocks/socket-client.mock.ts +43 -43
  37. package/src/_constants/mocks/socket-server.mock.ts +43 -43
  38. package/src/_enums/data-model-type.enum.ts +14 -14
  39. package/src/_enums/data-service-function.enum.ts +15 -15
  40. package/src/_enums/http/http-call-type.enum.ts +12 -12
  41. package/src/_enums/http/http-response-type.enum.ts +7 -7
  42. package/src/_enums/http/socket-event-type.enum.ts +18 -18
  43. package/src/_enums/index.ts +13 -13
  44. package/src/_enums/predefined-data-types.enum.ts +27 -27
  45. package/src/_enums/route-security.enum.ts +12 -12
  46. package/src/_enums/socket-security.enum.ts +11 -11
  47. package/src/_models/control-models/api-call-params.control-model.ts +126 -126
  48. package/src/_models/control-models/app-ext-system-controls.control-model.ts +9 -9
  49. package/src/_models/control-models/app-params.control-model.ts +45 -45
  50. package/src/_models/control-models/app-system-controls.control-model.ts +9 -9
  51. package/src/_models/control-models/endpoint-params.control-model.ts +309 -307
  52. package/src/_models/control-models/http-settings.control-model.ts +29 -29
  53. package/src/_models/control-models/index.ts +13 -13
  54. package/src/_models/control-models/socket-client-service-params.control-model.ts +28 -28
  55. package/src/_models/control-models/socket-event.control-model.ts +150 -150
  56. package/src/_models/control-models/socket-presence.control-model.ts +207 -207
  57. package/src/_models/control-models/socket-server-service-params.control-model.ts +20 -20
  58. package/src/_models/control-models/system-control.control-model.ts +12 -12
  59. package/src/_models/index.ts +9 -9
  60. package/src/_models/interfaces/certification-settings.interface.ts +7 -7
  61. package/src/_models/interfaces/global-service-settings.interface.ts +45 -45
  62. package/src/_models/interfaces/global-settings.interface.ts +83 -83
  63. package/src/_models/interfaces/index.ts +7 -7
  64. package/src/_models/interfaces/routing-module-settings.interface.ts +20 -20
  65. package/src/_models/types/db-filter.type.ts +108 -108
  66. package/src/_models/types/db-update.type.ts +100 -100
  67. package/src/_models/types/index.ts +5 -5
  68. package/src/_modules/api-service.index.ts +12 -12
  69. package/src/_modules/app-extended.index.ts +28 -28
  70. package/src/_modules/app.index.ts +24 -24
  71. package/src/_modules/auth.index.ts +7 -7
  72. package/src/_modules/constants.index.ts +2 -2
  73. package/src/_modules/controller.index.ts +10 -10
  74. package/src/_modules/custom-data/custom-data.controller.ts +69 -69
  75. package/src/_modules/custom-data/custom-data.data-service.ts +20 -20
  76. package/src/_modules/custom-data/get-custom-data-routing-module.util.ts +23 -23
  77. package/src/_modules/custom-data/index.ts +6 -6
  78. package/src/_modules/custom-data-module.index.ts +2 -2
  79. package/src/_modules/data-service.index.ts +9 -9
  80. package/src/_modules/email.index.ts +8 -8
  81. package/src/_modules/enums.index.ts +2 -2
  82. package/src/_modules/extended.index.ts +8 -8
  83. package/src/_modules/models.index.ts +2 -2
  84. package/src/_modules/services.index.ts +2 -2
  85. package/src/_modules/test/get-test-routing-module.util.ts +23 -23
  86. package/src/_modules/test/index.ts +5 -5
  87. package/src/_modules/test/test.controller.ts +115 -115
  88. package/src/_modules/test-module.index.ts +2 -2
  89. package/src/_modules/usage/get-usage-routing-module.util.ts +22 -22
  90. package/src/_modules/usage/index.ts +7 -7
  91. package/src/_modules/usage/usage.controller.ts +120 -120
  92. package/src/_modules/usage/usage.data-service.ts +172 -172
  93. package/src/_modules/usage-module.index.ts +2 -2
  94. package/src/_services/base/data.service.ts +921 -921
  95. package/src/_services/base/db.service.spec.ts +32 -32
  96. package/src/_services/base/db.service.ts +1063 -1063
  97. package/src/_services/base/singleton.service.ts +21 -21
  98. package/src/_services/core/api.service.ts +453 -453
  99. package/src/_services/core/auth.service.ts +172 -172
  100. package/src/_services/core/email.service.ts +678 -678
  101. package/src/_services/core/global.service.ts +270 -269
  102. package/src/_services/core/service-collection.service.ts +5 -5
  103. package/src/_services/index.ts +23 -23
  104. package/src/_services/route/controller.service.ts +129 -129
  105. package/src/_services/route/routing-module.service.ts +293 -273
  106. package/src/_services/server/app-extended.server.spec.ts +76 -76
  107. package/src/_services/server/app-extended.server.ts +520 -520
  108. package/src/_services/server/app.server.spec.ts +67 -67
  109. package/src/_services/server/app.server.ts +1181 -1179
  110. package/src/_services/shared.service.spec.ts +19 -19
  111. package/src/_services/shared.static-service.ts +73 -73
  112. package/src/_services/socket/socket-client.service.ts +236 -235
  113. package/src/_services/socket/socket-server.service.spec.ts +11 -11
  114. package/src/_services/socket/socket-server.service.ts +761 -761
  115. package/src/index.ts +18 -18
  116. package/tsconfig.json +41 -41
  117. package/build/tsconfig.tsbuildinfo +0 -1
@@ -1,921 +1,921 @@
1
-
2
- import {
3
- DynamoFM_Metadata, DynamoFM_DataModel_Params, DynamoFM_DataProperty_Params, DynamoFM_Error,
4
- DynamoFM_Log, DynamoFM_AnyError, DynamoFM_Error_Settings, DynamoFM_ErrorLevel
5
- } from '@futdevpro/fsm-dynamo';
6
- import { DynamoNTS_DBFilter } from '../../_models/types/db-filter.type';
7
- import { DynamoNTS_DBUpdate } from '../../_models/types/db-update.type';
8
-
9
- import { DynamoNTS_DBService } from './db.service';
10
- import { DynamoNTS_GlobalService } from '../core/global.service';
11
-
12
- /**
13
- * Basic Data Service that is connected to the relevant DBServices
14
- *
15
- * @example
16
- * export class UserMatchStatisticsService extends DynamoNTS_DataService<UserMatchStatistics> {
17
- * constructor(
18
- * set?: {
19
- * data?: UserMatchStatistics,
20
- * issuer?: string,
21
- * }
22
- * ) {
23
- * super(
24
- * new UserMatchStatistics(set?.data),
25
- * userMatchStatisticsModelParams
26
- * );
27
- * this.issuer = set?.issuer;
28
- * }
29
- * }
30
- */
31
- export class DynamoNTS_DataService<T extends DynamoFM_Metadata> {
32
-
33
- serviceName: string;
34
-
35
- dataDBService: DynamoNTS_DBService<T>;
36
- data: T;
37
- dataList: T[] = [];
38
- issuer: string;
39
-
40
- depKey?: string;
41
- depDBServiceKey?: string;
42
- depKeyIsUnique?: boolean;
43
- depKeyIsRequired?: boolean;
44
- private depDataDBService: DynamoNTS_DBService<any>;
45
-
46
- dataParams: DynamoFM_DataModel_Params;
47
-
48
- defaultErrorUserMsg: string =
49
- `We encountered an unhandled Data Service Error, ` +
50
- `\nplease contact the responsible development team.`;
51
- defaultValidationErrorUserMsg: string =
52
- `We encountered an unhandled Validation Error, ` +
53
- `\nplease contact the responsible development team.`;
54
-
55
- constructor(
56
- /**
57
- * Initial data, this will be used by functions on default
58
- */
59
- data: T,
60
- /**
61
- * DB data prams will be used to connect to usable dbService on GlobalService
62
- */
63
- dataParams: DynamoFM_DataModel_Params,
64
- /**
65
- * Initial set for issuer to be able to follow the issuer's activity
66
- */
67
- issuer: string
68
- ) {
69
- try {
70
- this.serviceName = this.constructor?.name;
71
- this.dataDBService = DynamoNTS_GlobalService.getDBService<T>(dataParams);
72
- this.data = data;
73
- this.dataParams = dataParams;
74
- this.lookForDependencyDataSettings();
75
- this.issuer = issuer;
76
- } catch (error) {
77
- throw new DynamoFM_Error({
78
- ...this._getDefaultErrorSettings('constructor', error),
79
- message: `The dataService construction failed for ${dataParams?.dataName}. ` +
80
- `${this.serviceName} (${this.constructor.name})` +
81
- `\nMaybe you forgot to add the dbService to the GlobalService?\n\n`,
82
- level: DynamoFM_ErrorLevel.critical,
83
-
84
- errorCode: 'NTS-DS0-C00',
85
- });
86
- /* DynamoFM_Log.error(
87
- `\nDynamoNTS_DataService ERROR: ` +
88
- `\nThe dataService construction failed for ` +
89
- `${dataParams?.dataName}. ${this.serviceName} (${this.constructor.name})` +
90
- `\nMaybe you forgot to add the dbService to the GlobalService?` +
91
- `\n\n`,
92
- new Error()
93
- ); */
94
- }
95
- }
96
-
97
- /**
98
- * returns all data from database to service dataList
99
- */
100
- async getAll(dontSetToService?: boolean): Promise<T[]> {
101
- try {
102
- const dataListExists: T[] = await this.dataDBService.getAll().catch((error): T[] => {
103
- if (error?.errorCode === 'NTS-DBS-GA1') {
104
- DynamoFM_Log.warn(`getAll ${this.dataParams.dataName} didn't found any.`);
105
-
106
- return [];
107
- } else {
108
- throw error;
109
- }
110
- });
111
-
112
- if (!dontSetToService) {
113
- this.dataList = dataListExists;
114
- }
115
-
116
- return dataListExists;
117
- } catch (error) {
118
- throw new DynamoFM_Error({
119
- ...this._getDefaultErrorSettings('getAll', error),
120
-
121
- errorCode: 'NTS-DS0-GA0',
122
- });
123
- }
124
- }
125
-
126
- /**
127
- * @description
128
- * returns data from database by id
129
- * also if dontSetToService is false or not setted,
130
- * the data will be saved to the service, even if its not found
131
- *
132
- * @remarks
133
- * If you need to get-save a data, if possible,
134
- * use db-service update instead.
135
- *
136
- * @param {string} id
137
- * (using id from service.data, if not provided)
138
- * @param dontSetToService
139
- *
140
- * @return {T} data: T
141
- */
142
- async getDataById(id?: string, dontSetToService?: boolean): Promise<T> {
143
- try {
144
- if (!id && !this.data._id) {
145
- throw new DynamoFM_Error({
146
- ...this._getDefaultErrorSettings(
147
- 'getDataById',
148
- new Error(
149
- `getDataById failed, ID is missing! ` +
150
- `(maybe you wanted to use getDataByDependencyId() instead...) ` +
151
- `(${this.dataParams.dataName})`
152
- )
153
- ),
154
-
155
- errorCode: 'NTS-DS0-GI1',
156
- });
157
- }
158
-
159
- const dataExists: T = await this.dataDBService.getDataById(id ?? this.data._id);
160
-
161
- if (!dontSetToService) {
162
- this.data = dataExists;
163
- }
164
-
165
- return dataExists;
166
- } catch (error) {
167
- if (error?.errorCode == 'NTS-DS0-GI1') {
168
- throw error;
169
- } else {
170
- throw new DynamoFM_Error({
171
- ...this._getDefaultErrorSettings('getDataById', error),
172
- errorCode: 'NTS-DS0-GI0',
173
- });
174
- }
175
- }
176
- }
177
-
178
- async getDataByIds(ids: string[], dontSetToService?: boolean): Promise<T[]> {
179
- try {
180
- if (!ids) {
181
- throw new DynamoFM_Error({
182
- ...this._getDefaultErrorSettings(
183
- 'getDataByIds',
184
- new Error(`getDataByIds failed, ids is missing! (${this.dataParams.dataName})`)
185
- ),
186
-
187
- errorCode: 'NTS-DS0-GIS1',
188
- });
189
- }
190
-
191
- if (ids.length === 0) {
192
- return [];
193
- }
194
-
195
- const datas: T[] = await this.dataDBService.find({ _id: { $in: ids } });
196
-
197
- if (!dontSetToService) {
198
- this.dataList = datas;
199
- }
200
-
201
- return datas;
202
- } catch (error) {
203
- throw new DynamoFM_Error({
204
- ...this._getDefaultErrorSettings('getDataByIds', error),
205
-
206
- errorCode: 'NTS-DS0-GIS0',
207
- });
208
- }
209
- }
210
-
211
- /**
212
- * returns data from database by dependencyId to the service
213
- * (using id from service.data, if not provided)
214
- * @param dependencyId
215
- */
216
- async getDataByDependencyId(dependencyId?: string, dontSetToService?: boolean): Promise<T> {
217
- try {
218
- if (!this.depKey) {
219
- throw new DynamoFM_Error({
220
- ...this._getDefaultErrorSettings(
221
- 'getDataByDependencyId',
222
- new Error(
223
- `getDataByDependencyId failed, dependencyKey is missing from service! ` +
224
- `(${this.dataParams.dataName})`
225
- )
226
- ),
227
-
228
- errorCode: 'NTS-DS0-GD1',
229
- });
230
- }
231
-
232
- if (!dependencyId && !this.data[this.depKey]) {
233
- throw new DynamoFM_Error({
234
- ...this._getDefaultErrorSettings(
235
- 'getDataByDependencyId',
236
- new Error(
237
- `getDataByDependencyId failed, ${this.depKey} is missing! ` +
238
- `(${this.dataParams.dataName})`
239
- )
240
- ),
241
-
242
- errorCode: 'NTS-DS0-GD2',
243
- });
244
- }
245
-
246
- const dataExists: T = await this.dataDBService.getDataByDependencyId(
247
- dependencyId ?? this.data[this.depKey]
248
- ).catch((error): null => {
249
- if (error?.errorCode === 'NTS-DBS-GD2') {
250
- DynamoFM_Log.warn(
251
- `getDataByDependencyId failed; ${this.dataParams.dataName} ` +
252
- `(${this.depKey}: ${dependencyId ?? this.data[this.depKey]}) didn't found any.`
253
- );
254
-
255
- return null;
256
- } else {
257
- throw error;
258
- }
259
- });
260
-
261
- if (!dontSetToService) {
262
- this.data = dataExists;
263
- }
264
-
265
- return dataExists;
266
- } catch (error) {
267
- if ([ 'NTS-DS0-GD1', 'NTS-DS0-GD2' ].includes(error?.errorCode)) {
268
- throw error;
269
- } else {
270
- throw new DynamoFM_Error({
271
- ...this._getDefaultErrorSettings('getDataByDependencyId', error),
272
-
273
- errorCode: 'NTS-DS0-GD0',
274
- });
275
- }
276
- }
277
- }
278
-
279
- async getDatasByDependencyIds(dependencyIds: string[], dontSetToService?: boolean): Promise<T[]> {
280
- try {
281
- if (!this.depKey) {
282
- throw new DynamoFM_Error({
283
- ...this._getDefaultErrorSettings(
284
- 'getDatasByDependencyIds',
285
- new Error(
286
- `getDatasByDependencyIds failed, dependencyKey is missing from service! ` +
287
- `(${this.dataParams.dataName})`
288
- )
289
- ),
290
-
291
- errorCode: 'NTS-DS0-GDS1',
292
- });
293
- }
294
-
295
- if (!dependencyIds) {
296
- throw new DynamoFM_Error({
297
- ...this._getDefaultErrorSettings(
298
- 'getDatasByDependencyIds',
299
- new Error(
300
- `getDatasByDependencyIds failed, dependencyIds is missing! ` +
301
- `(${this.dataParams.dataName})`
302
- )
303
- ),
304
-
305
- errorCode: 'NTS-DS0-GDS2',
306
- });
307
- }
308
-
309
- if (dependencyIds.length === 0) {
310
- return [];
311
- }
312
-
313
- const datas: T[] = await this.dataDBService.getDatasByDependencyIds(dependencyIds);
314
-
315
- if (!dontSetToService) {
316
- this.dataList = datas;
317
- }
318
-
319
- return datas;
320
- } catch (error) {
321
- if ([ 'NTS-DS0-GDS1', 'NTS-DS0-GDS2' ].includes(error?.errorCode)) {
322
- throw error;
323
- } else {
324
- throw new DynamoFM_Error({
325
- ...this._getDefaultErrorSettings('getDatasByDependencyIds', error),
326
-
327
- errorCode: 'NTS-DS0-GDS0',
328
- });
329
- }
330
- }
331
- }
332
-
333
- /**
334
- * returns dataList from database by dependencyId to the service
335
- * @param dependencyId
336
- */
337
- async getDataListByDependencyId(dependencyId?: string, dontSetToService?: boolean): Promise<T[]> {
338
- try {
339
- if (!this.depKey) {
340
- throw new DynamoFM_Error({
341
- ...this._getDefaultErrorSettings(
342
- 'getDataListByDependencyId',
343
- new Error(
344
- `getDataListByDependencyId failed, dependencyKey is missing from service! ` +
345
- `(${this.dataParams.dataName})`
346
- )
347
- ),
348
-
349
- errorCode: 'NTS-DS0-GLD1',
350
- });
351
- }
352
-
353
- if (!dependencyId && !this.data[this.depKey]) {
354
- throw new DynamoFM_Error({
355
- ...this._getDefaultErrorSettings(
356
- 'getDataListByDependencyId',
357
- new Error(
358
- `getDataListByDependencyId failed, ${this.depKey} is missing! ` +
359
- `(${this.dataParams.dataName})`
360
- )
361
- ),
362
-
363
- errorCode: 'NTS-DS0-GLD2',
364
- });
365
- }
366
-
367
- const dataListExists: T[] = await this.dataDBService.getDataListByDependencyId(
368
- dependencyId ?? this.data[this.depKey]
369
- ).catch((error): T[] => {
370
- if (error?.errorCode === 'NTS-DBS-GLD2') {
371
- DynamoFM_Log.warn(
372
- `getDataListByDependencyId ${this.dataParams.dataName} ` +
373
- `(${this.depKey}: ${dependencyId ?? this.data[this.depKey]}) didn't found any.`
374
- );
375
-
376
- return [];
377
- } else {
378
- throw error;
379
- }
380
- });
381
-
382
- if (!dontSetToService) {
383
- this.dataList = dataListExists;
384
- }
385
-
386
- return dataListExists;
387
- } catch (error) {
388
- if ([ 'NTS-DS0-GLD1', 'NTS-DS0-GLD2' ].includes(error?.errorCode)) {
389
- throw error;
390
- } else {
391
- throw new DynamoFM_Error({
392
- ...this._getDefaultErrorSettings('getDataListByDependencyId', error),
393
-
394
- errorCode: 'NTS-DS0-GLD0',
395
-
396
- });
397
- }
398
- }
399
- }
400
-
401
- /**
402
- *
403
- * // findOne desc:
404
- *
405
- * Find the data first by any of its parameters,
406
- * also if dontSetToService is false or not setted,
407
- * the data will be saved to the service, even if non found
408
- *
409
- * @param filter if you can, use unique parameters for find!
410
- *
411
- * @example
412
- * // by email:
413
- * { email: email }
414
- * //
415
- * @example
416
- * // or by id that is in list:
417
- * { userIds: { $in: this.userId } }
418
- * //
419
- * @example
420
- * // or by number or Date that is Greater Than AND Less Than:
421
- * { points: { $gt: 2, $lt: 14 } }
422
- * // further tools (syntax matches with $gt):
423
- * $eq: // Matches values that are EQual to a specified value.
424
- * $gte: // Matches values that are Greater Than OR Equal to a specified value.
425
- * $lte: // Matches values that are Less Than or Equal to a specified value.
426
- * $ne: // Matches all values that are Not Equal to a specified value.
427
- * $nin: // Matches None of the values specified IN an array.
428
- * //
429
- * @returns {T} data: T
430
- */
431
- async findData(filterBy: DynamoNTS_DBFilter<T>, dontSetToService?: boolean): Promise<T> {
432
- try {
433
- const dataExists: T = await this.dataDBService.findOne(filterBy).catch((error): null => {
434
- if (error?.errorCode === 'NTS-DBS-FO1') {
435
- DynamoFM_Log.warn(`findData ${this.dataParams.dataName} didn't found any.`);
436
-
437
- return null;
438
- } else {
439
- throw error;
440
- }
441
- });
442
-
443
- if (!dontSetToService) {
444
- this.data = dataExists;
445
- }
446
-
447
- return dataExists;
448
- } catch (error) {
449
- throw new DynamoFM_Error({
450
- ...this._getDefaultErrorSettings('findData', error),
451
-
452
- errorCode: 'NTS-DS0-FD0',
453
- });
454
- }
455
- }
456
-
457
- /**
458
- *
459
- * // find desc:
460
- *
461
- * Find the data first by any of its parameters,
462
- * also if dontSetToService is false or not setted,
463
- * the data will be saved to the service, even if non found
464
- *
465
- * @param filter if you can, use unique parameters for find!
466
- *
467
- * @example
468
- * // by email:
469
- * { email: email }
470
- * //
471
- * @example
472
- * // or by id that is in list:
473
- * { userIds: { $in: this.userId } }
474
- * //
475
- * @example
476
- * // or by number or Date that is Greater Than AND Less Than:
477
- * { points: { $gt: 2, $lt: 14 } }
478
- * // further tools (syntax matches with $gt):
479
- * $eq: // Matches values that are EQual to a specified value.
480
- * $gte: // Matches values that are Greater Than OR Equal to a specified value.
481
- * $lte: // Matches values that are Less Than or Equal to a specified value.
482
- * $ne: // Matches all values that are Not Equal to a specified value.
483
- * $nin: // Matches None of the values specified IN an array.
484
- * //
485
- * @returns {T[]} dataList: T[]
486
- */
487
- async findDatas(filterBy: DynamoNTS_DBFilter<T>, dontSetToService?: boolean): Promise<T[]> {
488
- try {
489
- const dataListExists: T[] = await this.dataDBService.find(filterBy).catch((error): T[] => {
490
- if (error?.errorCode === 'NTS-DBS-F1') {
491
- DynamoFM_Log.warn(`findDatas ${this.dataParams.dataName} didn't found any.`);
492
-
493
- return [];
494
- } else {
495
- throw error;
496
- }
497
- });
498
-
499
- if (!dontSetToService) {
500
- this.dataList = dataListExists;
501
- }
502
-
503
- return dataListExists;
504
- } catch (error) {
505
- throw new DynamoFM_Error({
506
- ...this._getDefaultErrorSettings('findDatas', error),
507
-
508
- errorCode: 'NTS-DS0-FDS0',
509
- });
510
- }
511
- }
512
-
513
- /**
514
- * This function uses the dataDBService.updateOne function.
515
- * This uses updateBy if setted, or data._id if its setted or this.data[this.dependencyKey]
516
- * @param set
517
- *
518
- * // updateOne desc:
519
- *
520
- * Find the data first by any of its parameters, throws error if not found
521
- * @param filter This uses the basic Mongoose updateOne.
522
- * If you can, use unique parameters for find!
523
- * @example
524
- * // by email:
525
- * { email: email }
526
- * //
527
- * @example
528
- * // or by id that is in list:
529
- * { userIds: { $in: this.userId } }
530
- * //
531
- * @example
532
- * // or by number or Date that is Greater Than AND Less Than:
533
- * { points: { $gt: 2, $lt: 14 } }
534
- * // further tools (syntax matches with $gt):
535
- * $eq: // Matches values that are EQual to a specified value.
536
- * $gte: // Matches values that are Greater Than OR Equal to a specified value.
537
- * $lte: // Matches values that are Less Than or Equal to a specified value.
538
- * $ne: // Matches all values that are Not Equal to a specified value.
539
- * $nin: // Matches None of the values specified IN an array.
540
- * //
541
- *
542
- * @param update this uses the basic Mongoose updateOne
543
- * @example
544
- * // increase a specific value (here by 15):
545
- * { $inc: { popularity: 15 } }
546
- * //
547
- * @example
548
- * // or add element to a list:
549
- * { $push: { reactions: this.newReaction }
550
- * // or add multiple elements to a list
551
- * { $push: { schedule: {$each: [ monday, tuesday, wednesday ] } } }
552
- * //
553
- * @example
554
- * // or all at once
555
- * {
556
- * $inc: { popularity: this.newVote.amount },
557
- * emailVerified: true,
558
- * $push: { reactions: this.newReaction }
559
- * }
560
- * // further tools (syntax matches with $inc):
561
- * $currentDate: // Sets the value of a field to current date, either as a Date or a Timestamp.
562
- * $min: // Only updates the field if the specified value is less than the existing field value.
563
- * $max: // Only updates the field if the specified value is greater than the existing field value.
564
- * $mul: // Multiplies the value of the field by the specified amount.
565
- * $rename: // Renames a field.
566
- * $unset: // Removes the specified field from a document. (set: "" to value)
567
- * //
568
- */
569
- async updateData(
570
- set: { filterBy?: DynamoNTS_DBFilter<T>, update: DynamoNTS_DBUpdate<T> }
571
- ): Promise<void> {
572
- try {
573
- if (set.filterBy) {
574
- await this.dataDBService.updateOne(set.filterBy, set.update, this.issuer);
575
-
576
- } else if (this.data._id) {
577
- await this.dataDBService.updateOne(
578
- { _id: this.data._id } as DynamoNTS_DBFilter<T>,
579
- set.update,
580
- this.issuer
581
- );
582
-
583
- } else if (this.depKey && this.data[this.depKey]) {
584
- await this.dataDBService.updateOne(
585
- { [this.depKey]: this.data[this.depKey] } as DynamoNTS_DBFilter<T>,
586
- set.update,
587
- this.issuer
588
- );
589
-
590
- } else {
591
- throw new DynamoFM_Error({
592
- ...this._getDefaultErrorSettings(
593
- 'updateData',
594
- new Error(
595
- `no usable parameter provided for updateData; no updateBy, no id, no dependencyId ` +
596
- `(${this.dataParams.dataName})`
597
- )
598
- ),
599
-
600
- errorCode: 'NTS-DS0-UD1',
601
- });
602
- }
603
- } catch (error) {
604
-
605
- if (error?.errorCode == 'NTS-DS0-UD1') {
606
- throw error;
607
-
608
- } else {
609
- throw new DynamoFM_Error({
610
- ...this._getDefaultErrorSettings('updateData', error),
611
-
612
- errorCode: 'NTS-DS0-UD0',
613
- });
614
- }
615
- }
616
- }
617
-
618
- /**
619
- * modifies data if the data have ID and already exists in the DB,
620
- * creates new if the ID is not present or cant find in DB,
621
- * and if dependency data setted up, will check before creation,
622
- *
623
- * @warning
624
- * but the proper way to update data, if you use update method instead,
625
- * this way, you can avoid data override errors
626
- * (when you simultaneously trying to change the same data's
627
- * different values from different flows)
628
- */
629
- async saveData(): Promise<T> {
630
- try {
631
- if (!this.data) {
632
- throw new DynamoFM_Error({
633
- ...this._getDefaultErrorSettings(
634
- 'saveData',
635
- new Error(`no data to save! (${this.dataParams.dataName})`)
636
- ),
637
-
638
- errorCode: 'NTS-DS0-SD4',
639
- });
640
- }
641
-
642
- await this.validateForSave();
643
-
644
- if (!this.data._id && (!this.depKey || !this.data[this.depKey])) {
645
- // if ID of dependencyID is not present, data not exists, create new data
646
- this.data = await this.dataDBService.createData(this.data, this.issuer);
647
-
648
- return this.data;
649
- }
650
-
651
- let dataExists: T;
652
-
653
- // check if data already exists with the specific ID
654
- if (this.data._id) {
655
- dataExists = await this.getDataById(null, true);
656
-
657
- if (dataExists) {
658
- // if data exists do modify
659
- this.data = await this.dataDBService.modifyData(this.data, this.issuer);
660
-
661
- return this.data;
662
-
663
- } else {
664
- throw new DynamoFM_Error({
665
- ...this._getDefaultErrorSettings(
666
- 'saveData',
667
- new Error(
668
- `saveData was unsuccessful: provided ID not exists ` +
669
- `(id: ${this.data._id}, ${this.dataParams.dataName})`
670
- )
671
- ),
672
-
673
- errorCode: 'NTS-DS0-SD1',
674
- });
675
- }
676
- }
677
-
678
- if (this.depKey) {
679
- if (!this.data[this.depKey]) {
680
- throw new DynamoFM_Error({
681
- ...this._getDefaultErrorSettings(
682
- 'saveData',
683
- new Error(
684
- `saveData was unsuccessful: dependency data id missing from data ` +
685
- `(key: ${this.depKey}, ${this.dataParams.dataName})`
686
- )
687
- ),
688
-
689
- errorCode: 'NTS-DS0-SD2',
690
- });
691
- }
692
-
693
- if (this.depKeyIsUnique) {
694
- dataExists = await this.getDataByDependencyId(null, true);
695
-
696
- if (dataExists) {
697
- // if data exists do modify
698
- this.data = await this.dataDBService.modifyData(this.data, this.issuer);
699
-
700
- return this.data;
701
-
702
- } else if (this.depKeyIsRequired) {
703
- // if data not exists check that dependency already exists for this
704
- const dependencyExists = await this.getDependencyDataDBService()
705
- .getDataById(this.data[this.depKey])
706
- .catch();
707
-
708
- if (!dependencyExists) {
709
- throw new DynamoFM_Error({
710
- ...this._getDefaultErrorSettings(
711
- 'saveData',
712
- new Error(
713
- `saveData was unsuccessful: dependency data not exists ` +
714
- `(key: ${this.depKey}, id: ${this.data[this.depKey]}, ` +
715
- `${this.dataParams.dataName})`
716
- )
717
- ),
718
-
719
- errorCode: 'NTS-DS0-SD3',
720
- });
721
- }
722
- }
723
- }
724
- }
725
-
726
- // if data not exists create new data
727
- this.data = await this.dataDBService.createData(this.data, this.issuer);
728
-
729
- return this.data;
730
-
731
- } catch (error) {
732
- if ([ 'NTS-DS0-SD1', 'NTS-DS0-SD2' ].includes(error?.errorCode)) {
733
- throw error;
734
-
735
- } else {
736
- throw new DynamoFM_Error({
737
- ...this._getDefaultErrorSettings('saveData', error),
738
-
739
- errorCode: 'NTS-DS0-SD0',
740
- });
741
- }
742
- }
743
- }
744
-
745
- /**
746
- * permanently deletes data from database by data._id
747
- */
748
- async deleteData(): Promise<void> {
749
- try {
750
- if (!this.data._id) {
751
- throw new DynamoFM_Error({
752
- ...this._getDefaultErrorSettings(
753
- 'deleteData',
754
- new Error(`deleteData failed, ID is missing! (${this.dataParams.dataName})`)
755
- ),
756
-
757
- errorCode: 'NTS-DS0-DD1',
758
- });
759
- }
760
-
761
- await this.dataDBService.deleteDataById(this.data._id);
762
- } catch (error) {
763
- if (error?.errorCode == 'NTS-DS0-DD1') {
764
- throw error;
765
- } else {
766
- throw new DynamoFM_Error({
767
- ...this._getDefaultErrorSettings('deleteData', error),
768
-
769
- errorCode: 'NTS-DS0-DD0',
770
- });
771
- }
772
- }
773
- }
774
-
775
- /**
776
- * validation of data, for modify and create, by the ModelParams
777
- */
778
- async validateForSave(): Promise<void> {
779
- try {
780
- for (let i = 0; i < this.dataParams.properties.length; i++) {
781
- // basic required validations
782
- if (
783
- (this.dataParams.properties[i].required &&
784
- (this.data[this.dataParams.properties[i].key] === null ||
785
- this.data[this.dataParams.properties[i].key] === undefined
786
- )
787
- ) ||
788
- (this.dataParams.properties[i].index &&
789
- (this.data[this.dataParams.properties[i].key] === null ||
790
- this.data[this.dataParams.properties[i].key] === undefined
791
- )
792
- )
793
- ) {
794
- throw new DynamoFM_Error({
795
- ...this._getDefaultErrorSettings(
796
- 'validateForSave',
797
- new Error(
798
- `validateForSave failed, ${this.dataParams.properties[i].key} is missing! ` +
799
- `(${this.dataParams.dataName})`
800
- )
801
- ),
802
-
803
- status: 422,
804
- errorCode: 'NTS-DS0-VD1',
805
- userMessage: this.defaultValidationErrorUserMsg,
806
- });
807
- }
808
-
809
- // specific Date validation
810
- if (this.dataParams.properties[i].type === 'Date' &&
811
- !(new Date(this.data[this.dataParams.properties[i].key]) instanceof Date)
812
- ) {
813
- throw new DynamoFM_Error({
814
- ...this._getDefaultErrorSettings(
815
- 'validateForSave',
816
- new Error(
817
- `validateForSave failed, ${this.dataParams.properties[i].key} is not a date! ` +
818
- `(${this.dataParams.dataName})`
819
- )
820
- ),
821
-
822
- status: 422,
823
- errorCode: 'NTS-DS0-VD2',
824
- userMessage: this.defaultValidationErrorUserMsg,
825
- });
826
- }
827
-
828
- // call additional validators
829
- if (this.dataParams.properties[i].additionalValidators) {
830
- for (let j = 0; j < this.dataParams.properties[i].additionalValidators.length; j++) {
831
- this.dataParams.properties[i].additionalValidators[j](
832
- this.data[this.dataParams.properties[i].key]
833
- );
834
- }
835
- }
836
- }
837
- } catch (error) {
838
- if ([ 'NTS-DS0-VD1', 'NTS-DS0-VD2' ].includes(error?.errorCode)) {
839
- throw error;
840
- } else {
841
- throw new DynamoFM_Error({
842
- ...this._getDefaultErrorSettings('validateForSave', error),
843
-
844
- status: 422,
845
- errorCode: 'NTS-DS0-VD0',
846
- });
847
- }
848
- }
849
- }
850
-
851
- /**
852
- * setting up dependency dataHook by DynamoBEDataModelParams
853
- */
854
- private lookForDependencyDataSettings(): void {
855
- const dependencyParam: DynamoFM_DataProperty_Params = this.dataParams.properties.find(
856
- (modelParams: DynamoFM_DataProperty_Params): boolean => modelParams.isDependencyHook
857
- );
858
-
859
- if (dependencyParam) {
860
- this.depKey = dependencyParam.key;
861
-
862
- if (dependencyParam.dependencyDataName) {
863
- this.depDBServiceKey = dependencyParam.dependencyDataName;
864
- }
865
-
866
- if (dependencyParam.unique) {
867
- this.depKeyIsUnique = true;
868
- }
869
-
870
- if (dependencyParam.required) {
871
- this.depKeyIsRequired = true;
872
- }
873
- }
874
- }
875
-
876
- /**
877
- *
878
- * @returns
879
- */
880
- getDependencyDataDBService(): DynamoNTS_DBService<any> {
881
- if (!this.depDBServiceKey) {
882
- throw new DynamoFM_Error({
883
- ...this._getDefaultErrorSettings(
884
- 'getDependencyDataDBService',
885
- new Error(
886
- `getDependencyDataDBService was unsuccessful, service key not setted up! ` +
887
- `(${this.dataParams.dataName}))`
888
- )
889
- ),
890
-
891
- status: 501,
892
- errorCode: 'NTS-DS0-GDDB0',
893
- });
894
- }
895
-
896
- if (this.depDataDBService) {
897
- return this.depDataDBService;
898
- } else {
899
- this.depDataDBService = DynamoNTS_GlobalService.getDBServiceByKey(this.depDBServiceKey);
900
-
901
- return this.depDataDBService;
902
- }
903
- }
904
-
905
- private _getDefaultErrorSettings(
906
- fnName: string,
907
- error: DynamoFM_AnyError
908
- ): DynamoFM_Error_Settings {
909
- return {
910
- status: (error as DynamoFM_Error)?.___status ?? 500,
911
- message:
912
- (error as Error)?.message ??
913
- `${fnName} was UNSUCCESFUL (NTS; ${this.dataParams.dataName})`,
914
- addECToUserMsg: !(error as DynamoFM_Error)?.__userMessage,
915
- userMessage: (error as DynamoFM_Error)?.__userMessage ?? this.defaultErrorUserMsg,
916
- issuer: this.issuer,
917
- issuerService: this.serviceName + ` (${this?.constructor?.name}-DynamoNTS_DataService)`,
918
- error: error,
919
- };
920
- }
921
- }
1
+
2
+ import {
3
+ DynamoFM_Metadata, DynamoFM_DataModel_Params, DynamoFM_DataProperty_Params, DynamoFM_Error,
4
+ DynamoFM_Log, DynamoFM_AnyError, DynamoFM_Error_Settings, DynamoFM_ErrorLevel
5
+ } from '@futdevpro/fsm-dynamo';
6
+ import { DynamoNTS_DBFilter } from '../../_models/types/db-filter.type';
7
+ import { DynamoNTS_DBUpdate } from '../../_models/types/db-update.type';
8
+
9
+ import { DynamoNTS_DBService } from './db.service';
10
+ import { DynamoNTS_GlobalService } from '../core/global.service';
11
+
12
+ /**
13
+ * Basic Data Service that is connected to the relevant DBServices
14
+ *
15
+ * @example
16
+ * export class UserMatchStatisticsService extends DynamoNTS_DataService<UserMatchStatistics> {
17
+ * constructor(
18
+ * set?: {
19
+ * data?: UserMatchStatistics,
20
+ * issuer?: string,
21
+ * }
22
+ * ) {
23
+ * super(
24
+ * new UserMatchStatistics(set?.data),
25
+ * userMatchStatisticsModelParams
26
+ * );
27
+ * this.issuer = set?.issuer;
28
+ * }
29
+ * }
30
+ */
31
+ export class DynamoNTS_DataService<T extends DynamoFM_Metadata> {
32
+
33
+ serviceName: string;
34
+
35
+ dataDBService: DynamoNTS_DBService<T>;
36
+ data: T;
37
+ dataList: T[] = [];
38
+ issuer: string;
39
+
40
+ depKey?: string;
41
+ depDBServiceKey?: string;
42
+ depKeyIsUnique?: boolean;
43
+ depKeyIsRequired?: boolean;
44
+ private depDataDBService: DynamoNTS_DBService<any>;
45
+
46
+ dataParams: DynamoFM_DataModel_Params;
47
+
48
+ defaultErrorUserMsg: string =
49
+ `We encountered an unhandled Data Service Error, ` +
50
+ `\nplease contact the responsible development team.`;
51
+ defaultValidationErrorUserMsg: string =
52
+ `We encountered an unhandled Validation Error, ` +
53
+ `\nplease contact the responsible development team.`;
54
+
55
+ constructor(
56
+ /**
57
+ * Initial data, this will be used by functions on default
58
+ */
59
+ data: T,
60
+ /**
61
+ * DB data prams will be used to connect to usable dbService on GlobalService
62
+ */
63
+ dataParams: DynamoFM_DataModel_Params,
64
+ /**
65
+ * Initial set for issuer to be able to follow the issuer's activity
66
+ */
67
+ issuer: string
68
+ ) {
69
+ try {
70
+ this.serviceName = this.constructor?.name;
71
+ this.dataDBService = DynamoNTS_GlobalService.getDBService<T>(dataParams);
72
+ this.data = data;
73
+ this.dataParams = dataParams;
74
+ this.lookForDependencyDataSettings();
75
+ this.issuer = issuer;
76
+ } catch (error) {
77
+ throw new DynamoFM_Error({
78
+ ...this._getDefaultErrorSettings('constructor', error),
79
+ message: `The dataService construction failed for ${dataParams?.dataName}. ` +
80
+ `${this.serviceName} (${this.constructor.name})` +
81
+ `\nMaybe you forgot to add the dbService to the GlobalService?\n\n`,
82
+ level: DynamoFM_ErrorLevel.critical,
83
+
84
+ errorCode: 'NTS-DS0-C00',
85
+ });
86
+ /* DynamoFM_Log.error(
87
+ `\nDynamoNTS_DataService ERROR: ` +
88
+ `\nThe dataService construction failed for ` +
89
+ `${dataParams?.dataName}. ${this.serviceName} (${this.constructor.name})` +
90
+ `\nMaybe you forgot to add the dbService to the GlobalService?` +
91
+ `\n\n`,
92
+ new Error()
93
+ ); */
94
+ }
95
+ }
96
+
97
+ /**
98
+ * returns all data from database to service dataList
99
+ */
100
+ async getAll(dontSetToService?: boolean): Promise<T[]> {
101
+ try {
102
+ const dataListExists: T[] = await this.dataDBService.getAll().catch((error): T[] => {
103
+ if (error?.errorCode === 'NTS-DBS-GA1') {
104
+ DynamoFM_Log.warn(`getAll ${this.dataParams.dataName} didn't found any.`);
105
+
106
+ return [];
107
+ } else {
108
+ throw error;
109
+ }
110
+ });
111
+
112
+ if (!dontSetToService) {
113
+ this.dataList = dataListExists;
114
+ }
115
+
116
+ return dataListExists;
117
+ } catch (error) {
118
+ throw new DynamoFM_Error({
119
+ ...this._getDefaultErrorSettings('getAll', error),
120
+
121
+ errorCode: 'NTS-DS0-GA0',
122
+ });
123
+ }
124
+ }
125
+
126
+ /**
127
+ * @description
128
+ * returns data from database by id
129
+ * also if dontSetToService is false or not setted,
130
+ * the data will be saved to the service, even if its not found
131
+ *
132
+ * @remarks
133
+ * If you need to get-save a data, if possible,
134
+ * use db-service update instead.
135
+ *
136
+ * @param {string} id
137
+ * (using id from service.data, if not provided)
138
+ * @param dontSetToService
139
+ *
140
+ * @return {T} data: T
141
+ */
142
+ async getDataById(id?: string, dontSetToService?: boolean): Promise<T> {
143
+ try {
144
+ if (!id && !this.data._id) {
145
+ throw new DynamoFM_Error({
146
+ ...this._getDefaultErrorSettings(
147
+ 'getDataById',
148
+ new Error(
149
+ `getDataById failed, ID is missing! ` +
150
+ `(maybe you wanted to use getDataByDependencyId() instead...) ` +
151
+ `(${this.dataParams.dataName})`
152
+ )
153
+ ),
154
+
155
+ errorCode: 'NTS-DS0-GI1',
156
+ });
157
+ }
158
+
159
+ const dataExists: T = await this.dataDBService.getDataById(id ?? this.data._id);
160
+
161
+ if (!dontSetToService) {
162
+ this.data = dataExists;
163
+ }
164
+
165
+ return dataExists;
166
+ } catch (error) {
167
+ if (error?.errorCode == 'NTS-DS0-GI1') {
168
+ throw error;
169
+ } else {
170
+ throw new DynamoFM_Error({
171
+ ...this._getDefaultErrorSettings('getDataById', error),
172
+ errorCode: 'NTS-DS0-GI0',
173
+ });
174
+ }
175
+ }
176
+ }
177
+
178
+ async getDataByIds(ids: string[], dontSetToService?: boolean): Promise<T[]> {
179
+ try {
180
+ if (!ids) {
181
+ throw new DynamoFM_Error({
182
+ ...this._getDefaultErrorSettings(
183
+ 'getDataByIds',
184
+ new Error(`getDataByIds failed, ids is missing! (${this.dataParams.dataName})`)
185
+ ),
186
+
187
+ errorCode: 'NTS-DS0-GIS1',
188
+ });
189
+ }
190
+
191
+ if (ids.length === 0) {
192
+ return [];
193
+ }
194
+
195
+ const datas: T[] = await this.dataDBService.find({ _id: { $in: ids } });
196
+
197
+ if (!dontSetToService) {
198
+ this.dataList = datas;
199
+ }
200
+
201
+ return datas;
202
+ } catch (error) {
203
+ throw new DynamoFM_Error({
204
+ ...this._getDefaultErrorSettings('getDataByIds', error),
205
+
206
+ errorCode: 'NTS-DS0-GIS0',
207
+ });
208
+ }
209
+ }
210
+
211
+ /**
212
+ * returns data from database by dependencyId to the service
213
+ * (using id from service.data, if not provided)
214
+ * @param dependencyId
215
+ */
216
+ async getDataByDependencyId(dependencyId?: string, dontSetToService?: boolean): Promise<T> {
217
+ try {
218
+ if (!this.depKey) {
219
+ throw new DynamoFM_Error({
220
+ ...this._getDefaultErrorSettings(
221
+ 'getDataByDependencyId',
222
+ new Error(
223
+ `getDataByDependencyId failed, dependencyKey is missing from service! ` +
224
+ `(${this.dataParams.dataName})`
225
+ )
226
+ ),
227
+
228
+ errorCode: 'NTS-DS0-GD1',
229
+ });
230
+ }
231
+
232
+ if (!dependencyId && !this.data[this.depKey]) {
233
+ throw new DynamoFM_Error({
234
+ ...this._getDefaultErrorSettings(
235
+ 'getDataByDependencyId',
236
+ new Error(
237
+ `getDataByDependencyId failed, ${this.depKey} is missing! ` +
238
+ `(${this.dataParams.dataName})`
239
+ )
240
+ ),
241
+
242
+ errorCode: 'NTS-DS0-GD2',
243
+ });
244
+ }
245
+
246
+ const dataExists: T = await this.dataDBService.getDataByDependencyId(
247
+ dependencyId ?? this.data[this.depKey]
248
+ ).catch((error): null => {
249
+ if (error?.errorCode === 'NTS-DBS-GD2') {
250
+ DynamoFM_Log.warn(
251
+ `getDataByDependencyId failed; ${this.dataParams.dataName} ` +
252
+ `(${this.depKey}: ${dependencyId ?? this.data[this.depKey]}) didn't found any.`
253
+ );
254
+
255
+ return null;
256
+ } else {
257
+ throw error;
258
+ }
259
+ });
260
+
261
+ if (!dontSetToService) {
262
+ this.data = dataExists;
263
+ }
264
+
265
+ return dataExists;
266
+ } catch (error) {
267
+ if ([ 'NTS-DS0-GD1', 'NTS-DS0-GD2' ].includes(error?.errorCode)) {
268
+ throw error;
269
+ } else {
270
+ throw new DynamoFM_Error({
271
+ ...this._getDefaultErrorSettings('getDataByDependencyId', error),
272
+
273
+ errorCode: 'NTS-DS0-GD0',
274
+ });
275
+ }
276
+ }
277
+ }
278
+
279
+ async getDatasByDependencyIds(dependencyIds: string[], dontSetToService?: boolean): Promise<T[]> {
280
+ try {
281
+ if (!this.depKey) {
282
+ throw new DynamoFM_Error({
283
+ ...this._getDefaultErrorSettings(
284
+ 'getDatasByDependencyIds',
285
+ new Error(
286
+ `getDatasByDependencyIds failed, dependencyKey is missing from service! ` +
287
+ `(${this.dataParams.dataName})`
288
+ )
289
+ ),
290
+
291
+ errorCode: 'NTS-DS0-GDS1',
292
+ });
293
+ }
294
+
295
+ if (!dependencyIds) {
296
+ throw new DynamoFM_Error({
297
+ ...this._getDefaultErrorSettings(
298
+ 'getDatasByDependencyIds',
299
+ new Error(
300
+ `getDatasByDependencyIds failed, dependencyIds is missing! ` +
301
+ `(${this.dataParams.dataName})`
302
+ )
303
+ ),
304
+
305
+ errorCode: 'NTS-DS0-GDS2',
306
+ });
307
+ }
308
+
309
+ if (dependencyIds.length === 0) {
310
+ return [];
311
+ }
312
+
313
+ const datas: T[] = await this.dataDBService.getDatasByDependencyIds(dependencyIds);
314
+
315
+ if (!dontSetToService) {
316
+ this.dataList = datas;
317
+ }
318
+
319
+ return datas;
320
+ } catch (error) {
321
+ if ([ 'NTS-DS0-GDS1', 'NTS-DS0-GDS2' ].includes(error?.errorCode)) {
322
+ throw error;
323
+ } else {
324
+ throw new DynamoFM_Error({
325
+ ...this._getDefaultErrorSettings('getDatasByDependencyIds', error),
326
+
327
+ errorCode: 'NTS-DS0-GDS0',
328
+ });
329
+ }
330
+ }
331
+ }
332
+
333
+ /**
334
+ * returns dataList from database by dependencyId to the service
335
+ * @param dependencyId
336
+ */
337
+ async getDataListByDependencyId(dependencyId?: string, dontSetToService?: boolean): Promise<T[]> {
338
+ try {
339
+ if (!this.depKey) {
340
+ throw new DynamoFM_Error({
341
+ ...this._getDefaultErrorSettings(
342
+ 'getDataListByDependencyId',
343
+ new Error(
344
+ `getDataListByDependencyId failed, dependencyKey is missing from service! ` +
345
+ `(${this.dataParams.dataName})`
346
+ )
347
+ ),
348
+
349
+ errorCode: 'NTS-DS0-GLD1',
350
+ });
351
+ }
352
+
353
+ if (!dependencyId && !this.data[this.depKey]) {
354
+ throw new DynamoFM_Error({
355
+ ...this._getDefaultErrorSettings(
356
+ 'getDataListByDependencyId',
357
+ new Error(
358
+ `getDataListByDependencyId failed, ${this.depKey} is missing! ` +
359
+ `(${this.dataParams.dataName})`
360
+ )
361
+ ),
362
+
363
+ errorCode: 'NTS-DS0-GLD2',
364
+ });
365
+ }
366
+
367
+ const dataListExists: T[] = await this.dataDBService.getDataListByDependencyId(
368
+ dependencyId ?? this.data[this.depKey]
369
+ ).catch((error): T[] => {
370
+ if (error?.errorCode === 'NTS-DBS-GLD2') {
371
+ DynamoFM_Log.warn(
372
+ `getDataListByDependencyId ${this.dataParams.dataName} ` +
373
+ `(${this.depKey}: ${dependencyId ?? this.data[this.depKey]}) didn't found any.`
374
+ );
375
+
376
+ return [];
377
+ } else {
378
+ throw error;
379
+ }
380
+ });
381
+
382
+ if (!dontSetToService) {
383
+ this.dataList = dataListExists;
384
+ }
385
+
386
+ return dataListExists;
387
+ } catch (error) {
388
+ if ([ 'NTS-DS0-GLD1', 'NTS-DS0-GLD2' ].includes(error?.errorCode)) {
389
+ throw error;
390
+ } else {
391
+ throw new DynamoFM_Error({
392
+ ...this._getDefaultErrorSettings('getDataListByDependencyId', error),
393
+
394
+ errorCode: 'NTS-DS0-GLD0',
395
+
396
+ });
397
+ }
398
+ }
399
+ }
400
+
401
+ /**
402
+ *
403
+ * // findOne desc:
404
+ *
405
+ * Find the data first by any of its parameters,
406
+ * also if dontSetToService is false or not setted,
407
+ * the data will be saved to the service, even if non found
408
+ *
409
+ * @param filter if you can, use unique parameters for find!
410
+ *
411
+ * @example
412
+ * // by email:
413
+ * { email: email }
414
+ * //
415
+ * @example
416
+ * // or by id that is in list:
417
+ * { userIds: { $in: this.userId } }
418
+ * //
419
+ * @example
420
+ * // or by number or Date that is Greater Than AND Less Than:
421
+ * { points: { $gt: 2, $lt: 14 } }
422
+ * // further tools (syntax matches with $gt):
423
+ * $eq: // Matches values that are EQual to a specified value.
424
+ * $gte: // Matches values that are Greater Than OR Equal to a specified value.
425
+ * $lte: // Matches values that are Less Than or Equal to a specified value.
426
+ * $ne: // Matches all values that are Not Equal to a specified value.
427
+ * $nin: // Matches None of the values specified IN an array.
428
+ * //
429
+ * @returns {T} data: T
430
+ */
431
+ async findData(filterBy: DynamoNTS_DBFilter<T>, dontSetToService?: boolean): Promise<T> {
432
+ try {
433
+ const dataExists: T = await this.dataDBService.findOne(filterBy).catch((error): null => {
434
+ if (error?.errorCode === 'NTS-DBS-FO1') {
435
+ DynamoFM_Log.warn(`findData ${this.dataParams.dataName} didn't found any.`);
436
+
437
+ return null;
438
+ } else {
439
+ throw error;
440
+ }
441
+ });
442
+
443
+ if (!dontSetToService) {
444
+ this.data = dataExists;
445
+ }
446
+
447
+ return dataExists;
448
+ } catch (error) {
449
+ throw new DynamoFM_Error({
450
+ ...this._getDefaultErrorSettings('findData', error),
451
+
452
+ errorCode: 'NTS-DS0-FD0',
453
+ });
454
+ }
455
+ }
456
+
457
+ /**
458
+ *
459
+ * // find desc:
460
+ *
461
+ * Find the data first by any of its parameters,
462
+ * also if dontSetToService is false or not setted,
463
+ * the data will be saved to the service, even if non found
464
+ *
465
+ * @param filter if you can, use unique parameters for find!
466
+ *
467
+ * @example
468
+ * // by email:
469
+ * { email: email }
470
+ * //
471
+ * @example
472
+ * // or by id that is in list:
473
+ * { userIds: { $in: this.userId } }
474
+ * //
475
+ * @example
476
+ * // or by number or Date that is Greater Than AND Less Than:
477
+ * { points: { $gt: 2, $lt: 14 } }
478
+ * // further tools (syntax matches with $gt):
479
+ * $eq: // Matches values that are EQual to a specified value.
480
+ * $gte: // Matches values that are Greater Than OR Equal to a specified value.
481
+ * $lte: // Matches values that are Less Than or Equal to a specified value.
482
+ * $ne: // Matches all values that are Not Equal to a specified value.
483
+ * $nin: // Matches None of the values specified IN an array.
484
+ * //
485
+ * @returns {T[]} dataList: T[]
486
+ */
487
+ async findDatas(filterBy: DynamoNTS_DBFilter<T>, dontSetToService?: boolean): Promise<T[]> {
488
+ try {
489
+ const dataListExists: T[] = await this.dataDBService.find(filterBy).catch((error): T[] => {
490
+ if (error?.errorCode === 'NTS-DBS-F1') {
491
+ DynamoFM_Log.warn(`findDatas ${this.dataParams.dataName} didn't found any.`);
492
+
493
+ return [];
494
+ } else {
495
+ throw error;
496
+ }
497
+ });
498
+
499
+ if (!dontSetToService) {
500
+ this.dataList = dataListExists;
501
+ }
502
+
503
+ return dataListExists;
504
+ } catch (error) {
505
+ throw new DynamoFM_Error({
506
+ ...this._getDefaultErrorSettings('findDatas', error),
507
+
508
+ errorCode: 'NTS-DS0-FDS0',
509
+ });
510
+ }
511
+ }
512
+
513
+ /**
514
+ * This function uses the dataDBService.updateOne function.
515
+ * This uses updateBy if setted, or data._id if its setted or this.data[this.dependencyKey]
516
+ * @param set
517
+ *
518
+ * // updateOne desc:
519
+ *
520
+ * Find the data first by any of its parameters, throws error if not found
521
+ * @param filter This uses the basic Mongoose updateOne.
522
+ * If you can, use unique parameters for find!
523
+ * @example
524
+ * // by email:
525
+ * { email: email }
526
+ * //
527
+ * @example
528
+ * // or by id that is in list:
529
+ * { userIds: { $in: this.userId } }
530
+ * //
531
+ * @example
532
+ * // or by number or Date that is Greater Than AND Less Than:
533
+ * { points: { $gt: 2, $lt: 14 } }
534
+ * // further tools (syntax matches with $gt):
535
+ * $eq: // Matches values that are EQual to a specified value.
536
+ * $gte: // Matches values that are Greater Than OR Equal to a specified value.
537
+ * $lte: // Matches values that are Less Than or Equal to a specified value.
538
+ * $ne: // Matches all values that are Not Equal to a specified value.
539
+ * $nin: // Matches None of the values specified IN an array.
540
+ * //
541
+ *
542
+ * @param update this uses the basic Mongoose updateOne
543
+ * @example
544
+ * // increase a specific value (here by 15):
545
+ * { $inc: { popularity: 15 } }
546
+ * //
547
+ * @example
548
+ * // or add element to a list:
549
+ * { $push: { reactions: this.newReaction }
550
+ * // or add multiple elements to a list
551
+ * { $push: { schedule: {$each: [ monday, tuesday, wednesday ] } } }
552
+ * //
553
+ * @example
554
+ * // or all at once
555
+ * {
556
+ * $inc: { popularity: this.newVote.amount },
557
+ * emailVerified: true,
558
+ * $push: { reactions: this.newReaction }
559
+ * }
560
+ * // further tools (syntax matches with $inc):
561
+ * $currentDate: // Sets the value of a field to current date, either as a Date or a Timestamp.
562
+ * $min: // Only updates the field if the specified value is less than the existing field value.
563
+ * $max: // Only updates the field if the specified value is greater than the existing field value.
564
+ * $mul: // Multiplies the value of the field by the specified amount.
565
+ * $rename: // Renames a field.
566
+ * $unset: // Removes the specified field from a document. (set: "" to value)
567
+ * //
568
+ */
569
+ async updateData(
570
+ set: { filterBy?: DynamoNTS_DBFilter<T>, update: DynamoNTS_DBUpdate<T> }
571
+ ): Promise<void> {
572
+ try {
573
+ if (set.filterBy) {
574
+ await this.dataDBService.updateOne(set.filterBy, set.update, this.issuer);
575
+
576
+ } else if (this.data._id) {
577
+ await this.dataDBService.updateOne(
578
+ { _id: this.data._id } as DynamoNTS_DBFilter<T>,
579
+ set.update,
580
+ this.issuer
581
+ );
582
+
583
+ } else if (this.depKey && this.data[this.depKey]) {
584
+ await this.dataDBService.updateOne(
585
+ { [this.depKey]: this.data[this.depKey] } as DynamoNTS_DBFilter<T>,
586
+ set.update,
587
+ this.issuer
588
+ );
589
+
590
+ } else {
591
+ throw new DynamoFM_Error({
592
+ ...this._getDefaultErrorSettings(
593
+ 'updateData',
594
+ new Error(
595
+ `no usable parameter provided for updateData; no updateBy, no id, no dependencyId ` +
596
+ `(${this.dataParams.dataName})`
597
+ )
598
+ ),
599
+
600
+ errorCode: 'NTS-DS0-UD1',
601
+ });
602
+ }
603
+ } catch (error) {
604
+
605
+ if (error?.errorCode == 'NTS-DS0-UD1') {
606
+ throw error;
607
+
608
+ } else {
609
+ throw new DynamoFM_Error({
610
+ ...this._getDefaultErrorSettings('updateData', error),
611
+
612
+ errorCode: 'NTS-DS0-UD0',
613
+ });
614
+ }
615
+ }
616
+ }
617
+
618
+ /**
619
+ * modifies data if the data have ID and already exists in the DB,
620
+ * creates new if the ID is not present or cant find in DB,
621
+ * and if dependency data setted up, will check before creation,
622
+ *
623
+ * @warning
624
+ * but the proper way to update data, if you use update method instead,
625
+ * this way, you can avoid data override errors
626
+ * (when you simultaneously trying to change the same data's
627
+ * different values from different flows)
628
+ */
629
+ async saveData(): Promise<T> {
630
+ try {
631
+ if (!this.data) {
632
+ throw new DynamoFM_Error({
633
+ ...this._getDefaultErrorSettings(
634
+ 'saveData',
635
+ new Error(`no data to save! (${this.dataParams.dataName})`)
636
+ ),
637
+
638
+ errorCode: 'NTS-DS0-SD4',
639
+ });
640
+ }
641
+
642
+ await this.validateForSave();
643
+
644
+ if (!this.data._id && (!this.depKey || !this.data[this.depKey])) {
645
+ // if ID of dependencyID is not present, data not exists, create new data
646
+ this.data = await this.dataDBService.createData(this.data, this.issuer);
647
+
648
+ return this.data;
649
+ }
650
+
651
+ let dataExists: T;
652
+
653
+ // check if data already exists with the specific ID
654
+ if (this.data._id) {
655
+ dataExists = await this.getDataById(null, true);
656
+
657
+ if (dataExists) {
658
+ // if data exists do modify
659
+ this.data = await this.dataDBService.modifyData(this.data, this.issuer);
660
+
661
+ return this.data;
662
+
663
+ } else {
664
+ throw new DynamoFM_Error({
665
+ ...this._getDefaultErrorSettings(
666
+ 'saveData',
667
+ new Error(
668
+ `saveData was unsuccessful: provided ID not exists ` +
669
+ `(id: ${this.data._id}, ${this.dataParams.dataName})`
670
+ )
671
+ ),
672
+
673
+ errorCode: 'NTS-DS0-SD1',
674
+ });
675
+ }
676
+ }
677
+
678
+ if (this.depKey) {
679
+ if (!this.data[this.depKey]) {
680
+ throw new DynamoFM_Error({
681
+ ...this._getDefaultErrorSettings(
682
+ 'saveData',
683
+ new Error(
684
+ `saveData was unsuccessful: dependency data id missing from data ` +
685
+ `(key: ${this.depKey}, ${this.dataParams.dataName})`
686
+ )
687
+ ),
688
+
689
+ errorCode: 'NTS-DS0-SD2',
690
+ });
691
+ }
692
+
693
+ if (this.depKeyIsUnique) {
694
+ dataExists = await this.getDataByDependencyId(null, true);
695
+
696
+ if (dataExists) {
697
+ // if data exists do modify
698
+ this.data = await this.dataDBService.modifyData(this.data, this.issuer);
699
+
700
+ return this.data;
701
+
702
+ } else if (this.depKeyIsRequired) {
703
+ // if data not exists check that dependency already exists for this
704
+ const dependencyExists = await this.getDependencyDataDBService()
705
+ .getDataById(this.data[this.depKey])
706
+ .catch();
707
+
708
+ if (!dependencyExists) {
709
+ throw new DynamoFM_Error({
710
+ ...this._getDefaultErrorSettings(
711
+ 'saveData',
712
+ new Error(
713
+ `saveData was unsuccessful: dependency data not exists ` +
714
+ `(key: ${this.depKey}, id: ${this.data[this.depKey]}, ` +
715
+ `${this.dataParams.dataName})`
716
+ )
717
+ ),
718
+
719
+ errorCode: 'NTS-DS0-SD3',
720
+ });
721
+ }
722
+ }
723
+ }
724
+ }
725
+
726
+ // if data not exists create new data
727
+ this.data = await this.dataDBService.createData(this.data, this.issuer);
728
+
729
+ return this.data;
730
+
731
+ } catch (error) {
732
+ if ([ 'NTS-DS0-SD1', 'NTS-DS0-SD2' ].includes(error?.errorCode)) {
733
+ throw error;
734
+
735
+ } else {
736
+ throw new DynamoFM_Error({
737
+ ...this._getDefaultErrorSettings('saveData', error),
738
+
739
+ errorCode: 'NTS-DS0-SD0',
740
+ });
741
+ }
742
+ }
743
+ }
744
+
745
+ /**
746
+ * permanently deletes data from database by data._id
747
+ */
748
+ async deleteData(): Promise<void> {
749
+ try {
750
+ if (!this.data._id) {
751
+ throw new DynamoFM_Error({
752
+ ...this._getDefaultErrorSettings(
753
+ 'deleteData',
754
+ new Error(`deleteData failed, ID is missing! (${this.dataParams.dataName})`)
755
+ ),
756
+
757
+ errorCode: 'NTS-DS0-DD1',
758
+ });
759
+ }
760
+
761
+ await this.dataDBService.deleteDataById(this.data._id);
762
+ } catch (error) {
763
+ if (error?.errorCode == 'NTS-DS0-DD1') {
764
+ throw error;
765
+ } else {
766
+ throw new DynamoFM_Error({
767
+ ...this._getDefaultErrorSettings('deleteData', error),
768
+
769
+ errorCode: 'NTS-DS0-DD0',
770
+ });
771
+ }
772
+ }
773
+ }
774
+
775
+ /**
776
+ * validation of data, for modify and create, by the ModelParams
777
+ */
778
+ async validateForSave(): Promise<void> {
779
+ try {
780
+ for (let i = 0; i < this.dataParams.properties.length; i++) {
781
+ // basic required validations
782
+ if (
783
+ (this.dataParams.properties[i].required &&
784
+ (this.data[this.dataParams.properties[i].key] === null ||
785
+ this.data[this.dataParams.properties[i].key] === undefined
786
+ )
787
+ ) ||
788
+ (this.dataParams.properties[i].index &&
789
+ (this.data[this.dataParams.properties[i].key] === null ||
790
+ this.data[this.dataParams.properties[i].key] === undefined
791
+ )
792
+ )
793
+ ) {
794
+ throw new DynamoFM_Error({
795
+ ...this._getDefaultErrorSettings(
796
+ 'validateForSave',
797
+ new Error(
798
+ `validateForSave failed, ${this.dataParams.properties[i].key} is missing! ` +
799
+ `(${this.dataParams.dataName})`
800
+ )
801
+ ),
802
+
803
+ status: 422,
804
+ errorCode: 'NTS-DS0-VD1',
805
+ userMessage: this.defaultValidationErrorUserMsg,
806
+ });
807
+ }
808
+
809
+ // specific Date validation
810
+ if (this.dataParams.properties[i].type === 'Date' &&
811
+ !(new Date(this.data[this.dataParams.properties[i].key]) instanceof Date)
812
+ ) {
813
+ throw new DynamoFM_Error({
814
+ ...this._getDefaultErrorSettings(
815
+ 'validateForSave',
816
+ new Error(
817
+ `validateForSave failed, ${this.dataParams.properties[i].key} is not a date! ` +
818
+ `(${this.dataParams.dataName})`
819
+ )
820
+ ),
821
+
822
+ status: 422,
823
+ errorCode: 'NTS-DS0-VD2',
824
+ userMessage: this.defaultValidationErrorUserMsg,
825
+ });
826
+ }
827
+
828
+ // call additional validators
829
+ if (this.dataParams.properties[i].additionalValidators) {
830
+ for (let j = 0; j < this.dataParams.properties[i].additionalValidators.length; j++) {
831
+ this.dataParams.properties[i].additionalValidators[j](
832
+ this.data[this.dataParams.properties[i].key]
833
+ );
834
+ }
835
+ }
836
+ }
837
+ } catch (error) {
838
+ if ([ 'NTS-DS0-VD1', 'NTS-DS0-VD2' ].includes(error?.errorCode)) {
839
+ throw error;
840
+ } else {
841
+ throw new DynamoFM_Error({
842
+ ...this._getDefaultErrorSettings('validateForSave', error),
843
+
844
+ status: 422,
845
+ errorCode: 'NTS-DS0-VD0',
846
+ });
847
+ }
848
+ }
849
+ }
850
+
851
+ /**
852
+ * setting up dependency dataHook by DynamoBEDataModelParams
853
+ */
854
+ private lookForDependencyDataSettings(): void {
855
+ const dependencyParam: DynamoFM_DataProperty_Params = this.dataParams.properties.find(
856
+ (modelParams: DynamoFM_DataProperty_Params): boolean => modelParams.isDependencyHook
857
+ );
858
+
859
+ if (dependencyParam) {
860
+ this.depKey = dependencyParam.key;
861
+
862
+ if (dependencyParam.dependencyDataName) {
863
+ this.depDBServiceKey = dependencyParam.dependencyDataName;
864
+ }
865
+
866
+ if (dependencyParam.unique) {
867
+ this.depKeyIsUnique = true;
868
+ }
869
+
870
+ if (dependencyParam.required) {
871
+ this.depKeyIsRequired = true;
872
+ }
873
+ }
874
+ }
875
+
876
+ /**
877
+ *
878
+ * @returns
879
+ */
880
+ getDependencyDataDBService(): DynamoNTS_DBService<any> {
881
+ if (!this.depDBServiceKey) {
882
+ throw new DynamoFM_Error({
883
+ ...this._getDefaultErrorSettings(
884
+ 'getDependencyDataDBService',
885
+ new Error(
886
+ `getDependencyDataDBService was unsuccessful, service key not setted up! ` +
887
+ `(${this.dataParams.dataName}))`
888
+ )
889
+ ),
890
+
891
+ status: 501,
892
+ errorCode: 'NTS-DS0-GDDB0',
893
+ });
894
+ }
895
+
896
+ if (this.depDataDBService) {
897
+ return this.depDataDBService;
898
+ } else {
899
+ this.depDataDBService = DynamoNTS_GlobalService.getDBServiceByKey(this.depDBServiceKey);
900
+
901
+ return this.depDataDBService;
902
+ }
903
+ }
904
+
905
+ private _getDefaultErrorSettings(
906
+ fnName: string,
907
+ error: DynamoFM_AnyError
908
+ ): DynamoFM_Error_Settings {
909
+ return {
910
+ status: (error as DynamoFM_Error)?.___status ?? 500,
911
+ message:
912
+ (error as Error)?.message ??
913
+ `${fnName} was UNSUCCESFUL (NTS; ${this.dataParams.dataName})`,
914
+ addECToUserMsg: !(error as DynamoFM_Error)?.__userMessage,
915
+ userMessage: (error as DynamoFM_Error)?.__userMessage ?? this.defaultErrorUserMsg,
916
+ issuer: this.issuer,
917
+ issuerService: this.serviceName + ` (${this?.constructor?.name}-DynamoNTS_DataService)`,
918
+ error: error,
919
+ };
920
+ }
921
+ }