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.mjs
ADDED
|
@@ -0,0 +1,825 @@
|
|
|
1
|
+
// src/RouterWrapper.ts
|
|
2
|
+
import { Router } from "express";
|
|
3
|
+
|
|
4
|
+
// src/_utils.ts
|
|
5
|
+
import { Logger } from "utils-logger-av";
|
|
6
|
+
var MyLogger = class extends 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 = error?.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 = (errorsList ?? {})[err.message] ?? null;
|
|
34
|
+
if (!error) res.status(500).send({ message: err.message });
|
|
35
|
+
else res.status(error.status ?? 500).send({ message: error.responseMessage ?? err.message });
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// src/DynamicDbRouter.ts
|
|
39
|
+
import { EntityMetadataNotFoundError, Equal, Like } from "typeorm";
|
|
40
|
+
|
|
41
|
+
// src/DbConnector.ts
|
|
42
|
+
import "reflect-metadata";
|
|
43
|
+
import { DataSource } from "typeorm";
|
|
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 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: sync ?? false,
|
|
58
|
+
logging: false,
|
|
59
|
+
migrations
|
|
60
|
+
});
|
|
61
|
+
await AppDataSource.initialize();
|
|
62
|
+
if (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: bodyObj.required ?? false,
|
|
200
|
+
description: bodyObj.description,
|
|
201
|
+
content: {
|
|
202
|
+
[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 (options[_path].get?.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 = 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: options?.page ?? 0,
|
|
320
|
+
pageSize: options?.pageSize ?? 10,
|
|
321
|
+
order: options?.order ?? "ASC",
|
|
322
|
+
orderBy: options?.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
|
+
...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) => _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 = 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 options.getParameters ?? []) {
|
|
400
|
+
const val = 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] = Like(`%${val}%`);
|
|
404
|
+
else searchQuery[param.name] = Equal(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: pageSize ?? 0,
|
|
412
|
+
skip: (page ?? 0) * (pageSize ?? 0),
|
|
413
|
+
order: { [orderBy ?? options.primaryKey]: order ?? "ASC" },
|
|
414
|
+
select: options.returningProps
|
|
415
|
+
});
|
|
416
|
+
res.send(entities);
|
|
417
|
+
} catch (err) {
|
|
418
|
+
errorCatcher(res, err, void 0, `[GET] / => ${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]: Equal(id), ...secureSearchQuery },
|
|
432
|
+
select: options.returningProps
|
|
433
|
+
});
|
|
434
|
+
res.send(singleEntity);
|
|
435
|
+
} catch (err) {
|
|
436
|
+
errorCatcher(res, err, void 0, `[GET] /:id => ${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 || options.bodyParameters.properties?.[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] / => ${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]: Equal(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 || options.bodyParameters.properties?.[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 => ${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]: Equal(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 => ${err.message ?? err}`);
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
return options.router;
|
|
521
|
+
};
|
|
522
|
+
_DynamicDbRouter.addDbRouterSwagger = (options) => {
|
|
523
|
+
if (!options.primaryKey) options.primaryKey = "id";
|
|
524
|
+
const avoidList = 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 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
|
+
...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
|
+
...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] = Equal(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 = Router();
|
|
604
|
+
if (this.data.dbRouting) {
|
|
605
|
+
const avoidOptionsForDefinedApis = [];
|
|
606
|
+
if (this.data.apis?.["/"]?.GET) avoidOptionsForDefinedApis.push("LIST");
|
|
607
|
+
if (this.data.apis?.["/:id"]?.GET) avoidOptionsForDefinedApis.push("GET");
|
|
608
|
+
if (this.data.apis?.["/"]?.POST) avoidOptionsForDefinedApis.push("POST");
|
|
609
|
+
if (this.data.apis?.["/:id"]?.PUT) avoidOptionsForDefinedApis.push("PUT");
|
|
610
|
+
if (this.data.apis?.["/:id"]?.DELETE) avoidOptionsForDefinedApis.push("DELETE");
|
|
611
|
+
for (const avoid of 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 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 ((this.data.apis?.[path2]?.[method] ?? void 0) === void 0) continue;
|
|
636
|
+
const currentMethod = this.data.apis[path2][method];
|
|
637
|
+
const middlewares = 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(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} => ${err.message ?? err}`);
|
|
648
|
+
res.status(500).send(err?.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: this.data.dbRouting?.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
|
+
import express from "express";
|
|
689
|
+
import http from "http";
|
|
690
|
+
import path from "path";
|
|
691
|
+
import swaggerUi from "swagger-ui-express";
|
|
692
|
+
var Starter = class {
|
|
693
|
+
constructor(options) {
|
|
694
|
+
this.init = async (options) => {
|
|
695
|
+
const app = express();
|
|
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 options.plugins ?? []) app.use(plugin);
|
|
701
|
+
for (const router of 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", swaggerUi.serve, swaggerUi.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 = path.resolve(process.cwd(), "client");
|
|
717
|
+
app.use(express.static(clientPath));
|
|
718
|
+
app.get("/apiUrl", (_, res) => res.send(options.projectConfig.API_URL));
|
|
719
|
+
if (options.tokenOptions?.api) {
|
|
720
|
+
app.get(options.tokenOptions.api.path ?? "/api/auth", options.tokenOptions.api.callback);
|
|
721
|
+
}
|
|
722
|
+
app.get("*", (_, res) => {
|
|
723
|
+
res.sendFile(path.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 = http.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
|
+
import crypto from "crypto";
|
|
750
|
+
import jose from "node-jose";
|
|
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 = req.headers.authorization?.split("Bearer ")?.[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 = jose.JWK.createKeyStore();
|
|
771
|
+
const encryptionKey = this.deriveEncryptionKey();
|
|
772
|
+
const key = await jose.JWK.asKey({
|
|
773
|
+
kty: "oct",
|
|
774
|
+
k: jose.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 crypto.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 jose.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 jose.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
|
+
export {
|
|
815
|
+
RouterWrapper,
|
|
816
|
+
Starter,
|
|
817
|
+
Swagger,
|
|
818
|
+
Token,
|
|
819
|
+
apiNok,
|
|
820
|
+
apiOk,
|
|
821
|
+
errorCatcher,
|
|
822
|
+
fullLogNok,
|
|
823
|
+
fullLogOk,
|
|
824
|
+
log
|
|
825
|
+
};
|