@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,520 +1,520 @@
1
-
2
- import * as SocketIO from 'socket.io';
3
- import * as Http from 'http';
4
-
5
- import { DynamoFM_Array, DynamoFM_Error, DynamoFM_Log, second, DynamoFM_wait } from '@futdevpro/fsm-dynamo';
6
-
7
- import { DynamoNTS_App } from './app.server';
8
- import { DynamoNTS_RouteSecurity } from '../../_enums/route-security.enum';
9
- import { DynamoNTS_SocketServerService } from '../socket/socket-server.service';
10
- import { DynamoNTS_SocketSecurity } from '../../_enums/socket-security.enum';
11
- import {
12
- DynamoNTS_AppExtSysControls
13
- } from '../../_models/control-models/app-ext-system-controls.control-model';
14
-
15
- /**
16
- * This will be the MAIN service of our server project,
17
- * follow the types and type instructions while setting up your project
18
- *
19
- * In this service, there are abstract functions that you will need to implement,
20
- * where you need to set up the main params for your application.
21
- *
22
- * The extended App is containing socket server tools
23
- *
24
- * You need to add socketService definitions to setupRoutingModules
25
- *
26
- * @example
27
- * export class App extends DynamoNTS_AppExtended {
28
- *
29
- * ...
30
- *
31
- * // Setting up App params, and preparing project global settings
32
- * setupAppParams(): void {
33
- * this.params = new DynamoNTS_AppParams({
34
- * name: 'Warbots Server',
35
- * title: warbotsTitleLog,
36
- * version: version,
37
- * dbName: 'warbots',
38
- * });
39
- *
40
- * // dynamoNTS_GlobalSettings.logRequestsContent = false;
41
- * }
42
- *
43
- * ...
44
- *
45
- * // Setting up DBServices
46
- * setGlobalServiceCollection(): void {
47
- * DynamoNTS_GlobalService.setServices({
48
- * authService: AuthService.getInstance(),
49
- * emailServiceCollection: EmailServiceCollectionService.getInstance(),
50
- * dbModels: [
51
- * userModelParams,
52
- * userDataModelParams,
53
- * userOptionsModelParams,
54
- * userStatisticsModelParams,
55
- * userAchievementsModelParams,
56
- * userNotificationsModelParams,
57
- *
58
- * matchStatisticsModelParams,
59
- * matchDataModelParams,
60
-
61
- * DynamoFM_usageSessionModel_params,
62
- * DynamoFM_customDataModel_params,
63
- * ]
64
- * });
65
- * }
66
- *
67
- * ...
68
- *
69
- * // Setting up Routes
70
- * setupRoutingModules(): void {
71
- * this.httpPort = env.port;
72
-
73
- * this.routingModules = [
74
- * new DynamoNTS_RoutingModule({
75
- * route: '/user',
76
- * controllers: [
77
- * UserController.getInstance(),
78
- * UserDataController.getInstance(),
79
- * UserOptionsController.getInstance(),
80
- * UserStatisticsController.getInstance(),
81
- * UserAchievementsController.getInstance(),
82
- * UserNotificationsController.getInstance()
83
- * ]
84
- * }),
85
- * new DynamoNTS_RoutingModule({
86
- * route: '/match',
87
- * controllers: [
88
- * MatchController.getInstance(),
89
- * MatchDistributionController.getInstance(),
90
- * MatchStatisticsController.getInstance(),
91
- * ]
92
- * }),
93
- * new DynamoNTS_RoutingModule({
94
- * route: '/server',
95
- * controllers: [
96
- * ServerController.getInstance(),
97
- * ]
98
- * }),
99
-
100
- * getTestRoutingModule(),
101
- * getUsageRoutingModule()
102
- * ];
103
- *
104
- * ...
105
- *
106
- * // Setting up Sockets
107
- * this.socketServices = [
108
- * NotificationService.getInstance(),
109
- * ChatService.getInstance(),
110
- * ...
111
- * ];
112
- * }
113
- * }
114
- */
115
- export abstract class DynamoNTS_AppExtended extends DynamoNTS_App {
116
-
117
- private systemControlsExt: DynamoNTS_AppExtSysControls = new DynamoNTS_AppExtSysControls();
118
- override get started(): boolean { return this.systemControlsExt.appExtended.started; }
119
- private httpsSocketSettingUpCount: number = 0;
120
- private httpSocketSettingUpCount: number = 0;
121
-
122
- private socketSecurity: DynamoNTS_RouteSecurity;
123
-
124
- private httpSocketServer: Http.Server;
125
-
126
- /**
127
- * @example
128
- * // Setting up Sockets
129
- * this.socketServices = [
130
- * NotificationService.getInstance(),
131
- * ChatService.getInstance(),
132
- * ...
133
- * ];
134
- */
135
- protected socketServices: DynamoNTS_SocketServerService<any>[];
136
- private allSocketServers: SocketIO.Server[] = [];
137
-
138
- constructor(){
139
- super(true);
140
-
141
- this.asyncConstructExt().catch((error: any): void => {
142
- DynamoFM_Log.H_error(
143
- `\nExtended Application: ${this.params?.name} start failed.` +
144
- `\n`, error,
145
- '\n'
146
- );
147
- });
148
- }
149
-
150
- private async asyncConstructExt(): Promise<void> {
151
- if (this.logFn && this.deepLog) console.log('\nfn:. asyncConstruct-extended');
152
- try {
153
- this.systemControlsExt.appExtended.init = true;
154
-
155
- this.socketServices = this.getSocketServices();
156
-
157
- if (this.socketServices?.length) {
158
- this.setSocketSecurity();
159
-
160
- await this.setupSocketServerServices();
161
-
162
- if (this.logSetup) console.log(
163
- `\nAll sockets setted up.... sockets using security: ${this.socketSecurity}`
164
- );
165
- } else {
166
- DynamoFM_Log.testWarn(
167
- 'No socketServices setted up while using Extended Application.',
168
- '\nYou should use DynamoNTS_App if you don`t need socket services.'
169
- );
170
- }
171
-
172
- await this.ready();
173
-
174
- if (this.params.title) {
175
- console.log(this.params.title);
176
- console.log(`Version: ${this.params.version}`);
177
- }
178
- DynamoFM_Log.H_success(`${this.params.name} started successfully.`);
179
-
180
- } catch (error) {
181
- DynamoFM_Log.H_error(
182
- `\nExtended Application: ${this.params?.name} start failed.` +
183
- `\n`, error,
184
- '\n'
185
- );
186
-
187
- throw new DynamoFM_Error({
188
- errorCode: 'NTS-AES-001',
189
- error: error,
190
- additionalContent: {
191
- constructErrors: this.constructErrors,
192
- systemControls: this.systemControls,
193
- systemControlsExt: this.systemControlsExt,
194
- systemReadies: {
195
- app: this.systemControls.app.getReady(),
196
- appExtended: this.systemControlsExt.appExtended.getReady(),
197
- mongoose: this.systemControls.mongoose.getReady(),
198
- httpServer: this.systemControls.httpServer.getReady(),
199
- httpsServer: this.systemControls.httpsServer.getReady(),
200
- httpSocketServer: this.systemControlsExt.httpSocketServer.getReady(),
201
- httpsSocketServer: this.systemControlsExt.httpsSocketServer.getReady(),
202
- },
203
- },
204
- });
205
- }
206
- }
207
-
208
- override async ready(timeout: number = 4 * second): Promise<void> {
209
- if (this.logFn) console.log('\nfn:. ready-extended');
210
- await super.ready(timeout);
211
-
212
- let ready: boolean = false;
213
- const start: number = +new Date();
214
-
215
- if (this.constructErrors.length) {
216
- DynamoFM_Log.H_error(
217
- `Extended Application: ${this.params?.name} start failed. ERRORS`,
218
- this.constructErrors,
219
- '\n'
220
- );
221
-
222
- throw new DynamoFM_Error({
223
- message: `${this.params?.name} start failed. ERRORS`,
224
- additionalContent: this.constructErrors,
225
- error: this.constructErrors?.[0] ?? new Error()
226
- });
227
- }
228
-
229
- while (!ready && +new Date() - start < timeout) {
230
- if (this.systemControlsExt.appExtended.init) {
231
- ready = (
232
- this.superStarted &&
233
- this.systemControlsExt.httpSocketServer.getReady() &&
234
- this.systemControlsExt.httpsSocketServer.getReady()
235
- );
236
- } else {
237
- DynamoFM_Log.error(`${this.params.name} APP NOT INITIALIZED while trying to get ready.`);
238
- }
239
-
240
- if (!ready) {
241
- await DynamoFM_wait(100);
242
- }
243
- }
244
-
245
- if (this.constructErrors.length) {
246
- DynamoFM_Log.H_error(
247
- `Extended Application: ${this.params?.name} start failed. TIMEOUT`,
248
- this.constructErrors,
249
- '\n'
250
- );
251
-
252
- throw new DynamoFM_Error({
253
- message: `${this.params?.name} start failed. TIMEOUT`,
254
- additionalContent: this.constructErrors,
255
- error: this.constructErrors?.[0] ?? new Error()
256
- });
257
- }
258
-
259
- if (ready) {
260
- this.systemControlsExt.appExtended.started = true;
261
-
262
- if (this.logFn && this.deepLog) console.log('\nfn:. ready-extended: return');
263
-
264
- return;
265
- } else {
266
- this.systemControlsExt.appExtended.started = false;
267
-
268
- let msg: string = `${this.params?.name} start failed. UNKNOWN`;
269
-
270
- if (
271
- this.systemControlsExt.httpSocketServer.init &&
272
- !this.systemControlsExt.httpSocketServer.started
273
- ) {
274
- msg += '\nhttpSocketServer start failed.';
275
- }
276
-
277
- if (
278
- this.systemControlsExt.httpsSocketServer.init &&
279
- !this.systemControlsExt.httpsSocketServer.started
280
- ) {
281
- msg += '\nhttpsSocketServer start failed.';
282
- }
283
-
284
- DynamoFM_Log.error(msg, this.constructErrors, '\n');
285
-
286
- throw new DynamoFM_Error({
287
- errorCode: 'NTS-AES-110',
288
- message: msg,
289
- additionalContent: {
290
- constructErrors: this.constructErrors,
291
- systemControls: this.systemControls,
292
- systemControlsExt: this.systemControlsExt,
293
- systemReadies: {
294
- app: this.systemControls.app.getReady(),
295
- appExtended: this.systemControlsExt.appExtended.getReady(),
296
- mongoose: this.systemControls.mongoose.getReady(),
297
- httpServer: this.systemControls.httpServer.getReady(),
298
- httpsServer: this.systemControls.httpsServer.getReady(),
299
- httpSocketServer: this.systemControlsExt.httpSocketServer.getReady(),
300
- httpsSocketServer: this.systemControlsExt.httpsSocketServer.getReady(),
301
- },
302
- },
303
- error: this.constructErrors?.[0] ?? new Error()
304
- });
305
- }
306
- }
307
-
308
- override async stop(): Promise<void> {
309
- if (this.logFn) console.log('\nfn:. stop-extended');
310
-
311
- if (this.started) {
312
- await super.stop(true);
313
-
314
- this.systemControlsExt.httpSocketServer.started = false;
315
- this.systemControlsExt.httpsSocketServer.started = false;
316
- await DynamoFM_Array.asyncForEach(
317
- this.allSocketServers,
318
- async (socketServer: SocketIO.Server): Promise<void> => {
319
- await new Promise<void>((resolve, reject): void => {
320
- socketServer.disconnectSockets(true);
321
- socketServer.close((err): void => {
322
- if (err) {
323
- DynamoFM_Log.error(`\nHTTP socket server close error`, err);
324
- reject(
325
- new DynamoFM_Error({
326
- errorCode: 'NTS-AES-120',
327
- message: `SocketServer close failed.`,
328
- error: err
329
- })
330
- );
331
- } else {
332
- resolve();
333
- }
334
- });
335
- });
336
- }
337
- );
338
- this.systemControlsExt.httpSocketServer.init = false;
339
- this.systemControlsExt.httpsSocketServer.init = false;
340
-
341
- DynamoFM_Log.H_info(`${this.params.name} stopped successfully.`);
342
- }
343
- }
344
-
345
- /**
346
- *
347
- */
348
- private setSocketSecurity(): void {
349
- if (this.logFn) console.log('\nfn:. setSocketSecurity');
350
- this.socketServices.forEach((service: DynamoNTS_SocketServerService<any>): void => {
351
- if (!this.socketSecurity) {
352
- this.socketSecurity = DynamoNTS_RouteSecurity[service.security];
353
- } else if (
354
- this.socketSecurity !== DynamoNTS_RouteSecurity.both &&
355
- this.socketSecurity !== DynamoNTS_RouteSecurity[service.security]
356
- ) {
357
- this.socketSecurity = DynamoNTS_RouteSecurity.both;
358
- }
359
- });
360
- }
361
-
362
- /**
363
- *
364
- */
365
- private async setupSocketServerServices(): Promise<void> {
366
- try {
367
- if (this.logFn) console.log('\nfn:. setupSocketServerServices');
368
- /* let httpServer: Http.Server; */
369
-
370
- if (this.socketSecurity !== DynamoNTS_RouteSecurity.secure) {
371
- if (!this.openExpress) {
372
- await this.initOpenExpress();
373
- }
374
-
375
- if (!this.httpSocketServer) {
376
- this.httpSocketServer = Http.createServer(this.openExpress);
377
- }
378
- }
379
-
380
- if (this.socketSecurity !== DynamoNTS_RouteSecurity.open) {
381
- if (!this.httpsServer) {
382
- if (this.cert) {
383
- await this.initSecureExpress();
384
- } else {
385
- let errorMsg: string =
386
- `\nYou have secure socket service, but the certification paths are not set!` +
387
- `\nset...` +
388
- `\n cert: {` +
389
- `\n keyPath: FileSystem.PathLike,` +
390
- `\n certPath: FileSystem.PathLike,` +
391
- `\n }` +
392
- `\nin DynamoBEServer - setupRoutingModules() to enable secure routes.`;
393
-
394
- errorMsg += '\n\nThe socket services setted to use secure server:';
395
- this.socketServices.forEach((service: DynamoNTS_SocketServerService<any>): void => {
396
- if (service.security != DynamoNTS_SocketSecurity.open) {
397
- errorMsg += `\n ${service?.name} (port: ${service.port})`;
398
- }
399
- });
400
-
401
- const error = new Error('Secure routes cannot be established!');
402
- const errorStack: string[] = error.stack.split('\n');
403
-
404
- errorStack.splice(1, 2);
405
- error.stack = errorStack.join('\n');
406
-
407
- DynamoFM_Log.error(errorMsg);
408
-
409
- throw error;
410
- }
411
- }
412
- }
413
-
414
- await DynamoFM_Array.asyncForEach(
415
- this.socketServices,
416
- async (service: DynamoNTS_SocketServerService<any>): Promise<void> => {
417
- try {
418
- this.systemControlsExt.httpSocketServer.init = true;
419
- const existingPorts: DynamoNTS_SocketServerService<any>[] = this.socketServices.filter(
420
- (mod: DynamoNTS_SocketServerService<any>): boolean => mod.port === service.port
421
- );
422
-
423
- if (
424
- 1 < existingPorts.length ||
425
- this.portSettings.httpPort === service.port ||
426
- this.portSettings.httpsPort === service.port
427
- ) {
428
- const error = new Error(`PORT DUPLICATION: ${service.port}`);
429
- const errorStack: string[] = error.stack.split('\n');
430
-
431
- errorStack.splice(1, 4);
432
- error.stack = errorStack.join('\n');
433
-
434
- DynamoFM_Log.error(`\n${error.message}`);
435
-
436
- throw error;
437
- }
438
-
439
- if (service.security === DynamoNTS_SocketSecurity.open) {
440
- if (this.logSetup) console.log(
441
- `\nsocket setup (open): ${service?.name}:${service.port}`
442
- );
443
- this.httpSocketSettingUpCount++;
444
- this.systemControlsExt.httpSocketServer.started = false;
445
-
446
- this.allSocketServers.push(
447
- await service.setupSocketServer(
448
- new SocketIO.Server(this.httpSocketServer),
449
- DynamoNTS_SocketSecurity.open,
450
- (): void => {
451
- this.httpSocketSettingUpCount--;
452
-
453
- if (this.httpSocketSettingUpCount === 0) {
454
- this.systemControlsExt.httpSocketServer.started = true;
455
- }
456
- }
457
- )
458
- );
459
-
460
- } else if (service.security === DynamoNTS_SocketSecurity.secure) {
461
- if (this.logSetup) console.log(
462
- `\nsocket setup (secure): ${service?.name}:${service.port}`
463
- );
464
- this.httpsSocketSettingUpCount++;
465
- this.systemControlsExt.httpsSocketServer.started = false;
466
-
467
- this.allSocketServers.push(
468
- await service.setupSocketServer(
469
- new SocketIO.Server(this.httpsServer),
470
- DynamoNTS_SocketSecurity.secure,
471
- (): void => {
472
- this.httpsSocketSettingUpCount--;
473
-
474
- if (this.httpsSocketSettingUpCount === 0) {
475
- this.systemControlsExt.httpsSocketServer.started = true;
476
- }
477
- }
478
- )
479
- );
480
-
481
- } else {
482
- const error = new Error(
483
- `INVALID Socket Service security: ${service.security} on ${service?.name}`
484
- );
485
- const errorStack: string[] = error.stack.split('\n');
486
-
487
- errorStack.splice(1, 4);
488
- error.stack = errorStack.join('\n');
489
-
490
- DynamoFM_Log.error(`\n${error.message}`);
491
-
492
- throw error;
493
- }
494
- } catch (error) {
495
- DynamoFM_Log.error(
496
- `\nSocket Server service setup failed. (${service?.name})\n`,
497
- error,
498
- '\n'
499
- );
500
-
501
- throw error;
502
- }
503
- }
504
- );
505
- } catch (error) {
506
- DynamoFM_Log.error(
507
- `\nSocket Server services setup failed. (${this.socketServices?.length} services)\n`,
508
- error,
509
- '\n'
510
- );
511
-
512
- throw error;
513
- }
514
- }
515
-
516
- /**
517
- * MISSING Description (TODO)
518
- */
519
- abstract getSocketServices(): DynamoNTS_SocketServerService<any>[];
520
- }
1
+
2
+ import * as SocketIO from 'socket.io';
3
+ import * as Http from 'http';
4
+
5
+ import { DynamoFM_Array, DynamoFM_Error, DynamoFM_Log, second, DynamoFM_wait } from '@futdevpro/fsm-dynamo';
6
+
7
+ import { DynamoNTS_App } from './app.server';
8
+ import { DynamoNTS_RouteSecurity } from '../../_enums/route-security.enum';
9
+ import { DynamoNTS_SocketServerService } from '../socket/socket-server.service';
10
+ import { DynamoNTS_SocketSecurity } from '../../_enums/socket-security.enum';
11
+ import {
12
+ DynamoNTS_AppExtSysControls
13
+ } from '../../_models/control-models/app-ext-system-controls.control-model';
14
+
15
+ /**
16
+ * This will be the MAIN service of our server project,
17
+ * follow the types and type instructions while setting up your project
18
+ *
19
+ * In this service, there are abstract functions that you will need to implement,
20
+ * where you need to set up the main params for your application.
21
+ *
22
+ * The extended App is containing socket server tools
23
+ *
24
+ * You need to add socketService definitions to setupRoutingModules
25
+ *
26
+ * @example
27
+ * export class App extends DynamoNTS_AppExtended {
28
+ *
29
+ * ...
30
+ *
31
+ * // Setting up App params, and preparing project global settings
32
+ * setupAppParams(): void {
33
+ * this.params = new DynamoNTS_AppParams({
34
+ * name: 'Warbots Server',
35
+ * title: warbotsTitleLog,
36
+ * version: version,
37
+ * dbName: 'warbots',
38
+ * });
39
+ *
40
+ * // dynamoNTS_GlobalSettings.logRequestsContent = false;
41
+ * }
42
+ *
43
+ * ...
44
+ *
45
+ * // Setting up DBServices
46
+ * setGlobalServiceCollection(): void {
47
+ * DynamoNTS_GlobalService.setServices({
48
+ * authService: AuthService.getInstance(),
49
+ * emailServiceCollection: EmailServiceCollectionService.getInstance(),
50
+ * dbModels: [
51
+ * userModelParams,
52
+ * userDataModelParams,
53
+ * userOptionsModelParams,
54
+ * userStatisticsModelParams,
55
+ * userAchievementsModelParams,
56
+ * userNotificationsModelParams,
57
+ *
58
+ * matchStatisticsModelParams,
59
+ * matchDataModelParams,
60
+
61
+ * DynamoFM_usageSessionModel_params,
62
+ * DynamoFM_customDataModel_params,
63
+ * ]
64
+ * });
65
+ * }
66
+ *
67
+ * ...
68
+ *
69
+ * // Setting up Routes
70
+ * setupRoutingModules(): void {
71
+ * this.httpPort = env.port;
72
+
73
+ * this.routingModules = [
74
+ * new DynamoNTS_RoutingModule({
75
+ * route: '/user',
76
+ * controllers: [
77
+ * UserController.getInstance(),
78
+ * UserDataController.getInstance(),
79
+ * UserOptionsController.getInstance(),
80
+ * UserStatisticsController.getInstance(),
81
+ * UserAchievementsController.getInstance(),
82
+ * UserNotificationsController.getInstance()
83
+ * ]
84
+ * }),
85
+ * new DynamoNTS_RoutingModule({
86
+ * route: '/match',
87
+ * controllers: [
88
+ * MatchController.getInstance(),
89
+ * MatchDistributionController.getInstance(),
90
+ * MatchStatisticsController.getInstance(),
91
+ * ]
92
+ * }),
93
+ * new DynamoNTS_RoutingModule({
94
+ * route: '/server',
95
+ * controllers: [
96
+ * ServerController.getInstance(),
97
+ * ]
98
+ * }),
99
+
100
+ * getTestRoutingModule(),
101
+ * getUsageRoutingModule()
102
+ * ];
103
+ *
104
+ * ...
105
+ *
106
+ * // Setting up Sockets
107
+ * this.socketServices = [
108
+ * NotificationService.getInstance(),
109
+ * ChatService.getInstance(),
110
+ * ...
111
+ * ];
112
+ * }
113
+ * }
114
+ */
115
+ export abstract class DynamoNTS_AppExtended extends DynamoNTS_App {
116
+
117
+ private systemControlsExt: DynamoNTS_AppExtSysControls = new DynamoNTS_AppExtSysControls();
118
+ override get started(): boolean { return this.systemControlsExt.appExtended.started; }
119
+ private httpsSocketSettingUpCount: number = 0;
120
+ private httpSocketSettingUpCount: number = 0;
121
+
122
+ private socketSecurity: DynamoNTS_RouteSecurity;
123
+
124
+ private httpSocketServer: Http.Server;
125
+
126
+ /**
127
+ * @example
128
+ * // Setting up Sockets
129
+ * this.socketServices = [
130
+ * NotificationService.getInstance(),
131
+ * ChatService.getInstance(),
132
+ * ...
133
+ * ];
134
+ */
135
+ protected socketServices: DynamoNTS_SocketServerService<any>[];
136
+ private allSocketServers: SocketIO.Server[] = [];
137
+
138
+ constructor(){
139
+ super(true);
140
+
141
+ this.asyncConstructExt().catch((error: any): void => {
142
+ DynamoFM_Log.H_error(
143
+ `\nExtended Application: ${this.params?.name} start failed.` +
144
+ `\n`, error,
145
+ '\n'
146
+ );
147
+ });
148
+ }
149
+
150
+ private async asyncConstructExt(): Promise<void> {
151
+ if (this.logFn && this.deepLog) console.log('\nfn:. asyncConstruct-extended');
152
+ try {
153
+ this.systemControlsExt.appExtended.init = true;
154
+
155
+ this.socketServices = this.getSocketServices();
156
+
157
+ if (this.socketServices?.length) {
158
+ this.setSocketSecurity();
159
+
160
+ await this.setupSocketServerServices();
161
+
162
+ if (this.logSetup) console.log(
163
+ `\nAll sockets setted up.... sockets using security: ${this.socketSecurity}`
164
+ );
165
+ } else {
166
+ DynamoFM_Log.testWarn(
167
+ 'No socketServices setted up while using Extended Application.',
168
+ '\nYou should use DynamoNTS_App if you don`t need socket services.'
169
+ );
170
+ }
171
+
172
+ await this.ready();
173
+
174
+ if (this.params.title) {
175
+ console.log(this.params.title);
176
+ console.log(`Version: ${this.params.version}`);
177
+ }
178
+ DynamoFM_Log.H_success(`${this.params.name} started successfully.`);
179
+
180
+ } catch (error) {
181
+ DynamoFM_Log.H_error(
182
+ `\nExtended Application: ${this.params?.name} start failed.` +
183
+ `\n`, error,
184
+ '\n'
185
+ );
186
+
187
+ throw new DynamoFM_Error({
188
+ errorCode: 'NTS-AES-001',
189
+ error: error,
190
+ additionalContent: {
191
+ constructErrors: this.constructErrors,
192
+ systemControls: this.systemControls,
193
+ systemControlsExt: this.systemControlsExt,
194
+ systemReadies: {
195
+ app: this.systemControls.app.getReady(),
196
+ appExtended: this.systemControlsExt.appExtended.getReady(),
197
+ mongoose: this.systemControls.mongoose.getReady(),
198
+ httpServer: this.systemControls.httpServer.getReady(),
199
+ httpsServer: this.systemControls.httpsServer.getReady(),
200
+ httpSocketServer: this.systemControlsExt.httpSocketServer.getReady(),
201
+ httpsSocketServer: this.systemControlsExt.httpsSocketServer.getReady(),
202
+ },
203
+ },
204
+ });
205
+ }
206
+ }
207
+
208
+ override async ready(timeout: number = 4 * second): Promise<void> {
209
+ if (this.logFn) console.log('\nfn:. ready-extended');
210
+ await super.ready(timeout);
211
+
212
+ let ready: boolean = false;
213
+ const start: number = +new Date();
214
+
215
+ if (this.constructErrors.length) {
216
+ DynamoFM_Log.H_error(
217
+ `Extended Application: ${this.params?.name} start failed. ERRORS`,
218
+ this.constructErrors,
219
+ '\n'
220
+ );
221
+
222
+ throw new DynamoFM_Error({
223
+ message: `${this.params?.name} start failed. ERRORS`,
224
+ additionalContent: this.constructErrors,
225
+ error: this.constructErrors?.[0] ?? new Error()
226
+ });
227
+ }
228
+
229
+ while (!ready && +new Date() - start < timeout) {
230
+ if (this.systemControlsExt.appExtended.init) {
231
+ ready = (
232
+ this.superStarted &&
233
+ this.systemControlsExt.httpSocketServer.getReady() &&
234
+ this.systemControlsExt.httpsSocketServer.getReady()
235
+ );
236
+ } else {
237
+ DynamoFM_Log.error(`${this.params.name} APP NOT INITIALIZED while trying to get ready.`);
238
+ }
239
+
240
+ if (!ready) {
241
+ await DynamoFM_wait(100);
242
+ }
243
+ }
244
+
245
+ if (this.constructErrors.length) {
246
+ DynamoFM_Log.H_error(
247
+ `Extended Application: ${this.params?.name} start failed. TIMEOUT`,
248
+ this.constructErrors,
249
+ '\n'
250
+ );
251
+
252
+ throw new DynamoFM_Error({
253
+ message: `${this.params?.name} start failed. TIMEOUT`,
254
+ additionalContent: this.constructErrors,
255
+ error: this.constructErrors?.[0] ?? new Error()
256
+ });
257
+ }
258
+
259
+ if (ready) {
260
+ this.systemControlsExt.appExtended.started = true;
261
+
262
+ if (this.logFn && this.deepLog) console.log('\nfn:. ready-extended: return');
263
+
264
+ return;
265
+ } else {
266
+ this.systemControlsExt.appExtended.started = false;
267
+
268
+ let msg: string = `${this.params?.name} start failed. UNKNOWN`;
269
+
270
+ if (
271
+ this.systemControlsExt.httpSocketServer.init &&
272
+ !this.systemControlsExt.httpSocketServer.started
273
+ ) {
274
+ msg += '\nhttpSocketServer start failed.';
275
+ }
276
+
277
+ if (
278
+ this.systemControlsExt.httpsSocketServer.init &&
279
+ !this.systemControlsExt.httpsSocketServer.started
280
+ ) {
281
+ msg += '\nhttpsSocketServer start failed.';
282
+ }
283
+
284
+ DynamoFM_Log.error(msg, this.constructErrors, '\n');
285
+
286
+ throw new DynamoFM_Error({
287
+ errorCode: 'NTS-AES-110',
288
+ message: msg,
289
+ additionalContent: {
290
+ constructErrors: this.constructErrors,
291
+ systemControls: this.systemControls,
292
+ systemControlsExt: this.systemControlsExt,
293
+ systemReadies: {
294
+ app: this.systemControls.app.getReady(),
295
+ appExtended: this.systemControlsExt.appExtended.getReady(),
296
+ mongoose: this.systemControls.mongoose.getReady(),
297
+ httpServer: this.systemControls.httpServer.getReady(),
298
+ httpsServer: this.systemControls.httpsServer.getReady(),
299
+ httpSocketServer: this.systemControlsExt.httpSocketServer.getReady(),
300
+ httpsSocketServer: this.systemControlsExt.httpsSocketServer.getReady(),
301
+ },
302
+ },
303
+ error: this.constructErrors?.[0] ?? new Error()
304
+ });
305
+ }
306
+ }
307
+
308
+ override async stop(): Promise<void> {
309
+ if (this.logFn) console.log('\nfn:. stop-extended');
310
+
311
+ if (this.started) {
312
+ await super.stop(true);
313
+
314
+ this.systemControlsExt.httpSocketServer.started = false;
315
+ this.systemControlsExt.httpsSocketServer.started = false;
316
+ await DynamoFM_Array.asyncForEach(
317
+ this.allSocketServers,
318
+ async (socketServer: SocketIO.Server): Promise<void> => {
319
+ await new Promise<void>((resolve, reject): void => {
320
+ socketServer.disconnectSockets(true);
321
+ socketServer.close((err): void => {
322
+ if (err) {
323
+ DynamoFM_Log.error(`\nHTTP socket server close error`, err);
324
+ reject(
325
+ new DynamoFM_Error({
326
+ errorCode: 'NTS-AES-120',
327
+ message: `SocketServer close failed.`,
328
+ error: err
329
+ })
330
+ );
331
+ } else {
332
+ resolve();
333
+ }
334
+ });
335
+ });
336
+ }
337
+ );
338
+ this.systemControlsExt.httpSocketServer.init = false;
339
+ this.systemControlsExt.httpsSocketServer.init = false;
340
+
341
+ DynamoFM_Log.H_info(`${this.params.name} stopped successfully.`);
342
+ }
343
+ }
344
+
345
+ /**
346
+ *
347
+ */
348
+ private setSocketSecurity(): void {
349
+ if (this.logFn) console.log('\nfn:. setSocketSecurity');
350
+ this.socketServices.forEach((service: DynamoNTS_SocketServerService<any>): void => {
351
+ if (!this.socketSecurity) {
352
+ this.socketSecurity = DynamoNTS_RouteSecurity[service.security];
353
+ } else if (
354
+ this.socketSecurity !== DynamoNTS_RouteSecurity.both &&
355
+ this.socketSecurity !== DynamoNTS_RouteSecurity[service.security]
356
+ ) {
357
+ this.socketSecurity = DynamoNTS_RouteSecurity.both;
358
+ }
359
+ });
360
+ }
361
+
362
+ /**
363
+ *
364
+ */
365
+ private async setupSocketServerServices(): Promise<void> {
366
+ try {
367
+ if (this.logFn) console.log('\nfn:. setupSocketServerServices');
368
+ /* let httpServer: Http.Server; */
369
+
370
+ if (this.socketSecurity !== DynamoNTS_RouteSecurity.secure) {
371
+ if (!this.openExpress) {
372
+ await this.initOpenExpress();
373
+ }
374
+
375
+ if (!this.httpSocketServer) {
376
+ this.httpSocketServer = Http.createServer(this.openExpress);
377
+ }
378
+ }
379
+
380
+ if (this.socketSecurity !== DynamoNTS_RouteSecurity.open) {
381
+ if (!this.httpsServer) {
382
+ if (this.cert) {
383
+ await this.initSecureExpress();
384
+ } else {
385
+ let errorMsg: string =
386
+ `\nYou have secure socket service, but the certification paths are not set!` +
387
+ `\nset...` +
388
+ `\n cert: {` +
389
+ `\n keyPath: FileSystem.PathLike,` +
390
+ `\n certPath: FileSystem.PathLike,` +
391
+ `\n }` +
392
+ `\nin DynamoBEServer - setupRoutingModules() to enable secure routes.`;
393
+
394
+ errorMsg += '\n\nThe socket services setted to use secure server:';
395
+ this.socketServices.forEach((service: DynamoNTS_SocketServerService<any>): void => {
396
+ if (service.security != DynamoNTS_SocketSecurity.open) {
397
+ errorMsg += `\n ${service?.name} (port: ${service.port})`;
398
+ }
399
+ });
400
+
401
+ const error = new Error('Secure routes cannot be established!');
402
+ const errorStack: string[] = error.stack.split('\n');
403
+
404
+ errorStack.splice(1, 2);
405
+ error.stack = errorStack.join('\n');
406
+
407
+ DynamoFM_Log.error(errorMsg);
408
+
409
+ throw error;
410
+ }
411
+ }
412
+ }
413
+
414
+ await DynamoFM_Array.asyncForEach(
415
+ this.socketServices,
416
+ async (service: DynamoNTS_SocketServerService<any>): Promise<void> => {
417
+ try {
418
+ this.systemControlsExt.httpSocketServer.init = true;
419
+ const existingPorts: DynamoNTS_SocketServerService<any>[] = this.socketServices.filter(
420
+ (mod: DynamoNTS_SocketServerService<any>): boolean => mod.port === service.port
421
+ );
422
+
423
+ if (
424
+ 1 < existingPorts.length ||
425
+ this.portSettings.httpPort === service.port ||
426
+ this.portSettings.httpsPort === service.port
427
+ ) {
428
+ const error = new Error(`PORT DUPLICATION: ${service.port}`);
429
+ const errorStack: string[] = error.stack.split('\n');
430
+
431
+ errorStack.splice(1, 4);
432
+ error.stack = errorStack.join('\n');
433
+
434
+ DynamoFM_Log.error(`\n${error.message}`);
435
+
436
+ throw error;
437
+ }
438
+
439
+ if (service.security === DynamoNTS_SocketSecurity.open) {
440
+ if (this.logSetup) console.log(
441
+ `\nsocket setup (open): ${service?.name}:${service.port}`
442
+ );
443
+ this.httpSocketSettingUpCount++;
444
+ this.systemControlsExt.httpSocketServer.started = false;
445
+
446
+ this.allSocketServers.push(
447
+ await service.setupSocketServer(
448
+ new SocketIO.Server(this.httpSocketServer),
449
+ DynamoNTS_SocketSecurity.open,
450
+ (): void => {
451
+ this.httpSocketSettingUpCount--;
452
+
453
+ if (this.httpSocketSettingUpCount === 0) {
454
+ this.systemControlsExt.httpSocketServer.started = true;
455
+ }
456
+ }
457
+ )
458
+ );
459
+
460
+ } else if (service.security === DynamoNTS_SocketSecurity.secure) {
461
+ if (this.logSetup) console.log(
462
+ `\nsocket setup (secure): ${service?.name}:${service.port}`
463
+ );
464
+ this.httpsSocketSettingUpCount++;
465
+ this.systemControlsExt.httpsSocketServer.started = false;
466
+
467
+ this.allSocketServers.push(
468
+ await service.setupSocketServer(
469
+ new SocketIO.Server(this.httpsServer),
470
+ DynamoNTS_SocketSecurity.secure,
471
+ (): void => {
472
+ this.httpsSocketSettingUpCount--;
473
+
474
+ if (this.httpsSocketSettingUpCount === 0) {
475
+ this.systemControlsExt.httpsSocketServer.started = true;
476
+ }
477
+ }
478
+ )
479
+ );
480
+
481
+ } else {
482
+ const error = new Error(
483
+ `INVALID Socket Service security: ${service.security} on ${service?.name}`
484
+ );
485
+ const errorStack: string[] = error.stack.split('\n');
486
+
487
+ errorStack.splice(1, 4);
488
+ error.stack = errorStack.join('\n');
489
+
490
+ DynamoFM_Log.error(`\n${error.message}`);
491
+
492
+ throw error;
493
+ }
494
+ } catch (error) {
495
+ DynamoFM_Log.error(
496
+ `\nSocket Server service setup failed. (${service?.name})\n`,
497
+ error,
498
+ '\n'
499
+ );
500
+
501
+ throw error;
502
+ }
503
+ }
504
+ );
505
+ } catch (error) {
506
+ DynamoFM_Log.error(
507
+ `\nSocket Server services setup failed. (${this.socketServices?.length} services)\n`,
508
+ error,
509
+ '\n'
510
+ );
511
+
512
+ throw error;
513
+ }
514
+ }
515
+
516
+ /**
517
+ * MISSING Description (TODO)
518
+ */
519
+ abstract getSocketServices(): DynamoNTS_SocketServerService<any>[];
520
+ }