expresso-macchiato 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/index.d.mts +603 -0
- package/dist/index.d.ts +603 -0
- package/dist/index.js +825 -0
- package/dist/index.mjs +825 -0
- package/expressojs-0.3.0.tgz +0 -0
- package/package.json +63 -0
- package/types/db.sptypes.ts +18 -0
- package/types/generic.sptypes.ts +35 -0
- package/types/router.sptypes.ts +39 -0
- package/types/starter.sptypes.ts +36 -0
- package/types/swagger.sptypes.ts +375 -0
- package/types/token.sptypes.ts +20 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,825 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/RouterWrapper.ts
|
|
2
|
+
var _express = require('express'); var _express2 = _interopRequireDefault(_express);
|
|
3
|
+
|
|
4
|
+
// src/_utils.ts
|
|
5
|
+
var _utilsloggerav = require('utils-logger-av');
|
|
6
|
+
var MyLogger = class extends _utilsloggerav.Logger {
|
|
7
|
+
constructor() {
|
|
8
|
+
super(...arguments);
|
|
9
|
+
this.setFilePath = (filePath) => {
|
|
10
|
+
this.logFilePath = filePath;
|
|
11
|
+
};
|
|
12
|
+
this.fullLogOk = (service, message) => {
|
|
13
|
+
this.ok(`[${service.toUpperCase()}]: ${message}`);
|
|
14
|
+
this.logFile(`[${service.toUpperCase()}]: ${message}`);
|
|
15
|
+
};
|
|
16
|
+
this.fullLogNok = (service, error, ...args) => {
|
|
17
|
+
const errMessage = _nullishCoalesce(_optionalChain([error, 'optionalAccess', _2 => _2.message]), () => ( error));
|
|
18
|
+
this.nok(`[${service.toUpperCase()}]: ${errMessage}`);
|
|
19
|
+
this.logFile(`[${service.toUpperCase()}]: ${errMessage}, ${args.join(",")}`, "error");
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
var log = new MyLogger({ primaryColor: "cyan", logFilePath: process.env.ERROR_FILE_PATH });
|
|
24
|
+
var { fullLogOk, fullLogNok } = log;
|
|
25
|
+
var apiOk = (res, status = 200, contentType) => ({ result: res, status, contentType, isOk: true });
|
|
26
|
+
var apiNok = (err, status = 500) => ({ result: err, status, isOk: false });
|
|
27
|
+
var errorCatcher = (res, err, errorsList, errorString) => {
|
|
28
|
+
if (errorString) fullLogNok("api-dynamicdb", errorString);
|
|
29
|
+
if (err instanceof Error === false) {
|
|
30
|
+
res.status(500).send({ message: err });
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const error = _nullishCoalesce((_nullishCoalesce(errorsList, () => ( {})))[err.message], () => ( null));
|
|
34
|
+
if (!error) res.status(500).send({ message: err.message });
|
|
35
|
+
else res.status(_nullishCoalesce(error.status, () => ( 500))).send({ message: _nullishCoalesce(error.responseMessage, () => ( err.message)) });
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// src/DynamicDbRouter.ts
|
|
39
|
+
var _typeorm = require('typeorm');
|
|
40
|
+
|
|
41
|
+
// src/DbConnector.ts
|
|
42
|
+
require('reflect-metadata');
|
|
43
|
+
|
|
44
|
+
var _DbConnector = class _DbConnector {
|
|
45
|
+
constructor(projectConfig) {
|
|
46
|
+
this.connect = async (entities, migrations, sync) => {
|
|
47
|
+
try {
|
|
48
|
+
if (!this.projectConfig.DB_DIALECT || !this.projectConfig.DB_NAME) throw new Error("[DB-CONNECTOR] Missing configs =>DB_DIALECT || DB_NAME");
|
|
49
|
+
const AppDataSource = new (0, _typeorm.DataSource)({
|
|
50
|
+
type: this.projectConfig.DB_DIALECT,
|
|
51
|
+
host: this.projectConfig.DB_HOST,
|
|
52
|
+
port: this.projectConfig.DB_PORT,
|
|
53
|
+
username: this.projectConfig.DB_USER,
|
|
54
|
+
password: this.projectConfig.DB_PASSWORD,
|
|
55
|
+
database: this.projectConfig.DB_NAME,
|
|
56
|
+
entities,
|
|
57
|
+
synchronize: _nullishCoalesce(sync, () => ( false)),
|
|
58
|
+
logging: false,
|
|
59
|
+
migrations
|
|
60
|
+
});
|
|
61
|
+
await AppDataSource.initialize();
|
|
62
|
+
if (_nullishCoalesce(sync, () => ( false))) await AppDataSource.synchronize();
|
|
63
|
+
else {
|
|
64
|
+
const executedMigrations = await AppDataSource.query(`SELECT name FROM sqlite_master WHERE type='table' AND name='migrations'`);
|
|
65
|
+
const executedMigrationNames = executedMigrations.map((migration) => migration.name);
|
|
66
|
+
if (migrations) {
|
|
67
|
+
log.teal("[DB-CONNECTOR] Running migrations:");
|
|
68
|
+
for (let migration of migrations) {
|
|
69
|
+
if (executedMigrationNames.includes(migration)) log.gray(`- Migration ${migration} already executed, skipping.`);
|
|
70
|
+
else {
|
|
71
|
+
log.yellow(`- Executing migration ${migration}`);
|
|
72
|
+
await AppDataSource.runMigrations();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
log.teal("[DB-CONNECTOR] Migrations done");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
_DbConnector.DataSource = AppDataSource;
|
|
79
|
+
log.magenta(`[DB-CONNECTOR] ORM CONNECTED`);
|
|
80
|
+
} catch (err) {
|
|
81
|
+
log.logError(err);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
this.projectConfig = projectConfig;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
_DbConnector.getDataSource = () => _DbConnector.DataSource;
|
|
88
|
+
var DbConnector = _DbConnector;
|
|
89
|
+
|
|
90
|
+
// src/Swagger.ts
|
|
91
|
+
var _Swagger = class _Swagger {
|
|
92
|
+
};
|
|
93
|
+
// --- PRIVATE
|
|
94
|
+
_Swagger.fromExpressParamsToSwagger = (str) => str.replace(/:(\w+)(?=\/|$)/g, "{$1}");
|
|
95
|
+
_Swagger.restMethodToSwaggerKeyMapping = {
|
|
96
|
+
"GET": "get",
|
|
97
|
+
"POST": "post",
|
|
98
|
+
"PUT": "put",
|
|
99
|
+
"DELETE": "delete"
|
|
100
|
+
};
|
|
101
|
+
// ------------------------------------------------------- //
|
|
102
|
+
// ------------------------------------------------------- //
|
|
103
|
+
// ----------------------- GENERIC ----------------------- //
|
|
104
|
+
// ------------------------------------------------------- //
|
|
105
|
+
// ------------------------------------------------------- //
|
|
106
|
+
_Swagger.addServer = (server) => _Swagger.apiDocument.servers.push(server);
|
|
107
|
+
// Call at init to add current server
|
|
108
|
+
_Swagger.generateOpenAPIDocument = () => JSON.parse(JSON.stringify(_Swagger.apiDocument, null, 2));
|
|
109
|
+
// Generates json to be served in api
|
|
110
|
+
_Swagger.apiDocument = // static document to be populated
|
|
111
|
+
{
|
|
112
|
+
openapi: "3.0.4",
|
|
113
|
+
servers: [],
|
|
114
|
+
info: { title: "Dynamically Generated API", version: "1.0.0" },
|
|
115
|
+
paths: {},
|
|
116
|
+
components: {
|
|
117
|
+
schemas: {},
|
|
118
|
+
securitySchemes: {
|
|
119
|
+
bearerAuth: {
|
|
120
|
+
type: "http",
|
|
121
|
+
scheme: "bearer",
|
|
122
|
+
bearerFormat: "JWT"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
security: [
|
|
127
|
+
{ "bearerAuth": [] }
|
|
128
|
+
]
|
|
129
|
+
};
|
|
130
|
+
// ------------------------------------------------------- //
|
|
131
|
+
// ------------------------------------------------------- //
|
|
132
|
+
// ----------------------- METHODS ----------------------- //
|
|
133
|
+
// ------------------------------------------------------- //
|
|
134
|
+
// ------------------------------------------------------- //
|
|
135
|
+
/**
|
|
136
|
+
* @Description
|
|
137
|
+
* - ❌ ROUTER-WRAPPER.
|
|
138
|
+
* - 🛠️ ADD-API-PATH
|
|
139
|
+
* - This method is not directly to insert inside the structur of addApiPath but is useful to create Schemas while not using the routerWrapper
|
|
140
|
+
*/
|
|
141
|
+
_Swagger.addSchema = (schema, properties) => {
|
|
142
|
+
if (!_Swagger.apiDocument.components || !_Swagger.apiDocument.components.schemas) _Swagger.apiDocument.components = { schemas: {} };
|
|
143
|
+
if (!_Swagger.apiDocument.components.schemas[schema]) _Swagger.apiDocument.components.schemas[schema] = {
|
|
144
|
+
type: "object",
|
|
145
|
+
properties
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* @Description
|
|
150
|
+
* - ❌ ROUTER-WRAPPER.
|
|
151
|
+
* - 🛠️ ADD-API-PATH
|
|
152
|
+
* - This method is thought to reduce the code in the addApiPath method
|
|
153
|
+
* - You can create a schema while declaring it and associating to the path calling this method
|
|
154
|
+
*/
|
|
155
|
+
_Swagger.getBasicPost = (schema, required, parameters, properties, description) => ({
|
|
156
|
+
responses: {},
|
|
157
|
+
parameters,
|
|
158
|
+
requestBody: {
|
|
159
|
+
required,
|
|
160
|
+
description,
|
|
161
|
+
schemaName: schema,
|
|
162
|
+
schema: {
|
|
163
|
+
[schema]: {
|
|
164
|
+
type: "object",
|
|
165
|
+
properties
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
/**
|
|
171
|
+
* @Description
|
|
172
|
+
* - ❌ **ROUTER-WRAPPER.**
|
|
173
|
+
* - 🛠️ **ADD-API-PATH**
|
|
174
|
+
* - This method is thought to reduce the code in the addApiPath method
|
|
175
|
+
*/
|
|
176
|
+
_Swagger.getBasicGet = (parameters) => ({
|
|
177
|
+
responses: {},
|
|
178
|
+
parameters
|
|
179
|
+
});
|
|
180
|
+
/**
|
|
181
|
+
* @Description
|
|
182
|
+
* - ❌ ROUTER-WRAPPER.
|
|
183
|
+
* - This method is useful if you don't want to use the router wrapper but add your swagger schema anyway.
|
|
184
|
+
* - **It is thought to be used inside the library**, iterating through the paths of the router wrapper.
|
|
185
|
+
* - **Devs can't use inside the parameters of a RouterWrapper constructor**
|
|
186
|
+
* - You can create the structure of a specified path and method, with a schema name that should be created elsewhere
|
|
187
|
+
*/
|
|
188
|
+
_Swagger.addSingleApiPath = (tag, basePath, _path, method, parameters, bodyObj, responses = {}) => {
|
|
189
|
+
const path2 = `${_Swagger.fromExpressParamsToSwagger(basePath)}${_Swagger.fromExpressParamsToSwagger(_path)}`;
|
|
190
|
+
const transcribedMethod = _Swagger.restMethodToSwaggerKeyMapping[method];
|
|
191
|
+
if (!_Swagger.apiDocument.paths[path2]) _Swagger.apiDocument.paths[path2] = {};
|
|
192
|
+
if (_Swagger.apiDocument.paths[path2][transcribedMethod]) return;
|
|
193
|
+
_Swagger.apiDocument.paths[path2][transcribedMethod] = {
|
|
194
|
+
responses,
|
|
195
|
+
parameters,
|
|
196
|
+
tags: [tag]
|
|
197
|
+
};
|
|
198
|
+
if (bodyObj) _Swagger.apiDocument.paths[path2][transcribedMethod].requestBody = {
|
|
199
|
+
required: _nullishCoalesce(bodyObj.required, () => ( false)),
|
|
200
|
+
description: bodyObj.description,
|
|
201
|
+
content: {
|
|
202
|
+
[_nullishCoalesce(bodyObj.comType, () => ( "application/json"))]: {
|
|
203
|
+
schema: { "$ref": "#/components/schemas/" + bodyObj.schema }
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
/**
|
|
209
|
+
* @Description
|
|
210
|
+
* - ❌ ROUTER-WRAPPER.
|
|
211
|
+
* - 🛠️ ADD-API-PATH
|
|
212
|
+
* - **This method is useful if you don't want to use the router wrapper but add your swagger schema anyway**.
|
|
213
|
+
* - You can use other other methods of this class to ease the writing
|
|
214
|
+
* - It is thought to create a full section of apis (hypotetically under one single tag) **while you create the schema in the meanwhile**
|
|
215
|
+
*/
|
|
216
|
+
_Swagger._addApiPath = (tag, basePath, options) => {
|
|
217
|
+
const finalPaths = {};
|
|
218
|
+
const finalSchemas = {};
|
|
219
|
+
for (const _path in options) {
|
|
220
|
+
const path2 = `${basePath}${_path}`;
|
|
221
|
+
if (_optionalChain([options, 'access', _3 => _3[_path], 'access', _4 => _4.get, 'optionalAccess', _5 => _5.tags])) options[_path].get.tags = [tag];
|
|
222
|
+
finalPaths[path2] = {
|
|
223
|
+
get: options[_path].get,
|
|
224
|
+
$ref: options[_path].$ref,
|
|
225
|
+
head: options[_path].head,
|
|
226
|
+
parameters: options[_path].parameters
|
|
227
|
+
};
|
|
228
|
+
if (options[_path].get) options[_path].get.tags = [tag];
|
|
229
|
+
if (options[_path].post && options[_path].post.requestBody) {
|
|
230
|
+
finalPaths[path2].post = {
|
|
231
|
+
responses: {},
|
|
232
|
+
parameters: options[_path].post.parameters,
|
|
233
|
+
tags: [tag],
|
|
234
|
+
summary: options[_path].post.summary,
|
|
235
|
+
requestBody: {
|
|
236
|
+
required: options[_path].post.requestBody.required,
|
|
237
|
+
description: options[_path].post.requestBody.description,
|
|
238
|
+
content: {
|
|
239
|
+
"application/json": { schema: { "$ref": "#/components/schemas/" + options[_path].post.requestBody.schemaName } }
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
for (const key in options[_path].post.requestBody.schema) {
|
|
244
|
+
if (!finalSchemas[key]) finalSchemas[key] = options[_path].post.requestBody.schema[key];
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (options[_path].put && options[_path].put.requestBody) {
|
|
248
|
+
finalPaths[path2].put = {
|
|
249
|
+
responses: {},
|
|
250
|
+
tags: [tag],
|
|
251
|
+
parameters: options[_path].put.parameters,
|
|
252
|
+
summary: options[_path].put.summary,
|
|
253
|
+
requestBody: {
|
|
254
|
+
required: options[_path].put.requestBody.required,
|
|
255
|
+
description: options[_path].put.requestBody.description,
|
|
256
|
+
content: {
|
|
257
|
+
"application/json": { schema: { "$ref": "#/components/schemas/" + options[_path].put.requestBody.schemaName } }
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
for (const key in options[_path].put.requestBody.schema) {
|
|
262
|
+
if (!finalSchemas[key]) finalSchemas[key] = options[_path].put.requestBody.schema[key];
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (options[_path].delete) {
|
|
266
|
+
finalPaths[path2].delete = {
|
|
267
|
+
responses: {},
|
|
268
|
+
tags: [tag],
|
|
269
|
+
parameters: options[_path].delete.parameters,
|
|
270
|
+
summary: options[_path].delete.summary
|
|
271
|
+
};
|
|
272
|
+
if (options[_path].delete.requestBody) {
|
|
273
|
+
const finalComType = _nullishCoalesce(options[_path].delete.requestBody.comType, () => ( "application/json"));
|
|
274
|
+
finalPaths[path2].delete.requestBody = {
|
|
275
|
+
required: options[_path].delete.requestBody.required,
|
|
276
|
+
description: options[_path].delete.requestBody.description,
|
|
277
|
+
content: {
|
|
278
|
+
[finalComType]: {
|
|
279
|
+
schema: { "$ref": "#/components/schemas/" + options[_path].delete.requestBody.schemaName }
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
for (const key in options[_path].delete.requestBody.schema) {
|
|
284
|
+
if (!finalSchemas[key]) finalSchemas[key] = options[_path].delete.requestBody.schema[key];
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
for (const path2 in finalPaths) {
|
|
290
|
+
for (const method in finalPaths[path2]) {
|
|
291
|
+
const methodKey = method;
|
|
292
|
+
if (!_Swagger.apiDocument.paths[path2]) _Swagger.apiDocument.paths[path2] = {};
|
|
293
|
+
if (!_Swagger.apiDocument.paths[path2][methodKey]) _Swagger.apiDocument.paths[path2][methodKey] = finalPaths[path2][methodKey];
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
for (const schema in finalSchemas) {
|
|
297
|
+
if (!_Swagger.apiDocument.components || !_Swagger.apiDocument.components.schemas) _Swagger.apiDocument.components = { schemas: {} };
|
|
298
|
+
if (!_Swagger.apiDocument.components.schemas[schema]) _Swagger.apiDocument.components.schemas[schema] = finalSchemas[schema];
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
// ------------------------------------------------------- //
|
|
302
|
+
// ------------------------------------------------------- //
|
|
303
|
+
// ------------------------ MICRO ------------------------ //
|
|
304
|
+
// ------------------------------------------------------- //
|
|
305
|
+
// ------------------------------------------------------- //
|
|
306
|
+
/**
|
|
307
|
+
* @Description
|
|
308
|
+
* - ✅ ROUTER-WRAPPER
|
|
309
|
+
* - Returns the tipical /:id parameter
|
|
310
|
+
*/
|
|
311
|
+
_Swagger.getIdParam = (pkLabel = "id") => ({ name: pkLabel, in: "path", required: true });
|
|
312
|
+
/**
|
|
313
|
+
* @Description
|
|
314
|
+
* - ✅ ROUTER-WRAPPER
|
|
315
|
+
* - Returns the tipical list pagination parameters
|
|
316
|
+
*/
|
|
317
|
+
_Swagger.getPaginationParams = (options) => {
|
|
318
|
+
const listOptions = {
|
|
319
|
+
page: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _6 => _6.page]), () => ( 0)),
|
|
320
|
+
pageSize: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _7 => _7.pageSize]), () => ( 10)),
|
|
321
|
+
order: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _8 => _8.order]), () => ( "ASC")),
|
|
322
|
+
orderBy: _optionalChain([options, 'optionalAccess', _9 => _9.orderBy])
|
|
323
|
+
};
|
|
324
|
+
return Object.entries(listOptions).map(([key, val]) => ({ name: key, in: "query", default: val, required: false }));
|
|
325
|
+
};
|
|
326
|
+
/**
|
|
327
|
+
* @Description
|
|
328
|
+
* - ✅ ROUTER-WRAPPER
|
|
329
|
+
* - Creates the swagger schema expected by your api
|
|
330
|
+
*/
|
|
331
|
+
_Swagger.createMultipartSchema = (name = "file", props) => ({
|
|
332
|
+
type: "object",
|
|
333
|
+
properties: {
|
|
334
|
+
[name]: { type: "string", format: "binary" },
|
|
335
|
+
..._nullishCoalesce(props, () => ( {}))
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
/**
|
|
339
|
+
* @Description
|
|
340
|
+
* - ✅ ROUTER-WRAPPER
|
|
341
|
+
* - Creates the swagger schema expected by your api
|
|
342
|
+
*/
|
|
343
|
+
_Swagger.createSchema = (props, required) => {
|
|
344
|
+
const finalSchemaObject = { type: "object", properties: {}, required };
|
|
345
|
+
for (const prop in props) {
|
|
346
|
+
if (typeof props[prop] === "string") finalSchemaObject.properties[prop] = { type: props[prop] };
|
|
347
|
+
else finalSchemaObject.properties[prop] = props[prop];
|
|
348
|
+
}
|
|
349
|
+
return finalSchemaObject;
|
|
350
|
+
};
|
|
351
|
+
var Swagger = _Swagger;
|
|
352
|
+
|
|
353
|
+
// src/DynamicDbRouter.ts
|
|
354
|
+
var _DynamicDbRouter = class _DynamicDbRouter {
|
|
355
|
+
};
|
|
356
|
+
_DynamicDbRouter.setTokenInstance = (tokenInstance) => {
|
|
357
|
+
_DynamicDbRouter.tokenInstance = tokenInstance;
|
|
358
|
+
};
|
|
359
|
+
_DynamicDbRouter.listOptionsKeys = ["pageSize", "page", "orderBy", "order"];
|
|
360
|
+
_DynamicDbRouter.getTypefromReflection = (typeormType) => _nullishCoalesce(_DynamicDbRouter.typeormToSwaggerMapper[typeormType], () => ( typeormType));
|
|
361
|
+
_DynamicDbRouter.typeormToSwaggerMapper = {
|
|
362
|
+
"text": "string",
|
|
363
|
+
"char varying": "string",
|
|
364
|
+
"char": "string",
|
|
365
|
+
"character varying": "string",
|
|
366
|
+
"character": "string",
|
|
367
|
+
"varchar": "string",
|
|
368
|
+
"varying character": "string",
|
|
369
|
+
"date": "date",
|
|
370
|
+
"datemultirange": "date",
|
|
371
|
+
"datetime": "date",
|
|
372
|
+
"int": "number",
|
|
373
|
+
"integer": "number",
|
|
374
|
+
"smallint": "number",
|
|
375
|
+
"bigint": "number",
|
|
376
|
+
"float": "number",
|
|
377
|
+
"real": "number",
|
|
378
|
+
"long": "number",
|
|
379
|
+
"double": "number",
|
|
380
|
+
"bit": "boolean",
|
|
381
|
+
"bool": "boolean",
|
|
382
|
+
"blob": "file"
|
|
383
|
+
};
|
|
384
|
+
_DynamicDbRouter.createDbRouter = (options) => {
|
|
385
|
+
if (!options.primaryKey) options.primaryKey = "id";
|
|
386
|
+
const avoidList = _nullishCoalesce(options.avoid, () => ( []));
|
|
387
|
+
if (!avoidList.includes("LIST")) options.router.get("/", async (req, res) => {
|
|
388
|
+
try {
|
|
389
|
+
let payload = null;
|
|
390
|
+
if (options.secure) {
|
|
391
|
+
if (_DynamicDbRouter.tokenInstance) payload = await _DynamicDbRouter.tokenInstance.authorize(req);
|
|
392
|
+
else throw new Error("Api secure option on but no token instance has been provided in the starter");
|
|
393
|
+
}
|
|
394
|
+
const listOptions = {};
|
|
395
|
+
for (const key in req.query) {
|
|
396
|
+
if (_DynamicDbRouter.listOptionsKeys.includes(key)) listOptions[key] = req.query[key];
|
|
397
|
+
}
|
|
398
|
+
const searchQuery = {};
|
|
399
|
+
for (const param of _nullishCoalesce(options.getParameters, () => ( []))) {
|
|
400
|
+
const val = _nullishCoalesce(req.query[param.name], () => ( void 0));
|
|
401
|
+
if (param.required && !val) throw new Error(`Params Error: ${param.name} required`);
|
|
402
|
+
if (val !== void 0) {
|
|
403
|
+
if (param.like) searchQuery[param.name] = _typeorm.Like.call(void 0, `%${val}%`);
|
|
404
|
+
else searchQuery[param.name] = _typeorm.Equal.call(void 0, val);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
const secureSearchQuery = _DynamicDbRouter.setSecureParams("LIST", payload, options.secure);
|
|
408
|
+
const { page, pageSize, order, orderBy } = listOptions;
|
|
409
|
+
const entities = await options.entity.find({
|
|
410
|
+
where: { ...searchQuery, ...secureSearchQuery },
|
|
411
|
+
take: _nullishCoalesce(pageSize, () => ( 0)),
|
|
412
|
+
skip: (_nullishCoalesce(page, () => ( 0))) * (_nullishCoalesce(pageSize, () => ( 0))),
|
|
413
|
+
order: { [_nullishCoalesce(orderBy, () => ( options.primaryKey))]: _nullishCoalesce(order, () => ( "ASC")) },
|
|
414
|
+
select: options.returningProps
|
|
415
|
+
});
|
|
416
|
+
res.send(entities);
|
|
417
|
+
} catch (err) {
|
|
418
|
+
errorCatcher(res, err, void 0, `[GET] / => ${_nullishCoalesce(err.message, () => ( err))}`);
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
if (!avoidList.includes("GET")) options.router.get("/:id", async (req, res) => {
|
|
422
|
+
try {
|
|
423
|
+
let payload = null;
|
|
424
|
+
if (options.secure) {
|
|
425
|
+
if (_DynamicDbRouter.tokenInstance) payload = await _DynamicDbRouter.tokenInstance.authorize(req);
|
|
426
|
+
else throw new Error("Api secure option on but no token instance has been provided in the starter");
|
|
427
|
+
}
|
|
428
|
+
const secureSearchQuery = _DynamicDbRouter.setSecureParams("GET", payload, options.secure);
|
|
429
|
+
const id = req.params.id;
|
|
430
|
+
const singleEntity = await options.entity.findOne({
|
|
431
|
+
where: { [options.primaryKey]: _typeorm.Equal.call(void 0, id), ...secureSearchQuery },
|
|
432
|
+
select: options.returningProps
|
|
433
|
+
});
|
|
434
|
+
res.send(singleEntity);
|
|
435
|
+
} catch (err) {
|
|
436
|
+
errorCatcher(res, err, void 0, `[GET] /:id => ${_nullishCoalesce(err.message, () => ( err))}`);
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
if (!avoidList.includes("POST")) options.router.post("/", async (req, res) => {
|
|
440
|
+
try {
|
|
441
|
+
let payload = null;
|
|
442
|
+
if (options.secure) {
|
|
443
|
+
if (_DynamicDbRouter.tokenInstance) payload = await _DynamicDbRouter.tokenInstance.authorize(req);
|
|
444
|
+
else throw new Error("Api secure option on but no token instance has been provided in the starter");
|
|
445
|
+
}
|
|
446
|
+
const secureSearchQuery = _DynamicDbRouter.setSecureParams("POST", payload, options.secure);
|
|
447
|
+
const finalBody = {};
|
|
448
|
+
const body = req.body;
|
|
449
|
+
for (const key in body) {
|
|
450
|
+
if (key !== options.primaryKey && (!options.bodyParameters || _optionalChain([options, 'access', _10 => _10.bodyParameters, 'access', _11 => _11.properties, 'optionalAccess', _12 => _12[key]]))) {
|
|
451
|
+
finalBody[key] = body[key];
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
for (const key in secureSearchQuery) {
|
|
455
|
+
finalBody[key] = secureSearchQuery[key];
|
|
456
|
+
}
|
|
457
|
+
const newEntity = await options.entity.create(finalBody).save();
|
|
458
|
+
const result = {};
|
|
459
|
+
for (const key in newEntity) {
|
|
460
|
+
if (!options.returningProps || options.returningProps.includes(key)) result[key] = newEntity[key];
|
|
461
|
+
}
|
|
462
|
+
res.send(result);
|
|
463
|
+
} catch (err) {
|
|
464
|
+
errorCatcher(res, err, void 0, `[POST] / => ${_nullishCoalesce(err.message, () => ( err))}`);
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
if (!avoidList.includes("PUT")) options.router.put("/:id", async (req, res) => {
|
|
468
|
+
try {
|
|
469
|
+
let payload = null;
|
|
470
|
+
if (options.secure) {
|
|
471
|
+
if (_DynamicDbRouter.tokenInstance) payload = await _DynamicDbRouter.tokenInstance.authorize(req);
|
|
472
|
+
else throw new Error("Api secure option on but no token instance has been provided in the starter");
|
|
473
|
+
}
|
|
474
|
+
const secureSearchQuery = _DynamicDbRouter.setSecureParams("PUT", payload, options.secure);
|
|
475
|
+
const id = req.params.id;
|
|
476
|
+
const body = req.body;
|
|
477
|
+
const singleEntity = await options.entity.findOneBy({ [options.primaryKey]: _typeorm.Equal.call(void 0, id) });
|
|
478
|
+
if (singleEntity === null) throw new Error("Entity not found");
|
|
479
|
+
for (const key in body) {
|
|
480
|
+
if (key !== options.primaryKey && key in singleEntity) {
|
|
481
|
+
if (!options.bodyParameters || _optionalChain([options, 'access', _13 => _13.bodyParameters, 'access', _14 => _14.properties, 'optionalAccess', _15 => _15[key]])) {
|
|
482
|
+
singleEntity[key] = body[key];
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
for (const key in secureSearchQuery) {
|
|
487
|
+
singleEntity[key] = body[key];
|
|
488
|
+
}
|
|
489
|
+
await options.entity.save(singleEntity);
|
|
490
|
+
const result = {};
|
|
491
|
+
for (const key in singleEntity) {
|
|
492
|
+
if (!options.returningProps || options.returningProps.includes(key)) result[key] = singleEntity[key];
|
|
493
|
+
}
|
|
494
|
+
res.send(result);
|
|
495
|
+
} catch (err) {
|
|
496
|
+
errorCatcher(res, err, void 0, `[PUT] /:id => ${_nullishCoalesce(err.message, () => ( err))}`);
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
if (!avoidList.includes("DELETE")) options.router.delete("/:id", async (req, res) => {
|
|
500
|
+
try {
|
|
501
|
+
let payload = null;
|
|
502
|
+
if (options.secure) {
|
|
503
|
+
if (_DynamicDbRouter.tokenInstance) payload = await _DynamicDbRouter.tokenInstance.authorize(req);
|
|
504
|
+
else throw new Error("Api secure option on but no token instance has been provided in the starter");
|
|
505
|
+
}
|
|
506
|
+
const secureSearchQuery = _DynamicDbRouter.setSecureParams("DELETE", payload, options.secure);
|
|
507
|
+
const id = req.params.id;
|
|
508
|
+
const singleEntity = await options.entity.findOneBy({ [options.primaryKey]: _typeorm.Equal.call(void 0, id), ...secureSearchQuery });
|
|
509
|
+
if (singleEntity === null) throw new Error("Entity not found");
|
|
510
|
+
await options.entity.remove(singleEntity);
|
|
511
|
+
const result = {};
|
|
512
|
+
for (const key in singleEntity) {
|
|
513
|
+
if (!options.returningProps || options.returningProps.includes(key)) result[key] = singleEntity[key];
|
|
514
|
+
}
|
|
515
|
+
res.send(singleEntity);
|
|
516
|
+
} catch (err) {
|
|
517
|
+
errorCatcher(res, err, void 0, `[DELETE] /:id => ${_nullishCoalesce(err.message, () => ( err))}`);
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
return options.router;
|
|
521
|
+
};
|
|
522
|
+
_DynamicDbRouter.addDbRouterSwagger = (options) => {
|
|
523
|
+
if (!options.primaryKey) options.primaryKey = "id";
|
|
524
|
+
const avoidList = _nullishCoalesce(options.avoid, () => ( []));
|
|
525
|
+
try {
|
|
526
|
+
let schemaProperties = {};
|
|
527
|
+
if (options.bodyParameters && options.bodyParameters) {
|
|
528
|
+
const defaultOverridingSchema = options.bodyParameters;
|
|
529
|
+
for (const param in defaultOverridingSchema.properties) {
|
|
530
|
+
const paramValue = defaultOverridingSchema.properties[param];
|
|
531
|
+
schemaProperties[param] = {
|
|
532
|
+
type: paramValue.type,
|
|
533
|
+
required: paramValue.required
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
} else {
|
|
537
|
+
const metadata = DbConnector.getDataSource().getMetadata(options.entity);
|
|
538
|
+
for (const col of metadata.columns) {
|
|
539
|
+
if (col.propertyName === options.primaryKey) continue;
|
|
540
|
+
schemaProperties[col.propertyName] = {
|
|
541
|
+
type: _DynamicDbRouter.getTypefromReflection(col.type.toString())
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
if (!avoidList.includes("POST") || !avoidList.includes("PUT")) {
|
|
546
|
+
Swagger.addSchema(options.tag, schemaProperties);
|
|
547
|
+
}
|
|
548
|
+
} catch (err) {
|
|
549
|
+
if (err instanceof _typeorm.EntityMetadataNotFoundError)
|
|
550
|
+
log.logError(`[${options.entity.name}] Metadata required for db routing but not connected on the database`);
|
|
551
|
+
}
|
|
552
|
+
if (!avoidList.includes("LIST")) {
|
|
553
|
+
const listOptions = { page: 0, pageSize: 10, order: "ASC", orderBy: options.primaryKey };
|
|
554
|
+
Swagger.addSingleApiPath(options.tag, options.basePath, "/", "GET", [
|
|
555
|
+
...Object.entries(listOptions).map(([key, val]) => ({ name: key, in: "query", default: val, required: false })),
|
|
556
|
+
..._nullishCoalesce(options.getParameters, () => ( []))
|
|
557
|
+
]);
|
|
558
|
+
}
|
|
559
|
+
if (!avoidList.includes("GET")) {
|
|
560
|
+
Swagger.addSingleApiPath(options.tag, options.basePath, `/{${options.primaryKey}}`, "GET", [
|
|
561
|
+
{ name: options.primaryKey, in: "path", required: true },
|
|
562
|
+
..._nullishCoalesce(options.getParameters, () => ( []))
|
|
563
|
+
]);
|
|
564
|
+
}
|
|
565
|
+
if (!avoidList.includes("POST")) {
|
|
566
|
+
Swagger.addSingleApiPath(options.tag, options.basePath, "/", "POST", void 0, { schema: options.tag });
|
|
567
|
+
}
|
|
568
|
+
if (!avoidList.includes("PUT")) {
|
|
569
|
+
Swagger.addSingleApiPath(
|
|
570
|
+
options.tag,
|
|
571
|
+
options.basePath,
|
|
572
|
+
`/{${options.primaryKey}}`,
|
|
573
|
+
"PUT",
|
|
574
|
+
[{ name: options.primaryKey, in: "path", required: true }],
|
|
575
|
+
{ schema: options.tag }
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
if (!avoidList.includes("DELETE")) {
|
|
579
|
+
Swagger.addSingleApiPath(options.tag, options.basePath, `/{${options.primaryKey}}`, "DELETE", [
|
|
580
|
+
{ name: options.primaryKey, in: "path", required: true }
|
|
581
|
+
]);
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
_DynamicDbRouter.setSecureParams = (method, payload, secure) => {
|
|
585
|
+
const searchQuery = {};
|
|
586
|
+
if (secure !== void 0 && typeof secure === "object" && payload !== null) {
|
|
587
|
+
for (const secureParam in secure) {
|
|
588
|
+
const secureParamVal = secure[secureParam];
|
|
589
|
+
if (secureParamVal.methods === "*" || secureParamVal.methods.includes(method) && payload[secureParamVal.tokenKey]) {
|
|
590
|
+
if (["LIST", "GET", "DELETE"].includes(method)) searchQuery[secureParam] = _typeorm.Equal.call(void 0, payload[secureParamVal.tokenKey]);
|
|
591
|
+
else searchQuery[secureParam] = payload[secureParamVal.tokenKey];
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return searchQuery;
|
|
596
|
+
};
|
|
597
|
+
var DynamicDbRouter = _DynamicDbRouter;
|
|
598
|
+
|
|
599
|
+
// src/RouterWrapper.ts
|
|
600
|
+
var RouterWrapper = class {
|
|
601
|
+
constructor(data) {
|
|
602
|
+
this.createExpressRouter = () => {
|
|
603
|
+
const newRouter = _express.Router.call(void 0, );
|
|
604
|
+
if (this.data.dbRouting) {
|
|
605
|
+
const avoidOptionsForDefinedApis = [];
|
|
606
|
+
if (_optionalChain([this, 'access', _16 => _16.data, 'access', _17 => _17.apis, 'optionalAccess', _18 => _18["/"], 'optionalAccess', _19 => _19.GET])) avoidOptionsForDefinedApis.push("LIST");
|
|
607
|
+
if (_optionalChain([this, 'access', _20 => _20.data, 'access', _21 => _21.apis, 'optionalAccess', _22 => _22["/:id"], 'optionalAccess', _23 => _23.GET])) avoidOptionsForDefinedApis.push("GET");
|
|
608
|
+
if (_optionalChain([this, 'access', _24 => _24.data, 'access', _25 => _25.apis, 'optionalAccess', _26 => _26["/"], 'optionalAccess', _27 => _27.POST])) avoidOptionsForDefinedApis.push("POST");
|
|
609
|
+
if (_optionalChain([this, 'access', _28 => _28.data, 'access', _29 => _29.apis, 'optionalAccess', _30 => _30["/:id"], 'optionalAccess', _31 => _31.PUT])) avoidOptionsForDefinedApis.push("PUT");
|
|
610
|
+
if (_optionalChain([this, 'access', _32 => _32.data, 'access', _33 => _33.apis, 'optionalAccess', _34 => _34["/:id"], 'optionalAccess', _35 => _35.DELETE])) avoidOptionsForDefinedApis.push("DELETE");
|
|
611
|
+
for (const avoid of _nullishCoalesce(this.data.dbRouting.avoid, () => ( []))) {
|
|
612
|
+
if (!avoidOptionsForDefinedApis.includes(avoid)) avoidOptionsForDefinedApis.push(avoid);
|
|
613
|
+
}
|
|
614
|
+
const { entity, bodyParameters, getParameters, primaryKey, secure, returningProps } = this.data.dbRouting;
|
|
615
|
+
DynamicDbRouter.createDbRouter({
|
|
616
|
+
entity,
|
|
617
|
+
bodyParameters,
|
|
618
|
+
getParameters,
|
|
619
|
+
primaryKey,
|
|
620
|
+
router: newRouter,
|
|
621
|
+
basePath: this.data.basePath,
|
|
622
|
+
tag: this.data.tag,
|
|
623
|
+
avoid: avoidOptionsForDefinedApis,
|
|
624
|
+
secure,
|
|
625
|
+
returningProps
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
if (this.data.swaggerNewSchemas) {
|
|
629
|
+
for (const schema in this.data.swaggerNewSchemas) Swagger.addSchema(schema, this.data.swaggerNewSchemas[schema].properties);
|
|
630
|
+
}
|
|
631
|
+
for (const _path in _nullishCoalesce(this.data.apis, () => ( {}))) {
|
|
632
|
+
const path2 = _path.startsWith("/") ? _path : `/${_path}`;
|
|
633
|
+
if (!this.data.apis || !this.data.apis[path2]) continue;
|
|
634
|
+
for (const method in this.data.apis[path2]) {
|
|
635
|
+
if ((_nullishCoalesce(_optionalChain([this, 'access', _36 => _36.data, 'access', _37 => _37.apis, 'optionalAccess', _38 => _38[path2], 'optionalAccess', _39 => _39[method]]), () => ( void 0))) === void 0) continue;
|
|
636
|
+
const currentMethod = this.data.apis[path2][method];
|
|
637
|
+
const middlewares = _nullishCoalesce(currentMethod.middlewares, () => ( []));
|
|
638
|
+
const callBackFunction = async (req, res) => {
|
|
639
|
+
try {
|
|
640
|
+
const handlerRes = await currentMethod.handler(req, res);
|
|
641
|
+
if (handlerRes.contentType) {
|
|
642
|
+
res.set("Content-Type", handlerRes.contentType);
|
|
643
|
+
res.status(_nullishCoalesce(handlerRes.status, () => ( 200))).send(handlerRes.result);
|
|
644
|
+
} else if (typeof handlerRes.result === "object") res.status(handlerRes.status).json(handlerRes.result);
|
|
645
|
+
else res.status(handlerRes.status).send(handlerRes.result);
|
|
646
|
+
} catch (err) {
|
|
647
|
+
fullLogNok("api", `[${method}] ${path2} => ${_nullishCoalesce(err.message, () => ( err))}`);
|
|
648
|
+
res.status(500).send(_nullishCoalesce(_optionalChain([err, 'optionalAccess', _40 => _40.message]), () => ( err)));
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
if (method === "GET") newRouter.get(path2, middlewares, callBackFunction);
|
|
652
|
+
else if (method === "POST") newRouter.post(path2, middlewares, callBackFunction);
|
|
653
|
+
else if (method === "PUT") newRouter.put(path2, middlewares, callBackFunction);
|
|
654
|
+
else if (method === "DELETE") newRouter.delete(path2, middlewares, callBackFunction);
|
|
655
|
+
Swagger.addSingleApiPath(
|
|
656
|
+
this.data.tag,
|
|
657
|
+
this.data.basePath,
|
|
658
|
+
path2,
|
|
659
|
+
method,
|
|
660
|
+
currentMethod.swaggerParameters,
|
|
661
|
+
currentMethod.swaggerBody,
|
|
662
|
+
currentMethod.swaggerResponses
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
if (this.data.dbRouting) {
|
|
667
|
+
const { entity, bodyParameters, getParameters, primaryKey } = this.data.dbRouting;
|
|
668
|
+
DynamicDbRouter.addDbRouterSwagger({
|
|
669
|
+
entity,
|
|
670
|
+
bodyParameters,
|
|
671
|
+
getParameters,
|
|
672
|
+
primaryKey,
|
|
673
|
+
router: newRouter,
|
|
674
|
+
basePath: this.data.basePath,
|
|
675
|
+
tag: this.data.tag,
|
|
676
|
+
avoid: this.data.dbRouting.avoid,
|
|
677
|
+
secure: _optionalChain([this, 'access', _41 => _41.data, 'access', _42 => _42.dbRouting, 'optionalAccess', _43 => _43.secure])
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
return newRouter;
|
|
681
|
+
};
|
|
682
|
+
this.data = data;
|
|
683
|
+
this.basePath = data.basePath.startsWith("/") ? data.basePath : `/${data.basePath}`;
|
|
684
|
+
}
|
|
685
|
+
};
|
|
686
|
+
|
|
687
|
+
// src/Starter.ts
|
|
688
|
+
|
|
689
|
+
var _http = require('http'); var _http2 = _interopRequireDefault(_http);
|
|
690
|
+
var _path2 = require('path'); var _path3 = _interopRequireDefault(_path2);
|
|
691
|
+
var _swaggeruiexpress = require('swagger-ui-express'); var _swaggeruiexpress2 = _interopRequireDefault(_swaggeruiexpress);
|
|
692
|
+
var Starter = class {
|
|
693
|
+
constructor(options) {
|
|
694
|
+
this.init = async (options) => {
|
|
695
|
+
const app = _express2.default.call(void 0, );
|
|
696
|
+
if (options.db) {
|
|
697
|
+
await this.initDb(options.projectConfig, options.db.entities, options.db.migrations, options.db.sync);
|
|
698
|
+
if (options.db.afterDbConnection) await options.db.afterDbConnection();
|
|
699
|
+
}
|
|
700
|
+
for (const plugin of _nullishCoalesce(options.plugins, () => ( []))) app.use(plugin);
|
|
701
|
+
for (const router of _nullishCoalesce(options.routers, () => ( []))) app.use(router.basePath, router.createExpressRouter());
|
|
702
|
+
if (options.swagger === void 0 || options.swagger) {
|
|
703
|
+
Swagger.addServer({ url: `http://127.0.0.1:${options.projectConfig.SERVER_PORT}` });
|
|
704
|
+
app.get("/swagger", (_, res) => {
|
|
705
|
+
const openAPIDocument = Swagger.generateOpenAPIDocument();
|
|
706
|
+
res.json(openAPIDocument);
|
|
707
|
+
});
|
|
708
|
+
app.use("/swagger-ui", _swaggeruiexpress2.default.serve, _swaggeruiexpress2.default.setup(void 0, {
|
|
709
|
+
swaggerOptions: {
|
|
710
|
+
url: "/swagger"
|
|
711
|
+
}
|
|
712
|
+
}));
|
|
713
|
+
}
|
|
714
|
+
if (options.tokenOptions) DynamicDbRouter.setTokenInstance(options.tokenOptions.tokenInstance);
|
|
715
|
+
if (options.clientPath) {
|
|
716
|
+
const clientPath = _path3.default.resolve(process.cwd(), "client");
|
|
717
|
+
app.use(_express2.default.static(clientPath));
|
|
718
|
+
app.get("/apiUrl", (_, res) => res.send(options.projectConfig.API_URL));
|
|
719
|
+
if (_optionalChain([options, 'access', _44 => _44.tokenOptions, 'optionalAccess', _45 => _45.api])) {
|
|
720
|
+
app.get(_nullishCoalesce(options.tokenOptions.api.path, () => ( "/api/auth")), options.tokenOptions.api.callback);
|
|
721
|
+
}
|
|
722
|
+
app.get("*", (_, res) => {
|
|
723
|
+
res.sendFile(_path3.default.join(clientPath, "index.html"));
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
if (options.socket === void 0 || options.socket === false) {
|
|
727
|
+
if (options.beforeStartListening) options.beforeStartListening(app);
|
|
728
|
+
app.listen(options.projectConfig.SERVER_PORT, () => log.base("Server started.", `Listening on port ${options.projectConfig.SERVER_PORT}`));
|
|
729
|
+
} else if (options.socket === true) {
|
|
730
|
+
const server = _http2.default.createServer(app);
|
|
731
|
+
if (options.beforeStartListening) options.beforeStartListening(app, server);
|
|
732
|
+
server.listen(options.projectConfig.SERVER_PORT, () => log.base("Server started.", `Listening on port ${options.projectConfig.SERVER_PORT}`));
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
this.initDb = async (projectConfig, entities, migrations, sync) => {
|
|
736
|
+
const connector = new DbConnector(projectConfig);
|
|
737
|
+
await connector.connect(entities, migrations, sync);
|
|
738
|
+
};
|
|
739
|
+
try {
|
|
740
|
+
log.setFilePath(options.projectConfig.ERROR_FILE_PATH);
|
|
741
|
+
this.init(options);
|
|
742
|
+
} catch (err) {
|
|
743
|
+
log.logError(err);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
|
|
748
|
+
// src/Token.ts
|
|
749
|
+
var _crypto = require('crypto'); var _crypto2 = _interopRequireDefault(_crypto);
|
|
750
|
+
var _nodejose = require('node-jose'); var _nodejose2 = _interopRequireDefault(_nodejose);
|
|
751
|
+
var Token = class {
|
|
752
|
+
constructor(tokenPayload) {
|
|
753
|
+
this.keyStore = null;
|
|
754
|
+
// Metodo per autorizzare una richiesta
|
|
755
|
+
this.authorize = async (req) => {
|
|
756
|
+
const token = _nullishCoalesce(_optionalChain([req, 'access', _46 => _46.headers, 'access', _47 => _47.authorization, 'optionalAccess', _48 => _48.split, 'call', _49 => _49("Bearer "), 'optionalAccess', _50 => _50[1]]), () => ( null));
|
|
757
|
+
if (token === null) throw new Error("UNAUTH");
|
|
758
|
+
const payload = await this.verifyJWE(token);
|
|
759
|
+
return payload;
|
|
760
|
+
};
|
|
761
|
+
if (!tokenPayload.SECRET_KEY) throw new Error("SECRET_KEY is required if you want to use the Token Class");
|
|
762
|
+
this.SECRET_KEY = tokenPayload.SECRET_KEY;
|
|
763
|
+
this.ExpTime = tokenPayload.ExpTime;
|
|
764
|
+
this.EncAlgorithm = tokenPayload.EncAlgorithm;
|
|
765
|
+
this.KeyLength = tokenPayload.KeyLength;
|
|
766
|
+
}
|
|
767
|
+
// Inizializza la KeyStore
|
|
768
|
+
async getKey() {
|
|
769
|
+
if (!this.keyStore) {
|
|
770
|
+
this.keyStore = _nodejose2.default.JWK.createKeyStore();
|
|
771
|
+
const encryptionKey = this.deriveEncryptionKey();
|
|
772
|
+
const key = await _nodejose2.default.JWK.asKey({
|
|
773
|
+
kty: "oct",
|
|
774
|
+
k: _nodejose2.default.util.base64url.encode(encryptionKey)
|
|
775
|
+
});
|
|
776
|
+
await this.keyStore.add(key);
|
|
777
|
+
}
|
|
778
|
+
return this.keyStore.all({ use: "enc" })[0];
|
|
779
|
+
}
|
|
780
|
+
// Metodo per derivare chiave di cifratura
|
|
781
|
+
deriveEncryptionKey() {
|
|
782
|
+
return _crypto2.default.createHash("sha256").update(this.SECRET_KEY).digest().slice(0, this.KeyLength);
|
|
783
|
+
}
|
|
784
|
+
// Metodo per generare token cifrato (JWE)
|
|
785
|
+
async generateJWE(payload) {
|
|
786
|
+
const key = await this.getKey();
|
|
787
|
+
const input = Buffer.from(JSON.stringify({
|
|
788
|
+
...payload,
|
|
789
|
+
iat: Math.floor(Date.now() / 1e3),
|
|
790
|
+
exp: Math.floor(Date.now() / 1e3) + this.ExpTime
|
|
791
|
+
}));
|
|
792
|
+
const jwe = await _nodejose2.default.JWE.createEncrypt({
|
|
793
|
+
format: "compact",
|
|
794
|
+
fields: { alg: "dir", enc: this.EncAlgorithm }
|
|
795
|
+
}, key).update(input).final();
|
|
796
|
+
return jwe;
|
|
797
|
+
}
|
|
798
|
+
// Metodo per decifrare token JWE
|
|
799
|
+
async verifyJWE(token) {
|
|
800
|
+
try {
|
|
801
|
+
const key = await this.getKey();
|
|
802
|
+
const result = await _nodejose2.default.JWE.createDecrypt(key).decrypt(token);
|
|
803
|
+
const payload = JSON.parse(result.plaintext.toString());
|
|
804
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
805
|
+
if (payload.exp && payload.exp < now) {
|
|
806
|
+
throw new Error("Token expired");
|
|
807
|
+
}
|
|
808
|
+
return payload;
|
|
809
|
+
} catch (error) {
|
|
810
|
+
throw new Error("Token decryption failed");
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
|
|
820
|
+
|
|
821
|
+
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
|
|
825
|
+
exports.RouterWrapper = RouterWrapper; exports.Starter = Starter; exports.Swagger = Swagger; exports.Token = Token; exports.apiNok = apiNok; exports.apiOk = apiOk; exports.errorCatcher = errorCatcher; exports.fullLogNok = fullLogNok; exports.fullLogOk = fullLogOk; exports.log = log;
|