namirasoft-node 1.4.19 → 1.4.21

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.
@@ -1,433 +1,433 @@
1
- import express, { Router } from 'express';
2
- import cors from "cors";
3
- import * as fs from "fs";
4
- import * as path from 'path';
5
- import serveIndex from "serve-index";
6
- import swaggerUi from 'swagger-ui-express';
7
- import swaggerJSDoc from 'swagger-jsdoc';
8
- import { BaseDatabase } from './BaseDatabase';
9
- import { ILogger } from "namirasoft-log";
10
- import { BaseApplicationLink } from './BaseApplicationLink';
11
- import { EnvService, HTTPMethod, ObjectService, PackageService } from 'namirasoft-core';
12
- import { ApplicationSchema, BaseVariableSchema, ObjectSchema, SwaggerApplicationBuilder } from 'namirasoft-schema';
13
- import { BaseController } from './BaseController';
14
- import { BaseCron } from './BaseCron';
15
-
16
- export abstract class BaseApplication<D extends BaseDatabase>
17
- {
18
- private linkLoader?: () => Promise<void>;
19
- private links: BaseApplicationLink[] = [];
20
- protected name_asset: string;
21
- protected name_page: string;
22
- protected base_path: string;
23
- protected dir_asset: string;
24
- protected dir_page: string;
25
- protected dir_swagger: string;
26
- protected path_asset: string;
27
- protected path_page: string;
28
- protected path_swagger: string;
29
- protected pkg: PackageService;
30
- protected title: string;
31
- protected description: string;
32
- protected logo: string;
33
- protected version: string;
34
- protected mode!: string;
35
- public express!: express.Express;
36
- public database!: D;
37
- public logger: ILogger;
38
- constructor(base_path: string)
39
- {
40
- this.base_path = base_path;
41
- this.name_asset = "asset";
42
- this.name_page = "page";
43
- this.dir_asset = "./" + this.name_asset;
44
- this.dir_page = "./" + this.name_page;
45
- this.dir_swagger = "./swagger";
46
- this.path_asset = base_path + "/" + this.name_asset;
47
- this.path_page = base_path + "/" + this.name_page;
48
- this.path_swagger = this.path_page + "/swagger";
49
- this.pkg = PackageService.getMain();
50
- this.title = this.pkg?.getTitle() ?? "";
51
- this.description = this.pkg?.getDescription() ?? "";
52
- this.logo = this.pkg?.getLogo() ?? "";
53
- this.version = this.pkg?.getVersion() ?? "";
54
- this.mode = new EnvService("SERVER_MODE", false).getString("api").toLowerCase();
55
- this.logger = this.getILogger();
56
- this.addLink = this.addLink.bind(this);
57
- this.addLink_Asset = this.addLink_Asset.bind(this);
58
- this.addLink_Page = this.addLink_Page.bind(this);
59
- this.addLink_Swagger = this.addLink_Swagger.bind(this);
60
-
61
- // create folders
62
- this.dir_asset = path.join(path.dirname(this.pkg.getPath()), this.dir_asset);
63
- this.dir_page = path.join(path.dirname(this.pkg.getPath()), this.dir_page);
64
- this.dir_swagger = path.join(path.dirname(this.pkg.getPath()), this.dir_swagger);
65
- if (!fs.existsSync(this.dir_asset))
66
- fs.mkdirSync(this.dir_asset);
67
- if (!fs.existsSync(this.dir_page))
68
- fs.mkdirSync(this.dir_page);
69
- if (!fs.existsSync(this.dir_swagger))
70
- fs.mkdirSync(this.dir_swagger, { recursive: true });
71
- }
72
- public abstract getDatabase(): D;
73
- public getOtherDatabases(): BaseDatabase[]
74
- {
75
- return [];
76
- }
77
- protected abstract getILogger(): ILogger;
78
- protected abstract getPort(): number;
79
- protected abstract getControllers(): any[];
80
- protected abstract getTables(): any[];
81
- protected abstract getCrons(): any[];
82
- protected async foreachController(handler: (generator: (req: express.Request, res: express.Response) => any) => Promise<boolean>)
83
- {
84
- let controllers = this.getControllers();
85
- for (let i = 0; i < controllers.length; i++)
86
- {
87
- const Template = controllers[i] as any;
88
- let con = await handler((req: express.Request, res: express.Response) =>
89
- {
90
- if (ObjectService.isClass(Template))
91
- return new Template(this, req, res);
92
- return Template(this, req, res);
93
- });
94
- if (!con)
95
- break;
96
- }
97
- }
98
- protected async foreachCron(handler: (generator: () => any) => Promise<boolean>)
99
- {
100
- let crons = this.getCrons();
101
- for (let i = 0; i < crons.length; i++)
102
- {
103
- try
104
- {
105
- const Template = crons[i] as any;
106
- let con = await handler(() =>
107
- {
108
- if (ObjectService.isClass(Template))
109
- return new Template(this);
110
- return Template(this);
111
- });
112
- if (!con)
113
- break;
114
- } catch (error)
115
- {
116
- this.logger.onCatchError(error);
117
- }
118
- }
119
- }
120
- // start
121
- async start()
122
- {
123
- this.logger.info("Application was started.");
124
- await this.startCrashHandler();
125
- await this.startDatabase();
126
- if (!process.env.NAMIRASOFT_MUTE)
127
- {
128
- await this.onBeforeStart();
129
- if (this.mode == "api")
130
- {
131
- await this.startExpress();
132
- await this.startCrons();
133
- await this.createSwagger();
134
- await this.startSwagger();
135
- await this.startHomePage();
136
- await this.createAssets();
137
- await this.startAssets();
138
- await this.createPages();
139
- await this.startPages();
140
- }
141
- await this.startOthers();
142
- await this.onAfterStart();
143
- }
144
- else
145
- {
146
- await this.saveSchema();
147
- }
148
- }
149
- protected async startCrashHandler(): Promise<void>
150
- {
151
- if (process.env.NAMIRASOFT_MUTE)
152
- return;
153
-
154
- process.on('unhandledRejection', (reason) =>
155
- {
156
- if (reason instanceof Error)
157
- this.logger.onCatchCritical(reason);
158
- else
159
- this.logger.critical(reason + "");
160
- });
161
- process.on('uncaughtException', (error) =>
162
- {
163
- this.logger.onCatchFatal(error);
164
- });
165
- }
166
- protected async startDatabase(): Promise<void>
167
- {
168
- this.database = this.getDatabase();
169
- await this.database.init();
170
- this.database.connect();
171
- await this.database.sync(false);
172
- if (!process.env.NAMIRASOFT_MUTE)
173
- await this.database.seedBefore();
174
- this.logger.success("Database was connected.");
175
- }
176
- protected async onBeforeStart(): Promise<void>
177
- { }
178
- protected async startExpress(): Promise<void>
179
- {
180
- if (!process.env.NAMIRASOFT_MUTE)
181
- {
182
- this.express = express();
183
- // Express
184
- this.express.use(express.static('static'));
185
- // Cors
186
- this.express.use(cors({ exposedHeaders: '*' }));
187
- // api routes
188
- this.express.use('/', await this.getRouter());
189
- // start server
190
- const port = this.getPort();
191
- this.express.listen(port, async () =>
192
- {
193
- this.logger.success(`Server is listening on port ${port}`);
194
- });
195
- }
196
- }
197
- protected async startCrons(): Promise<void>
198
- {
199
- if (!process.env.NAMIRASOFT_MUTE)
200
- {
201
- this.foreachCron(async generator =>
202
- {
203
- const template = generator() as BaseCron<D>;
204
- template.run();
205
- return true;
206
- });
207
- }
208
- }
209
- protected async createSwagger(): Promise<void>
210
- {
211
- let schema = await this.getSchema<BaseController<BaseDatabase, {}, {}, {}>>(c => c.generate_swagger);
212
- let builder = new SwaggerApplicationBuilder(schema);
213
- let result = await builder.run();
214
- for (let name of Object.keys(result.controllers))
215
- {
216
- const lines = result.controllers[name];
217
- fs.writeFileSync(this.dir_swagger + "/controller_" + name + ".swg", lines.join("\n"));
218
- }
219
- for (let name of Object.keys(result.classes))
220
- {
221
- const lines = result.classes[name];
222
- fs.writeFileSync(this.dir_swagger + "/model_" + name + ".swg", lines.join("\n"));
223
- }
224
- }
225
- protected async startSwagger(): Promise<void>
226
- {
227
- const joptions = {
228
- definition: {
229
- openapi: "3.0.1",
230
- info: {
231
- title: this.title,
232
- description: this.description,
233
- version: this.version,
234
- // license: {
235
- // name: "MIT",
236
- // url: "https://spdx.org/licenses/MIT.html",
237
- // },
238
- // contact: {
239
- // name: "Amir Abolhasani",
240
- // url: "https://namirasoft.com",
241
- // email: "accounts@namirasoft.com",
242
- // },
243
- },
244
- servers: [
245
- {
246
- url: this.base_path,
247
- },
248
- ],
249
- },
250
- apis: [this.dir_swagger + '/*.swg'],
251
- };
252
- const swaggerSpec = swaggerJSDoc(joptions);
253
- var options = {
254
- explorer: true
255
- };
256
- this.express.use(this.path_swagger + "/", swaggerUi.serve, swaggerUi.setup(swaggerSpec, options));
257
- }
258
- protected async startHomePage(): Promise<void>
259
- {
260
- this.express.get(this.base_path + "/", (req, res) =>
261
- {
262
- this.handleHomePage(req, res);
263
- });
264
- }
265
- protected abstract handleHomePage(_: express.Request, __: express.Response): Promise<void>;
266
- public getDirOfAsset(name: string)
267
- {
268
- return this.dir_asset + "/" + name;
269
- }
270
- public getPathOfAsset(name: string)
271
- {
272
- return this.path_asset + "/" + name;
273
- }
274
- protected async createAssets(): Promise<void>
275
- { }
276
- protected async startAssets(): Promise<void>
277
- {
278
- this.express.use(this.path_asset + '/',
279
- express.static(this.name_asset, { dotfiles: "allow" }),
280
- serveIndex(this.name_asset, { icons: true, view: "details", hidden: true }));
281
- }
282
- public getDirOfPage(name: string)
283
- {
284
- return this.dir_page + "/" + name;
285
- }
286
- public getPathOfPage(name: string)
287
- {
288
- return this.path_page + "/" + name;
289
- }
290
- protected async createPages(): Promise<void>
291
- { }
292
- protected async startPages(): Promise<void>
293
- {
294
- this.express.use(this.path_page + '/',
295
- express.static(this.name_page, {
296
- dotfiles: "allow", index: false, extensions: ['html']
297
- }),
298
- serveIndex(this.name_page, {
299
- icons: true,
300
- view: "details",
301
- hidden: false,
302
- filter: (filename) => { return filename.endsWith('.html'); }
303
-
304
- }));
305
- }
306
- protected async startOthers(): Promise<void>
307
- {
308
- }
309
- protected async onAfterStart(): Promise<void>
310
- {
311
- if (!process.env.NAMIRASOFT_MUTE)
312
- await this.database.seedAfter();
313
- }
314
- protected async getRouter(): Promise<Router>
315
- {
316
- const router = express.Router({ mergeParams: true });
317
- await this.foreachController(async generator =>
318
- {
319
- try
320
- {
321
- const template = generator(null as any, null as any);
322
- let info = template.getInfo();
323
- let handlers = [];
324
- if (template.bodyAs.json.enabled)
325
- handlers.push(express.json({ limit: template.bodyAs.json.limit }));
326
- if (template.bodyAs.raw.enabled)
327
- handlers.push(express.raw({ type: template.bodyAs.raw.type }));
328
- handlers.push((req: express.Request, res: express.Response) =>
329
- {
330
- let controller = generator(req, res);
331
- controller.run();
332
- });
333
- let path = this.base_path + info.path;
334
- let ps: BaseVariableSchema[] = await template.getParametersSchema();
335
- for (let p of ps)
336
- path = path.replace(`{${p.name}}`, `:${p.name}`);
337
- if (info.method == HTTPMethod.GET)
338
- router.get(path, ...handlers);
339
- else if (info.method == HTTPMethod.POST)
340
- router.post(path, ...handlers);
341
- else if (info.method == HTTPMethod.PUT)
342
- router.put(path, ...handlers);
343
- else if (info.method == HTTPMethod.DELETE)
344
- router.delete(path, ...handlers);
345
- else
346
- return false;
347
- } catch (error)
348
- {
349
- this.logger.onCatchError(error);
350
- }
351
- return true;
352
- });
353
- return router;
354
- }
355
- // schema
356
- protected async saveSchema()
357
- {
358
- let app_schema = await this.getSchema<BaseController<BaseDatabase, {}, {}, {}>>(c => c.generate_sdk);
359
- app_schema.toFile("./application.schema");
360
- }
361
- async getSchema<C>(filter: (controller: C) => boolean): Promise<ApplicationSchema>
362
- {
363
- let schema = new ApplicationSchema(this.pkg);
364
- await this.foreachController(async generator =>
365
- {
366
- const template = generator(null as any, null as any);
367
- template.database = this.database;
368
- if (template instanceof BaseController)
369
- if (!filter || filter(template as C))
370
- schema.controllers.push(await template.getSchema());
371
- return true;
372
- });
373
- let tables = this.getTables();
374
- for (let i = 0; i < tables.length; i++)
375
- {
376
- const table = tables[i];
377
- let obj = table.getSchema(true, null) as ObjectSchema;
378
- schema.tables.push({
379
- meta: {
380
- short: table.getShortName()
381
- },
382
- schema: obj
383
- });
384
- }
385
- schema.check();
386
- return schema;
387
- }
388
- // public
389
- async getLinks(): Promise<BaseApplicationLink[]>
390
- {
391
- if (this.linkLoader)
392
- {
393
- this.links = [];
394
- await this.linkLoader();
395
- }
396
- return this.links;
397
- }
398
- setLinkLoader(linkLoader: () => Promise<void>)
399
- {
400
- this.linkLoader = linkLoader;
401
- }
402
- addLink(link: BaseApplicationLink)
403
- {
404
- this.links.push(link);
405
- }
406
- addLink_Asset()
407
- {
408
- this.addLink({
409
- name: "Assets",
410
- url: this.path_asset + "/",
411
- logo: "https://static.namirasoft.com/image/concept/file/blue-yellow.png",
412
- description: "This shows the list of all assets of this API"
413
- });
414
- }
415
- addLink_Page()
416
- {
417
- this.addLink({
418
- name: "Pages",
419
- url: this.path_page + "/",
420
- logo: "https://static.namirasoft.com/image/concept/page/gray.png",
421
- description: "This shows the list of all pages of this API"
422
- });
423
- }
424
- addLink_Swagger()
425
- {
426
- this.addLink({
427
- name: "Swagger",
428
- url: this.path_swagger + "/",
429
- logo: "https://static.namirasoft.com/image/application/swagger/logo/base.png",
430
- description: this.description + " Swagger"
431
- });
432
- }
1
+ import express, { Router } from 'express';
2
+ import cors from "cors";
3
+ import * as fs from "fs";
4
+ import * as path from 'path';
5
+ import serveIndex from "serve-index";
6
+ import swaggerUi from 'swagger-ui-express';
7
+ import swaggerJSDoc from 'swagger-jsdoc';
8
+ import { BaseDatabase } from './BaseDatabase';
9
+ import { ILogger } from "namirasoft-log";
10
+ import { BaseApplicationLink } from './BaseApplicationLink';
11
+ import { EnvService, HTTPMethod, ObjectService, PackageService } from 'namirasoft-core';
12
+ import { ApplicationSchema, BaseVariableSchema, ObjectSchema, SwaggerApplicationBuilder } from 'namirasoft-schema';
13
+ import { BaseController } from './BaseController';
14
+ import { BaseCron } from './BaseCron';
15
+
16
+ export abstract class BaseApplication<D extends BaseDatabase>
17
+ {
18
+ private linkLoader?: () => Promise<void>;
19
+ private links: BaseApplicationLink[] = [];
20
+ protected name_asset: string;
21
+ protected name_page: string;
22
+ protected base_path: string;
23
+ protected dir_asset: string;
24
+ protected dir_page: string;
25
+ protected dir_swagger: string;
26
+ protected path_asset: string;
27
+ protected path_page: string;
28
+ protected path_swagger: string;
29
+ protected pkg: PackageService;
30
+ protected title: string;
31
+ protected description: string;
32
+ protected logo: string;
33
+ protected version: string;
34
+ protected mode!: string;
35
+ public express!: express.Express;
36
+ public database!: D;
37
+ public logger: ILogger;
38
+ constructor(base_path: string)
39
+ {
40
+ this.base_path = base_path;
41
+ this.name_asset = "asset";
42
+ this.name_page = "page";
43
+ this.dir_asset = "./" + this.name_asset;
44
+ this.dir_page = "./" + this.name_page;
45
+ this.dir_swagger = "./swagger";
46
+ this.path_asset = base_path + "/" + this.name_asset;
47
+ this.path_page = base_path + "/" + this.name_page;
48
+ this.path_swagger = this.path_page + "/swagger";
49
+ this.pkg = PackageService.getMain();
50
+ this.title = this.pkg?.getTitle() ?? "";
51
+ this.description = this.pkg?.getDescription() ?? "";
52
+ this.logo = this.pkg?.getLogo() ?? "";
53
+ this.version = this.pkg?.getVersion() ?? "";
54
+ this.mode = new EnvService("SERVER_MODE", false).getString("api").toLowerCase();
55
+ this.logger = this.getILogger();
56
+ this.addLink = this.addLink.bind(this);
57
+ this.addLink_Asset = this.addLink_Asset.bind(this);
58
+ this.addLink_Page = this.addLink_Page.bind(this);
59
+ this.addLink_Swagger = this.addLink_Swagger.bind(this);
60
+
61
+ // create folders
62
+ this.dir_asset = path.join(path.dirname(this.pkg.getPath()), this.dir_asset);
63
+ this.dir_page = path.join(path.dirname(this.pkg.getPath()), this.dir_page);
64
+ this.dir_swagger = path.join(path.dirname(this.pkg.getPath()), this.dir_swagger);
65
+ if (!fs.existsSync(this.dir_asset))
66
+ fs.mkdirSync(this.dir_asset);
67
+ if (!fs.existsSync(this.dir_page))
68
+ fs.mkdirSync(this.dir_page);
69
+ if (!fs.existsSync(this.dir_swagger))
70
+ fs.mkdirSync(this.dir_swagger, { recursive: true });
71
+ }
72
+ public abstract getDatabase(): D;
73
+ public getOtherDatabases(): BaseDatabase[]
74
+ {
75
+ return [];
76
+ }
77
+ protected abstract getILogger(): ILogger;
78
+ protected abstract getPort(): number;
79
+ protected abstract getControllers(): any[];
80
+ protected abstract getTables(): any[];
81
+ protected abstract getCrons(): any[];
82
+ protected async foreachController(handler: (generator: (req: express.Request, res: express.Response) => any) => Promise<boolean>)
83
+ {
84
+ let controllers = this.getControllers();
85
+ for (let i = 0; i < controllers.length; i++)
86
+ {
87
+ const Template = controllers[i] as any;
88
+ let con = await handler((req: express.Request, res: express.Response) =>
89
+ {
90
+ if (ObjectService.isClass(Template))
91
+ return new Template(this, req, res);
92
+ return Template(this, req, res);
93
+ });
94
+ if (!con)
95
+ break;
96
+ }
97
+ }
98
+ protected async foreachCron(handler: (generator: () => any) => Promise<boolean>)
99
+ {
100
+ let crons = this.getCrons();
101
+ for (let i = 0; i < crons.length; i++)
102
+ {
103
+ try
104
+ {
105
+ const Template = crons[i] as any;
106
+ let con = await handler(() =>
107
+ {
108
+ if (ObjectService.isClass(Template))
109
+ return new Template(this);
110
+ return Template(this);
111
+ });
112
+ if (!con)
113
+ break;
114
+ } catch (error)
115
+ {
116
+ this.logger.onCatchError(error);
117
+ }
118
+ }
119
+ }
120
+ // start
121
+ async start()
122
+ {
123
+ this.logger.info("Application was started.");
124
+ await this.startCrashHandler();
125
+ await this.startDatabase();
126
+ if (!process.env.NAMIRASOFT_MUTE)
127
+ {
128
+ await this.onBeforeStart();
129
+ if (this.mode == "api")
130
+ {
131
+ await this.startExpress();
132
+ await this.startCrons();
133
+ await this.createSwagger();
134
+ await this.startSwagger();
135
+ await this.startHomePage();
136
+ await this.createAssets();
137
+ await this.startAssets();
138
+ await this.createPages();
139
+ await this.startPages();
140
+ }
141
+ await this.startOthers();
142
+ await this.onAfterStart();
143
+ }
144
+ else
145
+ {
146
+ await this.saveSchema();
147
+ }
148
+ }
149
+ protected async startCrashHandler(): Promise<void>
150
+ {
151
+ if (process.env.NAMIRASOFT_MUTE)
152
+ return;
153
+
154
+ process.on('unhandledRejection', (reason) =>
155
+ {
156
+ if (reason instanceof Error)
157
+ this.logger.onCatchCritical(reason);
158
+ else
159
+ this.logger.critical(reason + "");
160
+ });
161
+ process.on('uncaughtException', (error) =>
162
+ {
163
+ this.logger.onCatchFatal(error);
164
+ });
165
+ }
166
+ protected async startDatabase(): Promise<void>
167
+ {
168
+ this.database = this.getDatabase();
169
+ await this.database.init();
170
+ this.database.connect();
171
+ await this.database.sync(false);
172
+ if (!process.env.NAMIRASOFT_MUTE)
173
+ await this.database.seedBefore();
174
+ this.logger.success("Database was connected.");
175
+ }
176
+ protected async onBeforeStart(): Promise<void>
177
+ { }
178
+ protected async startExpress(): Promise<void>
179
+ {
180
+ if (!process.env.NAMIRASOFT_MUTE)
181
+ {
182
+ this.express = express();
183
+ // Express
184
+ this.express.use(express.static('static'));
185
+ // Cors
186
+ this.express.use(cors({ exposedHeaders: '*' }));
187
+ // api routes
188
+ this.express.use('/', await this.getRouter());
189
+ // start server
190
+ const port = this.getPort();
191
+ this.express.listen(port, async () =>
192
+ {
193
+ this.logger.success(`Server is listening on port ${port}`);
194
+ });
195
+ }
196
+ }
197
+ protected async startCrons(): Promise<void>
198
+ {
199
+ if (!process.env.NAMIRASOFT_MUTE)
200
+ {
201
+ this.foreachCron(async generator =>
202
+ {
203
+ const template = generator() as BaseCron<D>;
204
+ template.run();
205
+ return true;
206
+ });
207
+ }
208
+ }
209
+ protected async createSwagger(): Promise<void>
210
+ {
211
+ let schema = await this.getSchema<BaseController<BaseDatabase, {}, {}, {}>>(c => c.generate_swagger);
212
+ let builder = new SwaggerApplicationBuilder(schema);
213
+ let result = await builder.run();
214
+ for (let name of Object.keys(result.controllers))
215
+ {
216
+ const lines = result.controllers[name];
217
+ fs.writeFileSync(this.dir_swagger + "/controller_" + name + ".swg", lines.join("\n"));
218
+ }
219
+ for (let name of Object.keys(result.classes))
220
+ {
221
+ const lines = result.classes[name];
222
+ fs.writeFileSync(this.dir_swagger + "/model_" + name + ".swg", lines.join("\n"));
223
+ }
224
+ }
225
+ protected async startSwagger(): Promise<void>
226
+ {
227
+ const joptions = {
228
+ definition: {
229
+ openapi: "3.0.1",
230
+ info: {
231
+ title: this.title,
232
+ description: this.description,
233
+ version: this.version,
234
+ // license: {
235
+ // name: "MIT",
236
+ // url: "https://spdx.org/licenses/MIT.html",
237
+ // },
238
+ // contact: {
239
+ // name: "Amir Abolhasani",
240
+ // url: "https://namirasoft.com",
241
+ // email: "accounts@namirasoft.com",
242
+ // },
243
+ },
244
+ servers: [
245
+ {
246
+ url: this.base_path,
247
+ },
248
+ ],
249
+ },
250
+ apis: [this.dir_swagger + '/*.swg'],
251
+ };
252
+ const swaggerSpec = swaggerJSDoc(joptions);
253
+ var options = {
254
+ explorer: true
255
+ };
256
+ this.express.use(this.path_swagger + "/", swaggerUi.serve, swaggerUi.setup(swaggerSpec, options));
257
+ }
258
+ protected async startHomePage(): Promise<void>
259
+ {
260
+ this.express.get(this.base_path + "/", (req, res) =>
261
+ {
262
+ this.handleHomePage(req, res);
263
+ });
264
+ }
265
+ protected abstract handleHomePage(_: express.Request, __: express.Response): Promise<void>;
266
+ public getDirOfAsset(name: string)
267
+ {
268
+ return this.dir_asset + "/" + name;
269
+ }
270
+ public getPathOfAsset(name: string)
271
+ {
272
+ return this.path_asset + "/" + name;
273
+ }
274
+ protected async createAssets(): Promise<void>
275
+ { }
276
+ protected async startAssets(): Promise<void>
277
+ {
278
+ this.express.use(this.path_asset + '/',
279
+ express.static(this.name_asset, { dotfiles: "allow" }),
280
+ serveIndex(this.name_asset, { icons: true, view: "details", hidden: true }));
281
+ }
282
+ public getDirOfPage(name: string)
283
+ {
284
+ return this.dir_page + "/" + name;
285
+ }
286
+ public getPathOfPage(name: string)
287
+ {
288
+ return this.path_page + "/" + name;
289
+ }
290
+ protected async createPages(): Promise<void>
291
+ { }
292
+ protected async startPages(): Promise<void>
293
+ {
294
+ this.express.use(this.path_page + '/',
295
+ express.static(this.name_page, {
296
+ dotfiles: "allow", index: false, extensions: ['html']
297
+ }),
298
+ serveIndex(this.name_page, {
299
+ icons: true,
300
+ view: "details",
301
+ hidden: false,
302
+ filter: (filename) => { return filename.endsWith('.html'); }
303
+
304
+ }));
305
+ }
306
+ protected async startOthers(): Promise<void>
307
+ {
308
+ }
309
+ protected async onAfterStart(): Promise<void>
310
+ {
311
+ if (!process.env.NAMIRASOFT_MUTE)
312
+ await this.database.seedAfter();
313
+ }
314
+ protected async getRouter(): Promise<Router>
315
+ {
316
+ const router = express.Router({ mergeParams: true });
317
+ await this.foreachController(async generator =>
318
+ {
319
+ try
320
+ {
321
+ const template = generator(null as any, null as any);
322
+ let info = template.getInfo();
323
+ let handlers = [];
324
+ if (template.bodyAs.json.enabled)
325
+ handlers.push(express.json({ limit: template.bodyAs.json.limit }));
326
+ if (template.bodyAs.raw.enabled)
327
+ handlers.push(express.raw({ type: template.bodyAs.raw.type }));
328
+ handlers.push((req: express.Request, res: express.Response) =>
329
+ {
330
+ let controller = generator(req, res);
331
+ controller.run();
332
+ });
333
+ let path = this.base_path + info.path;
334
+ let ps: BaseVariableSchema[] = await template.getParametersSchema();
335
+ for (let p of ps)
336
+ path = path.replace(`{${p.name}}`, `:${p.name}`);
337
+ if (info.method == HTTPMethod.GET)
338
+ router.get(path, ...handlers);
339
+ else if (info.method == HTTPMethod.POST)
340
+ router.post(path, ...handlers);
341
+ else if (info.method == HTTPMethod.PUT)
342
+ router.put(path, ...handlers);
343
+ else if (info.method == HTTPMethod.DELETE)
344
+ router.delete(path, ...handlers);
345
+ else
346
+ return false;
347
+ } catch (error)
348
+ {
349
+ this.logger.onCatchError(error);
350
+ }
351
+ return true;
352
+ });
353
+ return router;
354
+ }
355
+ // schema
356
+ protected async saveSchema()
357
+ {
358
+ let app_schema = await this.getSchema<BaseController<BaseDatabase, {}, {}, {}>>(c => c.generate_sdk);
359
+ app_schema.toFile("./application.schema");
360
+ }
361
+ async getSchema<C>(filter: (controller: C) => boolean): Promise<ApplicationSchema>
362
+ {
363
+ let schema = new ApplicationSchema(this.pkg);
364
+ await this.foreachController(async generator =>
365
+ {
366
+ const template = generator(null as any, null as any);
367
+ template.database = this.database;
368
+ if (template instanceof BaseController)
369
+ if (!filter || filter(template as C))
370
+ schema.controllers.push(await template.getSchema());
371
+ return true;
372
+ });
373
+ let tables = this.getTables();
374
+ for (let i = 0; i < tables.length; i++)
375
+ {
376
+ const table = tables[i];
377
+ let obj = table.getSchema(true, null) as ObjectSchema;
378
+ schema.tables.push({
379
+ meta: {
380
+ short: table.getShortName()
381
+ },
382
+ schema: obj
383
+ });
384
+ }
385
+ schema.check();
386
+ return schema;
387
+ }
388
+ // public
389
+ async getLinks(): Promise<BaseApplicationLink[]>
390
+ {
391
+ if (this.linkLoader)
392
+ {
393
+ this.links = [];
394
+ await this.linkLoader();
395
+ }
396
+ return this.links;
397
+ }
398
+ setLinkLoader(linkLoader: () => Promise<void>)
399
+ {
400
+ this.linkLoader = linkLoader;
401
+ }
402
+ addLink(link: BaseApplicationLink)
403
+ {
404
+ this.links.push(link);
405
+ }
406
+ addLink_Asset()
407
+ {
408
+ this.addLink({
409
+ name: "Assets",
410
+ url: this.path_asset + "/",
411
+ logo: "https://static.namirasoft.com/image/concept/file/blue-yellow.png",
412
+ description: "This shows the list of all assets of this API"
413
+ });
414
+ }
415
+ addLink_Page()
416
+ {
417
+ this.addLink({
418
+ name: "Pages",
419
+ url: this.path_page + "/",
420
+ logo: "https://static.namirasoft.com/image/concept/page/gray.png",
421
+ description: "This shows the list of all pages of this API"
422
+ });
423
+ }
424
+ addLink_Swagger()
425
+ {
426
+ this.addLink({
427
+ name: "Swagger",
428
+ url: this.path_swagger + "/",
429
+ logo: "https://static.namirasoft.com/image/application/swagger/logo/base.png",
430
+ description: this.description + " Swagger"
431
+ });
432
+ }
433
433
  }