namirasoft-node 1.4.131 → 1.4.133
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BaseApplication.d.ts +16 -12
- package/dist/BaseApplication.js +121 -81
- package/dist/BaseApplication.js.map +1 -1
- package/dist/BaseTable.d.ts +2 -2
- package/dist/BaseTable.js +2 -2
- package/dist/BaseTable.js.map +1 -1
- package/dist/BaseWorker.d.ts +20 -0
- package/dist/BaseWorker.js +18 -0
- package/dist/BaseWorker.js.map +1 -0
- package/package.json +43 -43
- package/src/AnomalyDetector.ts +84 -84
- package/src/BaseApplication.ts +587 -530
- package/src/BaseApplicationLink.ts +6 -6
- package/src/BaseController.ts +226 -226
- package/src/BaseCron.ts +114 -114
- package/src/BaseDatabase.ts +52 -52
- package/src/BaseEmailService.ts +38 -38
- package/src/BaseFilterItemBuilder.ts +191 -191
- package/src/BaseFilterItemBuilderDatabase.ts +32 -32
- package/src/BaseFilterItemBuilderObject.ts +95 -95
- package/src/BaseTable.ts +150 -150
- package/src/BaseTableColumnOptions.ts +8 -8
- package/src/BaseWorker.ts +35 -0
- package/src/CommandOperation.ts +32 -32
- package/src/EncryptionOperation.ts +40 -40
- package/src/GmailService.ts +22 -22
- package/src/IDatabase.ts +12 -12
- package/src/IPOperation.ts +38 -38
- package/src/Meta.ts +36 -36
- package/src/OTPOperation.ts +94 -94
- package/src/RequestHeaderService.ts +27 -27
- package/src/SMTPService.ts +26 -26
- package/src/ServerToServerOperation.ts +23 -23
- package/src/Timer.ts +17 -17
- package/src/Validator.ts +15 -15
- package/src/index.ts +23 -23
package/src/BaseApplication.ts
CHANGED
|
@@ -1,531 +1,588 @@
|
|
|
1
|
-
import cors from "cors";
|
|
2
|
-
import express, { Router } from 'express';
|
|
3
|
-
import * as fs from "fs";
|
|
4
|
-
import * as http from "http";
|
|
5
|
-
import { EnvService, HTTPMethod, ObjectService, PackageService } from 'namirasoft-core';
|
|
6
|
-
import { ILogger } from "namirasoft-log";
|
|
7
|
-
import { ApplicationSchema, BaseVariableSchema, ObjectSchema, SwaggerApplicationBuilder } from 'namirasoft-schema';
|
|
8
|
-
import * as path from 'path';
|
|
9
|
-
import serveIndex from "serve-index";
|
|
10
|
-
import swaggerJSDoc from 'swagger-jsdoc';
|
|
11
|
-
import swaggerUi from 'swagger-ui-express';
|
|
12
|
-
import { BaseApplicationLink } from './BaseApplicationLink';
|
|
13
|
-
import { BaseController } from './BaseController';
|
|
14
|
-
import { BaseCron } from './BaseCron';
|
|
15
|
-
import { BaseDatabase } from './BaseDatabase';
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
{
|
|
20
|
-
|
|
21
|
-
private
|
|
22
|
-
|
|
23
|
-
protected
|
|
24
|
-
protected
|
|
25
|
-
protected
|
|
26
|
-
protected
|
|
27
|
-
protected
|
|
28
|
-
protected
|
|
29
|
-
protected
|
|
30
|
-
protected
|
|
31
|
-
protected
|
|
32
|
-
protected
|
|
33
|
-
protected
|
|
34
|
-
protected
|
|
35
|
-
protected
|
|
36
|
-
protected
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
public
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
this.
|
|
47
|
-
this.
|
|
48
|
-
this.
|
|
49
|
-
this.
|
|
50
|
-
this.
|
|
51
|
-
this.
|
|
52
|
-
this.
|
|
53
|
-
this.
|
|
54
|
-
this.
|
|
55
|
-
this.
|
|
56
|
-
this.
|
|
57
|
-
this.
|
|
58
|
-
this.
|
|
59
|
-
this.
|
|
60
|
-
this.
|
|
61
|
-
this.
|
|
62
|
-
this.
|
|
63
|
-
this.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
this.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (!fs.existsSync(this.
|
|
72
|
-
fs.mkdirSync(this.
|
|
73
|
-
if (!fs.existsSync(this.
|
|
74
|
-
fs.mkdirSync(this.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
protected abstract
|
|
82
|
-
protected abstract
|
|
83
|
-
|
|
84
|
-
protected abstract
|
|
85
|
-
protected
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
let
|
|
120
|
-
|
|
121
|
-
if (
|
|
122
|
-
return
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
this.logger.onCatchCritical(
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
await
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
await
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
await
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
protected async
|
|
236
|
-
{
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
304
|
-
protected
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
{
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
{
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
1
|
+
import cors from "cors";
|
|
2
|
+
import express, { Router } from 'express';
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as http from "http";
|
|
5
|
+
import { EnvService, HTTPMethod, ObjectService, PackageService } from 'namirasoft-core';
|
|
6
|
+
import { ILogger } from "namirasoft-log";
|
|
7
|
+
import { ApplicationSchema, BaseVariableSchema, ObjectSchema, SwaggerApplicationBuilder } from 'namirasoft-schema';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import serveIndex from "serve-index";
|
|
10
|
+
import swaggerJSDoc from 'swagger-jsdoc';
|
|
11
|
+
import swaggerUi from 'swagger-ui-express';
|
|
12
|
+
import { BaseApplicationLink } from './BaseApplicationLink';
|
|
13
|
+
import { BaseController } from './BaseController';
|
|
14
|
+
import { BaseCron } from './BaseCron';
|
|
15
|
+
import { BaseDatabase } from './BaseDatabase';
|
|
16
|
+
import { BaseWorker } from "./BaseWorker";
|
|
17
|
+
import { IDatabase } from './IDatabase';
|
|
18
|
+
|
|
19
|
+
export abstract class BaseApplication<D extends { [name: string]: IDatabase }>
|
|
20
|
+
{
|
|
21
|
+
private linkLoader?: () => Promise<void>;
|
|
22
|
+
private links: BaseApplicationLink[] = [];
|
|
23
|
+
protected name_asset: string;
|
|
24
|
+
protected name_page: string;
|
|
25
|
+
protected base_path: string;
|
|
26
|
+
protected dir_asset: string;
|
|
27
|
+
protected dir_page: string;
|
|
28
|
+
protected dir_swagger: string;
|
|
29
|
+
protected path_asset: string;
|
|
30
|
+
protected path_page: string;
|
|
31
|
+
protected path_swagger: string;
|
|
32
|
+
protected pkg: PackageService;
|
|
33
|
+
protected title: string;
|
|
34
|
+
protected description: string;
|
|
35
|
+
protected logo: string;
|
|
36
|
+
protected version: string;
|
|
37
|
+
protected mode!: string;
|
|
38
|
+
public express!: express.Express;
|
|
39
|
+
private server!: http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
|
|
40
|
+
public databases!: D;
|
|
41
|
+
public logger: ILogger;
|
|
42
|
+
private crons: BaseCron<any>[] = [];
|
|
43
|
+
private workers: BaseWorker<any>[] = [];
|
|
44
|
+
constructor(base_path: string)
|
|
45
|
+
{
|
|
46
|
+
this.base_path = base_path;
|
|
47
|
+
this.name_asset = "asset";
|
|
48
|
+
this.name_page = "page";
|
|
49
|
+
this.dir_asset = "./" + this.name_asset;
|
|
50
|
+
this.dir_page = "./" + this.name_page;
|
|
51
|
+
this.dir_swagger = "./swagger";
|
|
52
|
+
this.path_asset = base_path + "/" + this.name_asset;
|
|
53
|
+
this.path_page = base_path + "/" + this.name_page;
|
|
54
|
+
this.path_swagger = this.path_page + "/swagger";
|
|
55
|
+
this.pkg = PackageService.getMain();
|
|
56
|
+
this.title = this.pkg?.getTitle() ?? "";
|
|
57
|
+
this.description = this.pkg?.getDescription() ?? "";
|
|
58
|
+
this.logo = this.pkg?.getLogo() ?? "";
|
|
59
|
+
this.version = this.pkg?.getVersion() ?? "";
|
|
60
|
+
this.mode = new EnvService("SERVER_MODE", false).getString("api").toLowerCase();
|
|
61
|
+
this.logger = this.getILogger();
|
|
62
|
+
this.addLink = this.addLink.bind(this);
|
|
63
|
+
this.addLink_Asset = this.addLink_Asset.bind(this);
|
|
64
|
+
this.addLink_Page = this.addLink_Page.bind(this);
|
|
65
|
+
this.addLink_Swagger = this.addLink_Swagger.bind(this);
|
|
66
|
+
|
|
67
|
+
// create folders
|
|
68
|
+
this.dir_asset = path.join(path.dirname(this.pkg.getPath()), this.dir_asset);
|
|
69
|
+
this.dir_page = path.join(path.dirname(this.pkg.getPath()), this.dir_page);
|
|
70
|
+
this.dir_swagger = path.join(path.dirname(this.pkg.getPath()), this.dir_swagger);
|
|
71
|
+
if (!fs.existsSync(this.dir_asset))
|
|
72
|
+
fs.mkdirSync(this.dir_asset);
|
|
73
|
+
if (!fs.existsSync(this.dir_page))
|
|
74
|
+
fs.mkdirSync(this.dir_page);
|
|
75
|
+
if (!fs.existsSync(this.dir_swagger))
|
|
76
|
+
fs.mkdirSync(this.dir_swagger, { recursive: true });
|
|
77
|
+
|
|
78
|
+
process.on('SIGTERM', () => this.stop());
|
|
79
|
+
process.on('SIGINT', () => this.stop());
|
|
80
|
+
}
|
|
81
|
+
protected abstract getILogger(): ILogger;
|
|
82
|
+
protected abstract getPort(): number;
|
|
83
|
+
public abstract getDatabases(): D;
|
|
84
|
+
protected abstract getControllers(): any[];
|
|
85
|
+
protected abstract getCrons(): any[];
|
|
86
|
+
protected abstract getWorkers(): any[];
|
|
87
|
+
protected abstract getTables(): any[];
|
|
88
|
+
|
|
89
|
+
// For Each
|
|
90
|
+
public async foreachIDatabase(handler: (d: IDatabase) => Promise<void>): Promise<void>
|
|
91
|
+
{
|
|
92
|
+
let names = Object.keys(this.databases);
|
|
93
|
+
for (let name of names)
|
|
94
|
+
await handler(this.databases[name]);
|
|
95
|
+
}
|
|
96
|
+
public async foreachDatabase(handler: (d: BaseDatabase) => Promise<void>): Promise<void>
|
|
97
|
+
{
|
|
98
|
+
await this.foreachIDatabase(async d =>
|
|
99
|
+
{
|
|
100
|
+
if (d instanceof BaseDatabase)
|
|
101
|
+
await handler(d);
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
protected async foreachController(handler: (generator: (req: express.Request, res: express.Response) => BaseController<{}, any, any, any>) => Promise<boolean>, modes: string[])
|
|
105
|
+
{
|
|
106
|
+
let controllers = this.getControllers();
|
|
107
|
+
for (let i = 0; i < controllers.length; i++)
|
|
108
|
+
{
|
|
109
|
+
const Template = controllers[i] as any;
|
|
110
|
+
let generator = (req: express.Request, res: express.Response) =>
|
|
111
|
+
{
|
|
112
|
+
if (ObjectService.isClass(Template))
|
|
113
|
+
return new Template(this, req, res);
|
|
114
|
+
return Template(this, req, res);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
if (modes.length > 0)
|
|
118
|
+
{
|
|
119
|
+
let template = generator(null as any, null as any);
|
|
120
|
+
if (!template.modes.includes("*"))
|
|
121
|
+
if (!modes.some(mode => template.modes.includes(mode)))
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
let con = await handler(generator);
|
|
126
|
+
if (!con)
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
protected async foreachCron(handler: (generator: () => any) => Promise<boolean>)
|
|
131
|
+
{
|
|
132
|
+
let crons = this.getCrons();
|
|
133
|
+
for (let i = 0; i < crons.length; i++)
|
|
134
|
+
{
|
|
135
|
+
try
|
|
136
|
+
{
|
|
137
|
+
const Template = crons[i] as any;
|
|
138
|
+
let con = await handler(() =>
|
|
139
|
+
{
|
|
140
|
+
if (ObjectService.isClass(Template))
|
|
141
|
+
return new Template(this);
|
|
142
|
+
return Template(this);
|
|
143
|
+
});
|
|
144
|
+
if (!con)
|
|
145
|
+
break;
|
|
146
|
+
} catch (error)
|
|
147
|
+
{
|
|
148
|
+
this.logger.onCatchCritical(error);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
protected async foreachWorker(handler: (generator: () => any) => Promise<boolean>)
|
|
153
|
+
{
|
|
154
|
+
let workers = this.getWorkers();
|
|
155
|
+
for (let i = 0; i < workers.length; i++)
|
|
156
|
+
{
|
|
157
|
+
try
|
|
158
|
+
{
|
|
159
|
+
const Template = workers[i] as any;
|
|
160
|
+
let con = await handler(() =>
|
|
161
|
+
{
|
|
162
|
+
if (ObjectService.isClass(Template))
|
|
163
|
+
return new Template(this);
|
|
164
|
+
return Template(this);
|
|
165
|
+
});
|
|
166
|
+
if (!con)
|
|
167
|
+
break;
|
|
168
|
+
} catch (error)
|
|
169
|
+
{
|
|
170
|
+
this.logger.onCatchCritical(error);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Start
|
|
176
|
+
async start()
|
|
177
|
+
{
|
|
178
|
+
this.logger.info(`Application was started in mode '${this.mode}'.`);
|
|
179
|
+
await this.startCrashHandler();
|
|
180
|
+
await this.startDatabase();
|
|
181
|
+
if (!process.env.NAMIRASOFT_MUTE)
|
|
182
|
+
{
|
|
183
|
+
await this.onBeforeStart();
|
|
184
|
+
await this.startExpress();
|
|
185
|
+
if (this.mode == "api")
|
|
186
|
+
{
|
|
187
|
+
await this.createSwagger();
|
|
188
|
+
await this.startSwagger();
|
|
189
|
+
await this.startHomePage();
|
|
190
|
+
await this.createAssets();
|
|
191
|
+
await this.startAssets();
|
|
192
|
+
await this.createPages();
|
|
193
|
+
await this.startPages();
|
|
194
|
+
}
|
|
195
|
+
await this.startCrons();
|
|
196
|
+
await this.startWorkers();
|
|
197
|
+
await this.onAfterStart();
|
|
198
|
+
}
|
|
199
|
+
else
|
|
200
|
+
{
|
|
201
|
+
await this.saveSchema();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
protected async startCrashHandler(): Promise<void>
|
|
205
|
+
{
|
|
206
|
+
if (process.env.NAMIRASOFT_MUTE)
|
|
207
|
+
return;
|
|
208
|
+
|
|
209
|
+
process.on('unhandledRejection', (reason) =>
|
|
210
|
+
{
|
|
211
|
+
if (reason instanceof Error)
|
|
212
|
+
this.logger.onCatchCritical(reason);
|
|
213
|
+
else
|
|
214
|
+
this.logger.critical(reason + "");
|
|
215
|
+
});
|
|
216
|
+
process.on('uncaughtException', (error) =>
|
|
217
|
+
{
|
|
218
|
+
this.logger.onCatchFatal(error);
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
protected async startDatabase(): Promise<void>
|
|
222
|
+
{
|
|
223
|
+
this.databases = this.getDatabases();
|
|
224
|
+
await this.foreachIDatabase(async database =>
|
|
225
|
+
{
|
|
226
|
+
await database.init();
|
|
227
|
+
await database.connect();
|
|
228
|
+
await database.prepare();
|
|
229
|
+
await database.sync(false);
|
|
230
|
+
if (!process.env.NAMIRASOFT_MUTE)
|
|
231
|
+
await database.seedBefore();
|
|
232
|
+
});
|
|
233
|
+
this.logger.success("Databases were connected.");
|
|
234
|
+
}
|
|
235
|
+
protected async onBeforeStart(): Promise<void>
|
|
236
|
+
{ }
|
|
237
|
+
protected async startExpress(): Promise<void>
|
|
238
|
+
{
|
|
239
|
+
if (!process.env.NAMIRASOFT_MUTE)
|
|
240
|
+
{
|
|
241
|
+
this.express = express();
|
|
242
|
+
// Express
|
|
243
|
+
this.express.use(express.static('static'));
|
|
244
|
+
// Cors
|
|
245
|
+
this.express.use(cors({
|
|
246
|
+
exposedHeaders: '*',
|
|
247
|
+
origin: (_, callback) =>
|
|
248
|
+
{
|
|
249
|
+
callback(null, true);
|
|
250
|
+
},
|
|
251
|
+
credentials: true,
|
|
252
|
+
}));
|
|
253
|
+
// api routes
|
|
254
|
+
this.express.use('/', await this.getRouter());
|
|
255
|
+
// start server
|
|
256
|
+
const port = this.getPort();
|
|
257
|
+
this.server = this.express.listen(port, async () =>
|
|
258
|
+
{
|
|
259
|
+
this.logger.success(`Server is listening on port ${port}`);
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
protected async getRouter(): Promise<Router>
|
|
264
|
+
{
|
|
265
|
+
const router = express.Router({ mergeParams: true });
|
|
266
|
+
await this.foreachController(async generator =>
|
|
267
|
+
{
|
|
268
|
+
try
|
|
269
|
+
{
|
|
270
|
+
const template = generator(null as any, null as any);
|
|
271
|
+
let info = template.getInfo();
|
|
272
|
+
let handlers = [];
|
|
273
|
+
if (template.bodyAs.json.enabled)
|
|
274
|
+
handlers.push(express.json({ limit: template.bodyAs.json.limit }));
|
|
275
|
+
if (template.bodyAs.raw.enabled)
|
|
276
|
+
handlers.push(express.raw({ type: template.bodyAs.raw.type }));
|
|
277
|
+
handlers.push((req: express.Request, res: express.Response) =>
|
|
278
|
+
{
|
|
279
|
+
let controller = generator(req, res);
|
|
280
|
+
controller.run();
|
|
281
|
+
});
|
|
282
|
+
let path = this.base_path + info.path;
|
|
283
|
+
let ps: BaseVariableSchema[] = await template.getParametersSchema();
|
|
284
|
+
for (let p of ps)
|
|
285
|
+
path = path.replace(`{${p.name}}`, `:${p.name}`);
|
|
286
|
+
if (info.method == HTTPMethod.GET)
|
|
287
|
+
router.get(path, ...handlers);
|
|
288
|
+
else if (info.method == HTTPMethod.POST)
|
|
289
|
+
router.post(path, ...handlers);
|
|
290
|
+
else if (info.method == HTTPMethod.PUT)
|
|
291
|
+
router.put(path, ...handlers);
|
|
292
|
+
else if (info.method == HTTPMethod.PATCH)
|
|
293
|
+
router.patch(path, ...handlers);
|
|
294
|
+
else if (info.method == HTTPMethod.DELETE)
|
|
295
|
+
router.delete(path, ...handlers);
|
|
296
|
+
} catch (error)
|
|
297
|
+
{
|
|
298
|
+
this.logger.onCatchFatal(error);
|
|
299
|
+
}
|
|
300
|
+
return true;
|
|
301
|
+
}, [this.mode]);
|
|
302
|
+
return router;
|
|
303
|
+
}
|
|
304
|
+
protected async createSwagger(): Promise<void>
|
|
305
|
+
{
|
|
306
|
+
let schema = await this.getSchema<BaseController<D, {}, {}, {}>>(c => c.generate_swagger);
|
|
307
|
+
let builder = new SwaggerApplicationBuilder(schema);
|
|
308
|
+
let result = builder.runSynch();
|
|
309
|
+
for (let name of Object.keys(result.controllers))
|
|
310
|
+
{
|
|
311
|
+
const lines = result.controllers[name];
|
|
312
|
+
fs.writeFileSync(this.dir_swagger + "/controller_" + name + ".swg", lines.join("\n"));
|
|
313
|
+
}
|
|
314
|
+
for (let name of Object.keys(result.classes))
|
|
315
|
+
{
|
|
316
|
+
const lines = result.classes[name];
|
|
317
|
+
fs.writeFileSync(this.dir_swagger + "/model_" + name + ".swg", lines.join("\n"));
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
protected async startSwagger(): Promise<void>
|
|
321
|
+
{
|
|
322
|
+
const joptions = {
|
|
323
|
+
definition: {
|
|
324
|
+
openapi: "3.0.1",
|
|
325
|
+
info: {
|
|
326
|
+
title: this.title,
|
|
327
|
+
description: this.description,
|
|
328
|
+
version: this.version,
|
|
329
|
+
// license: {
|
|
330
|
+
// name: "MIT",
|
|
331
|
+
// url: "https://spdx.org/licenses/MIT.html",
|
|
332
|
+
// },
|
|
333
|
+
// contact: {
|
|
334
|
+
// name: "Amir Abolhasani",
|
|
335
|
+
// url: "https://namirasoft.com",
|
|
336
|
+
// email: "accounts@namirasoft.com",
|
|
337
|
+
// },
|
|
338
|
+
},
|
|
339
|
+
servers: [
|
|
340
|
+
{
|
|
341
|
+
url: this.base_path,
|
|
342
|
+
},
|
|
343
|
+
],
|
|
344
|
+
},
|
|
345
|
+
apis: [this.dir_swagger + '/*.swg'],
|
|
346
|
+
};
|
|
347
|
+
const swaggerSpec = swaggerJSDoc(joptions);
|
|
348
|
+
var options = {
|
|
349
|
+
explorer: true
|
|
350
|
+
};
|
|
351
|
+
this.express.use(this.path_swagger + "/", swaggerUi.serve, swaggerUi.setup(swaggerSpec, options));
|
|
352
|
+
}
|
|
353
|
+
protected async startHomePage(): Promise<void>
|
|
354
|
+
{
|
|
355
|
+
this.express.get(this.base_path + "/", (req, res) =>
|
|
356
|
+
{
|
|
357
|
+
this.handleHomePage(req, res);
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
protected abstract handleHomePage(_: express.Request, __: express.Response): Promise<void>;
|
|
361
|
+
|
|
362
|
+
protected async createAssets(): Promise<void>
|
|
363
|
+
{ }
|
|
364
|
+
protected async startAssets(): Promise<void>
|
|
365
|
+
{
|
|
366
|
+
this.express.use(this.path_asset + '/',
|
|
367
|
+
express.static(this.name_asset, { dotfiles: "allow" }),
|
|
368
|
+
serveIndex(this.name_asset, { icons: true, view: "details", hidden: true }));
|
|
369
|
+
}
|
|
370
|
+
protected async createPages(): Promise<void>
|
|
371
|
+
{ }
|
|
372
|
+
protected async startPages(): Promise<void>
|
|
373
|
+
{
|
|
374
|
+
this.express.use(this.path_page + '/',
|
|
375
|
+
express.static(this.name_page, {
|
|
376
|
+
dotfiles: "allow", index: false, extensions: ['html']
|
|
377
|
+
}),
|
|
378
|
+
serveIndex(this.name_page, {
|
|
379
|
+
icons: true,
|
|
380
|
+
view: "details",
|
|
381
|
+
hidden: false,
|
|
382
|
+
filter: (filename) => { return filename.endsWith('.html'); }
|
|
383
|
+
|
|
384
|
+
}));
|
|
385
|
+
}
|
|
386
|
+
protected async startCrons(): Promise<void>
|
|
387
|
+
{
|
|
388
|
+
if (!process.env.NAMIRASOFT_MUTE)
|
|
389
|
+
{
|
|
390
|
+
this.foreachCron(async generator =>
|
|
391
|
+
{
|
|
392
|
+
const template = generator() as BaseCron<D>;
|
|
393
|
+
template.run();
|
|
394
|
+
this.crons.push(template);
|
|
395
|
+
return true;
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
protected async startWorkers(): Promise<void>
|
|
400
|
+
{
|
|
401
|
+
if (!process.env.NAMIRASOFT_MUTE)
|
|
402
|
+
{
|
|
403
|
+
this.foreachWorker(async generator =>
|
|
404
|
+
{
|
|
405
|
+
const template = generator() as BaseWorker<D>;
|
|
406
|
+
template.start();
|
|
407
|
+
this.workers.push(template);
|
|
408
|
+
return true;
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
protected async onAfterStart(): Promise<void>
|
|
413
|
+
{
|
|
414
|
+
if (!process.env.NAMIRASOFT_MUTE)
|
|
415
|
+
await this.foreachIDatabase(async database =>
|
|
416
|
+
{
|
|
417
|
+
await database.seedAfter();
|
|
418
|
+
})
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Path
|
|
422
|
+
public getDirOfAsset(name: string)
|
|
423
|
+
{
|
|
424
|
+
return this.dir_asset + "/" + name;
|
|
425
|
+
}
|
|
426
|
+
public getPathOfAsset(name: string)
|
|
427
|
+
{
|
|
428
|
+
return this.path_asset + "/" + name;
|
|
429
|
+
}
|
|
430
|
+
public getDirOfPage(name: string)
|
|
431
|
+
{
|
|
432
|
+
return this.dir_page + "/" + name;
|
|
433
|
+
}
|
|
434
|
+
public getPathOfPage(name: string)
|
|
435
|
+
{
|
|
436
|
+
return this.path_page + "/" + name;
|
|
437
|
+
}
|
|
438
|
+
public read<T>(file_path: string)
|
|
439
|
+
{
|
|
440
|
+
let filePath = path.join(__dirname, file_path);
|
|
441
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8')) as T;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Schema
|
|
445
|
+
protected async saveSchema()
|
|
446
|
+
{
|
|
447
|
+
let app_schema = await this.getSchema<BaseController<D, {}, {}, {}>>(c => c.generate_sdk);
|
|
448
|
+
app_schema.toFile("./application.schema");
|
|
449
|
+
}
|
|
450
|
+
async getSchema<C>(filter: (controller: C) => boolean): Promise<ApplicationSchema>
|
|
451
|
+
{
|
|
452
|
+
let schema = new ApplicationSchema(this.pkg);
|
|
453
|
+
await this.foreachController(async generator =>
|
|
454
|
+
{
|
|
455
|
+
const template = generator(null as any, null as any);
|
|
456
|
+
if (template instanceof BaseController)
|
|
457
|
+
if (!filter || filter(template as C))
|
|
458
|
+
schema.controllers.push(await template.getSchema());
|
|
459
|
+
return true;
|
|
460
|
+
}, []);
|
|
461
|
+
let tables = this.getTables();
|
|
462
|
+
for (let i = 0; i < tables.length; i++)
|
|
463
|
+
{
|
|
464
|
+
const table = tables[i];
|
|
465
|
+
let obj = table.getSchema(true, null) as ObjectSchema;
|
|
466
|
+
schema.tables.push({
|
|
467
|
+
meta: {
|
|
468
|
+
short: table.getShortName()
|
|
469
|
+
},
|
|
470
|
+
schema: obj
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
schema.check();
|
|
474
|
+
return schema;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// Links
|
|
478
|
+
async getLinks(): Promise<BaseApplicationLink[]>
|
|
479
|
+
{
|
|
480
|
+
if (this.linkLoader)
|
|
481
|
+
{
|
|
482
|
+
this.links = [];
|
|
483
|
+
await this.linkLoader();
|
|
484
|
+
}
|
|
485
|
+
return this.links;
|
|
486
|
+
}
|
|
487
|
+
setLinkLoader(linkLoader: () => Promise<void>)
|
|
488
|
+
{
|
|
489
|
+
this.linkLoader = linkLoader;
|
|
490
|
+
}
|
|
491
|
+
addLink(link: BaseApplicationLink)
|
|
492
|
+
{
|
|
493
|
+
this.links.push(link);
|
|
494
|
+
}
|
|
495
|
+
addLink_Asset()
|
|
496
|
+
{
|
|
497
|
+
this.addLink({
|
|
498
|
+
name: "Assets",
|
|
499
|
+
url: this.path_asset + "/",
|
|
500
|
+
logo: "https://static.namirasoft.com/image/concept/file/blue-yellow.png",
|
|
501
|
+
description: "This shows the list of all assets of this API"
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
addLink_Page()
|
|
505
|
+
{
|
|
506
|
+
this.addLink({
|
|
507
|
+
name: "Pages",
|
|
508
|
+
url: this.path_page + "/",
|
|
509
|
+
logo: "https://static.namirasoft.com/image/concept/page/gray.png",
|
|
510
|
+
description: "This shows the list of all pages of this API"
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
addLink_Swagger()
|
|
514
|
+
{
|
|
515
|
+
this.addLink({
|
|
516
|
+
name: "Swagger",
|
|
517
|
+
url: this.path_swagger + "/",
|
|
518
|
+
logo: "https://static.namirasoft.com/image/application/swagger/logo/base.png",
|
|
519
|
+
description: this.description + " Swagger"
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Stop
|
|
524
|
+
async stop()
|
|
525
|
+
{
|
|
526
|
+
setTimeout(() =>
|
|
527
|
+
{
|
|
528
|
+
process.exit(0);
|
|
529
|
+
}, 10000);
|
|
530
|
+
|
|
531
|
+
if (!process.env.NAMIRASOFT_MUTE)
|
|
532
|
+
{
|
|
533
|
+
await this.onBeforeStop();
|
|
534
|
+
await this.stopExpress();
|
|
535
|
+
await this.stopCrons();
|
|
536
|
+
await this.stopWorkers();
|
|
537
|
+
await this.onAfterStop();
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
await this.stopDatabase();
|
|
541
|
+
|
|
542
|
+
setTimeout(() =>
|
|
543
|
+
{
|
|
544
|
+
process.exit(0);
|
|
545
|
+
}, 5000);
|
|
546
|
+
}
|
|
547
|
+
protected async stopDatabase(): Promise<void>
|
|
548
|
+
{
|
|
549
|
+
this.databases = this.getDatabases();
|
|
550
|
+
await this.foreachIDatabase(async database =>
|
|
551
|
+
{
|
|
552
|
+
await database.close();
|
|
553
|
+
});
|
|
554
|
+
this.logger.success("Databases were disconnected.");
|
|
555
|
+
}
|
|
556
|
+
protected async onBeforeStop(): Promise<void>
|
|
557
|
+
{ }
|
|
558
|
+
protected async stopExpress(): Promise<void>
|
|
559
|
+
{
|
|
560
|
+
if (!process.env.NAMIRASOFT_MUTE)
|
|
561
|
+
this.server?.close();
|
|
562
|
+
}
|
|
563
|
+
protected async stopCrons(): Promise<void>
|
|
564
|
+
{
|
|
565
|
+
if (!process.env.NAMIRASOFT_MUTE)
|
|
566
|
+
{
|
|
567
|
+
for (let i = 0; i < this.crons.length; i++)
|
|
568
|
+
{
|
|
569
|
+
const cron = this.crons[i];
|
|
570
|
+
cron.stop();
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
protected async stopWorkers(): Promise<void>
|
|
575
|
+
{
|
|
576
|
+
if (!process.env.NAMIRASOFT_MUTE)
|
|
577
|
+
{
|
|
578
|
+
for (let i = 0; i < this.workers.length; i++)
|
|
579
|
+
{
|
|
580
|
+
const worker = this.workers[i];
|
|
581
|
+
await worker.stop();
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
protected async onAfterStop(): Promise<void>
|
|
586
|
+
{
|
|
587
|
+
}
|
|
531
588
|
}
|