@ecopex/ecopex-framework 1.0.9 → 1.0.10
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/config/swagger.js +4 -3
- package/index.js +1 -1
- package/libraries/controls.js +9 -1
- package/libraries/fastify.js +22 -13
- package/libraries/knex.js +8 -5
- package/package.json +1 -1
- package/routes/auto/handler.js +14 -14
- package/stores/base.js +2 -2
- package/stores/config.js +8 -3
- package/utils/jsonRouteLoader.js +28 -26
- package/utils/middleware.js +6 -9
- package/utils/routeLoader.js +18 -14
package/config/swagger.js
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
* Swagger configuration for Admin service
|
|
3
3
|
*/
|
|
4
4
|
const { config } = require('../stores/config');
|
|
5
|
+
|
|
5
6
|
module.exports = {
|
|
6
7
|
swagger: {
|
|
7
8
|
openapi: {
|
|
8
9
|
info: {
|
|
9
|
-
title: config.name + ' API',
|
|
10
|
-
description: config.name + ' API
|
|
10
|
+
title: (config.name || '').toUpperCase() + ' API',
|
|
11
|
+
description: (config.name || '').toUpperCase() + ' API DOCUMENTATION',
|
|
11
12
|
version: '1.0.0'
|
|
12
13
|
},
|
|
13
14
|
host: `${config.host || 'localhost'}:${config.port || 3001}`,
|
|
@@ -40,6 +41,6 @@ module.exports = {
|
|
|
40
41
|
}
|
|
41
42
|
},
|
|
42
43
|
swaggerUi: {
|
|
43
|
-
routePrefix: '/
|
|
44
|
+
routePrefix: '/'
|
|
44
45
|
}
|
|
45
46
|
};
|
package/index.js
CHANGED
package/libraries/controls.js
CHANGED
|
@@ -98,6 +98,13 @@ const ipcheck = (req, whitelists = '') => {
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
const toTitleCase = (str = '') => {
|
|
102
|
+
return str.replace(
|
|
103
|
+
/\w\S*/g,
|
|
104
|
+
text => text.charAt(0).toUpperCase() + text.substring(1).toLowerCase()
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
101
108
|
module.exports = {
|
|
102
109
|
emailValidation,
|
|
103
110
|
phoneValidation,
|
|
@@ -109,5 +116,6 @@ module.exports = {
|
|
|
109
116
|
checkPassoword,
|
|
110
117
|
ipcheck,
|
|
111
118
|
sleep,
|
|
112
|
-
roundTo
|
|
119
|
+
roundTo,
|
|
120
|
+
toTitleCase
|
|
113
121
|
}
|
package/libraries/fastify.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { loadRoutes } = require('../utils/routeLoader');
|
|
2
2
|
const Middleware = require('../utils/middleware');
|
|
3
|
-
const { setConfig } = require('../stores/config');
|
|
3
|
+
const { setConfig, config: configStore } = require('../stores/config');
|
|
4
4
|
|
|
5
5
|
let fastifyInstance = null;
|
|
6
6
|
|
|
@@ -15,8 +15,8 @@ async function registerPlugins(config) {
|
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
// Set error handler first, before any plugins
|
|
18
|
-
fastifyInstance.setErrorHandler(Middleware.errorHandler);
|
|
19
|
-
fastifyInstance.setNotFoundHandler(Middleware.errorNotFoundHandler);
|
|
18
|
+
fastifyInstance.setErrorHandler((error, request, reply) => Middleware.errorHandler(error, request, reply, config));
|
|
19
|
+
fastifyInstance.setNotFoundHandler((request, reply) => Middleware.errorNotFoundHandler(request, reply));
|
|
20
20
|
|
|
21
21
|
// CORS plugin
|
|
22
22
|
await fastifyInstance.register(require('@fastify/cors'), {
|
|
@@ -52,14 +52,23 @@ async function registerPlugins(config) {
|
|
|
52
52
|
fastifyInstance.addHook('preHandler', Middleware.responseFormatter());
|
|
53
53
|
|
|
54
54
|
// Health check endpoint
|
|
55
|
-
fastifyInstance.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
55
|
+
fastifyInstance.route({
|
|
56
|
+
method: 'GET',
|
|
57
|
+
url: '/' + (configStore.prefix ? configStore.prefix + '/' : '') + 'health',
|
|
58
|
+
schema: {
|
|
59
|
+
description: 'Health check',
|
|
60
|
+
summary: 'Health check',
|
|
61
|
+
tags: ['Global Services']
|
|
62
|
+
},
|
|
63
|
+
handler: async (request, reply) => {
|
|
64
|
+
return {
|
|
65
|
+
status: 'ok',
|
|
66
|
+
service: config.name,
|
|
67
|
+
timestamp: new Date().toISOString(),
|
|
68
|
+
uptime: process.uptime(),
|
|
69
|
+
pid: process.pid
|
|
70
|
+
};
|
|
71
|
+
}
|
|
63
72
|
});
|
|
64
73
|
|
|
65
74
|
return fastifyInstance;
|
|
@@ -70,7 +79,7 @@ async function loadAdminRoutes(config) {
|
|
|
70
79
|
try {
|
|
71
80
|
// Load admin routes
|
|
72
81
|
if(fastifyInstance) {
|
|
73
|
-
await loadRoutes(fastifyInstance, './routes/' + config.name,
|
|
82
|
+
await loadRoutes(fastifyInstance, './routes/' + config.name, config.common || false, config.name);
|
|
74
83
|
}
|
|
75
84
|
} catch (error) {
|
|
76
85
|
console.error('Error loading admin routes:', error);
|
|
@@ -83,7 +92,7 @@ async function start(config) {
|
|
|
83
92
|
try {
|
|
84
93
|
|
|
85
94
|
setConfig(config);
|
|
86
|
-
|
|
95
|
+
|
|
87
96
|
// Register plugins
|
|
88
97
|
await registerPlugins(config);
|
|
89
98
|
|
package/libraries/knex.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
const knex = require('knex');
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const connection = {
|
|
4
|
+
db: null
|
|
5
|
+
}
|
|
4
6
|
|
|
5
|
-
const initialize = async (
|
|
6
|
-
const { config: configStore } = require('../stores/config');
|
|
7
|
+
const initialize = async (configStore) => {
|
|
7
8
|
const databaseConfig = configStore?.database || {};
|
|
8
9
|
|
|
9
10
|
const db_config = {
|
|
@@ -30,10 +31,12 @@ const initialize = async (config) => {
|
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
const db = knex(db_config[configStore.development ? 'development' : 'production']);
|
|
33
|
-
|
|
34
|
+
connection.db = db;
|
|
35
|
+
|
|
36
|
+
return connection.db;
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
module.exports = {
|
|
37
40
|
initialize,
|
|
38
|
-
|
|
41
|
+
connection
|
|
39
42
|
}
|
package/package.json
CHANGED
package/routes/auto/handler.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const knex = require('../../libraries/knex');
|
|
2
2
|
const BCRYPT = require('../../libraries/bcrypt');
|
|
3
3
|
const bcrypt = new BCRYPT();
|
|
4
4
|
const i18n = require('../../utils/i18n');
|
|
@@ -30,7 +30,7 @@ async function getAll(request, reply, routeOptions = {}) {
|
|
|
30
30
|
const orderBy = `${tableName}.${(splitOrder[0] || primaryKey)}`;
|
|
31
31
|
const orderDirection = splitOrder[1] || 'desc';
|
|
32
32
|
|
|
33
|
-
let query = db
|
|
33
|
+
let query = knex.connection.db(tableName + ' as ' + tableName).select(`${tableName}.*`);
|
|
34
34
|
|
|
35
35
|
// Apply search filter if provided
|
|
36
36
|
if (search && routeConfig.searchable_fields) {
|
|
@@ -155,7 +155,7 @@ async function getById(request, reply, routeOptions = {}) {
|
|
|
155
155
|
const tableName = routeOptions.tableName || 'users';
|
|
156
156
|
const routeConfig = routeOptions.routeConfig || {};
|
|
157
157
|
|
|
158
|
-
const item_query = db
|
|
158
|
+
const item_query = knex.connection.db(tableName)
|
|
159
159
|
.select(`${tableName}.*`)
|
|
160
160
|
.where(primaryKey, id);
|
|
161
161
|
|
|
@@ -261,14 +261,14 @@ async function create(request, reply, routeOptions = {}) {
|
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
try {
|
|
264
|
-
const [id] = await db
|
|
264
|
+
const [id] = await knex.connection.db(tableName)
|
|
265
265
|
.insert({
|
|
266
266
|
...data,
|
|
267
267
|
created_at: new Date(),
|
|
268
268
|
updated_at: new Date()
|
|
269
269
|
});
|
|
270
270
|
|
|
271
|
-
const item = await db
|
|
271
|
+
const item = await knex.connection.db(tableName)
|
|
272
272
|
.where(primaryKey, id)
|
|
273
273
|
.first();
|
|
274
274
|
|
|
@@ -345,7 +345,7 @@ async function update(request, reply, routeOptions = {}) {
|
|
|
345
345
|
|
|
346
346
|
|
|
347
347
|
// Check if record exists
|
|
348
|
-
const existingItem = await db
|
|
348
|
+
const existingItem = await knex.connection.db(tableName)
|
|
349
349
|
.where(request.params)
|
|
350
350
|
.first();
|
|
351
351
|
|
|
@@ -363,14 +363,14 @@ async function update(request, reply, routeOptions = {}) {
|
|
|
363
363
|
}
|
|
364
364
|
}
|
|
365
365
|
|
|
366
|
-
await db
|
|
366
|
+
await knex.connection.db(tableName)
|
|
367
367
|
.where(request.params)
|
|
368
368
|
.update({
|
|
369
369
|
...data,
|
|
370
370
|
updated_at: new Date()
|
|
371
371
|
})
|
|
372
372
|
|
|
373
|
-
const updatedItem = await db
|
|
373
|
+
const updatedItem = await knex.connection.db(tableName)
|
|
374
374
|
.where(request.params)
|
|
375
375
|
.first();
|
|
376
376
|
|
|
@@ -406,7 +406,7 @@ async function upload(request, reply, routeOptions = {}) {
|
|
|
406
406
|
const { [primaryKey]: id } = request.params;
|
|
407
407
|
const routeConfig = routeOptions.routeConfig || {};
|
|
408
408
|
|
|
409
|
-
const existingItem = await db
|
|
409
|
+
const existingItem = await knex.connection.db(tableName)
|
|
410
410
|
.where(primaryKey, id)
|
|
411
411
|
.first();
|
|
412
412
|
|
|
@@ -425,7 +425,7 @@ async function upload(request, reply, routeOptions = {}) {
|
|
|
425
425
|
});
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
-
await db
|
|
428
|
+
await knex.connection.db(tableName)
|
|
429
429
|
.where(primaryKey, id)
|
|
430
430
|
.update({
|
|
431
431
|
[routeConfig.upload_field]: uploadResult.file.fileUrl
|
|
@@ -464,7 +464,7 @@ async function deleteRecord(request, reply, routeOptions = {}) {
|
|
|
464
464
|
const tableName = routeOptions.tableName || 'users';
|
|
465
465
|
|
|
466
466
|
// Check if record exists
|
|
467
|
-
const existingItem = await db
|
|
467
|
+
const existingItem = await knex.connection.db(tableName)
|
|
468
468
|
.where('id', id)
|
|
469
469
|
.first();
|
|
470
470
|
|
|
@@ -475,7 +475,7 @@ async function deleteRecord(request, reply, routeOptions = {}) {
|
|
|
475
475
|
});
|
|
476
476
|
}
|
|
477
477
|
|
|
478
|
-
await db
|
|
478
|
+
await knex.connection.db(tableName)
|
|
479
479
|
.where('id', id)
|
|
480
480
|
.del();
|
|
481
481
|
|
|
@@ -524,7 +524,7 @@ const generateRandomString = async (from_string = null, field_name = null, table
|
|
|
524
524
|
* @returns {Promise<boolean>} - The unique status
|
|
525
525
|
*/
|
|
526
526
|
const checkUnique = async (value = null, field_name = null, tableName = null) => {
|
|
527
|
-
const existing_item = await db
|
|
527
|
+
const existing_item = await knex.connection.db(tableName).select(field_name).where(field_name, value).first();
|
|
528
528
|
return existing_item ? true : false;
|
|
529
529
|
}
|
|
530
530
|
|
|
@@ -594,7 +594,7 @@ const processJoinTables = async (items, joinTables) => {
|
|
|
594
594
|
|
|
595
595
|
const personal_ids = items.map(item => item[joinTable.primary_key]);
|
|
596
596
|
|
|
597
|
-
const personal_items = db
|
|
597
|
+
const personal_items = knex.connection.db(joinTable.table).whereIn(joinTable.table + '.' + joinTable.foreign_key, personal_ids);
|
|
598
598
|
|
|
599
599
|
if(joinTable.extra_where) {
|
|
600
600
|
personal_items.where(db.raw(joinTable.table + '.' + joinTable.extra_where));
|
package/stores/base.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const
|
|
1
|
+
const { connection } = require('../libraries/knex');
|
|
2
2
|
|
|
3
3
|
module.exports = class StoreModel {
|
|
4
4
|
constructor(name = 'store_model', primary_key = 'id', schema = {}) {
|
|
5
5
|
this.name = name;
|
|
6
|
-
this.knex =
|
|
6
|
+
this.knex = connection.db;
|
|
7
7
|
this.data = new Map();
|
|
8
8
|
this.primary_key = primary_key;
|
|
9
9
|
this.schema = schema;
|
package/stores/config.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
const config = {};
|
|
2
2
|
|
|
3
|
-
const setConfig = (
|
|
4
|
-
|
|
3
|
+
const setConfig = (newConfig) => {
|
|
4
|
+
if(Object.keys(newConfig).length > 0) {
|
|
5
|
+
for(const key in newConfig) {
|
|
6
|
+
config[key] = newConfig[key];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return config;
|
|
5
10
|
}
|
|
6
11
|
|
|
7
12
|
module.exports = {
|
package/utils/jsonRouteLoader.js
CHANGED
|
@@ -3,6 +3,7 @@ const path = require('path');
|
|
|
3
3
|
const handlers = require('../routes/auto/handler');
|
|
4
4
|
const general = require('../libraries/general');
|
|
5
5
|
const { add_model } = require('../stores');
|
|
6
|
+
const { config: configStore } = require('../stores/config');
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* JSON Route Loader
|
|
@@ -19,7 +20,7 @@ class JsonRouteLoader {
|
|
|
19
20
|
* Load all JSON route configurations from routes/admin folder
|
|
20
21
|
* @param {Object} fastify - Fastify instance
|
|
21
22
|
*/
|
|
22
|
-
async loadJsonRoutes(fastify, routesDir, workerName) {
|
|
23
|
+
async loadJsonRoutes(fastify, routesDir, workerName, type = 'service') {
|
|
23
24
|
const adminPath = path.resolve(routesDir);
|
|
24
25
|
|
|
25
26
|
if(!workerName) {
|
|
@@ -39,7 +40,7 @@ class JsonRouteLoader {
|
|
|
39
40
|
|
|
40
41
|
for (const jsonFile of jsonFiles) {
|
|
41
42
|
try {
|
|
42
|
-
await this.loadJsonRoute(fastify, path.join(adminPath, jsonFile), workerName);
|
|
43
|
+
await this.loadJsonRoute(fastify, path.join(adminPath, jsonFile), workerName, type);
|
|
43
44
|
} catch (error) {
|
|
44
45
|
console.log(error.message);
|
|
45
46
|
}
|
|
@@ -51,7 +52,7 @@ class JsonRouteLoader {
|
|
|
51
52
|
* @param {Object} fastify - Fastify instance
|
|
52
53
|
* @param {string} jsonPath - Path to JSON file
|
|
53
54
|
*/
|
|
54
|
-
async loadJsonRoute(fastify, jsonPath, workerName) {
|
|
55
|
+
async loadJsonRoute(fastify, jsonPath, workerName, type = 'service') {
|
|
55
56
|
try {
|
|
56
57
|
|
|
57
58
|
const config = require(jsonPath);
|
|
@@ -75,7 +76,7 @@ class JsonRouteLoader {
|
|
|
75
76
|
const routeName = route.action;
|
|
76
77
|
const routeConfig = route;
|
|
77
78
|
if (this.supportedRoutes.includes(routeName)) {
|
|
78
|
-
await this.registerRoute(fastify, tableName, routeName, routeConfig, primaryKey, workerName, fileName, store, schema);
|
|
79
|
+
await this.registerRoute(fastify, tableName, routeName, routeConfig, primaryKey, workerName, fileName, store, schema, type);
|
|
79
80
|
if(store) {
|
|
80
81
|
await add_model(store, primaryKey, schema);
|
|
81
82
|
}
|
|
@@ -111,9 +112,9 @@ class JsonRouteLoader {
|
|
|
111
112
|
* @param {string} routeName - Route name (list, get, create, update, delete)
|
|
112
113
|
* @param {Object} routeConfig - Route configuration
|
|
113
114
|
*/
|
|
114
|
-
async registerRoute(fastify, tableName, routeName, routeConfig, primaryKey, workerName, fileName, store, schema) {
|
|
115
|
+
async registerRoute(fastify, tableName, routeName, routeConfig, primaryKey, workerName, fileName, store, schema, type = 'service') {
|
|
115
116
|
|
|
116
|
-
const routeDefinition = this.generateRouteDefinition(tableName, routeName, routeConfig, primaryKey, fileName, schema);
|
|
117
|
+
const routeDefinition = this.generateRouteDefinition(tableName, routeName, routeConfig, primaryKey, fileName, schema, type);
|
|
117
118
|
const routeKey = `${routeDefinition.method}:${routeDefinition.url}`;
|
|
118
119
|
|
|
119
120
|
if (this.registeredRoutes.has(routeKey)) {
|
|
@@ -166,40 +167,41 @@ class JsonRouteLoader {
|
|
|
166
167
|
* @param {Object} routeConfig - Route configuration
|
|
167
168
|
* @returns {Object} Route definition
|
|
168
169
|
*/
|
|
169
|
-
generateRouteDefinition(tableName, routeName, routeConfig, primaryKey, fileName, schema) {
|
|
170
|
-
const
|
|
170
|
+
generateRouteDefinition(tableName, routeName, routeConfig, primaryKey, fileName, schema, type = 'service') {
|
|
171
|
+
const prefix = configStore.prefix ? configStore.prefix + '/' : '';
|
|
172
|
+
const baseUrl = `/${prefix}${fileName}`;
|
|
171
173
|
primaryKey = primaryKey || 'id';
|
|
172
174
|
|
|
173
175
|
const routeDefinitions = {
|
|
174
176
|
list: {
|
|
175
177
|
method: 'GET',
|
|
176
178
|
url: baseUrl,
|
|
177
|
-
schema: this.generateListSchema(tableName, routeConfig, primaryKey, schema)
|
|
179
|
+
schema: this.generateListSchema(tableName, routeConfig, primaryKey, schema, type)
|
|
178
180
|
},
|
|
179
181
|
get: {
|
|
180
182
|
method: 'GET',
|
|
181
183
|
url: `${baseUrl}/:${primaryKey}`,
|
|
182
|
-
schema: this.generateGetSchema(tableName, routeConfig, primaryKey, schema)
|
|
184
|
+
schema: this.generateGetSchema(tableName, routeConfig, primaryKey, schema, type)
|
|
183
185
|
},
|
|
184
186
|
create: {
|
|
185
187
|
method: 'POST',
|
|
186
188
|
url: baseUrl,
|
|
187
|
-
schema: this.generateCreateSchema(tableName, routeConfig, primaryKey, schema)
|
|
189
|
+
schema: this.generateCreateSchema(tableName, routeConfig, primaryKey, schema, type)
|
|
188
190
|
},
|
|
189
191
|
update: {
|
|
190
192
|
method: 'PUT',
|
|
191
193
|
url: `${baseUrl}/:${primaryKey}`,
|
|
192
|
-
schema: this.generateUpdateSchema(tableName, routeConfig, primaryKey, schema)
|
|
194
|
+
schema: this.generateUpdateSchema(tableName, routeConfig, primaryKey, schema, type)
|
|
193
195
|
},
|
|
194
196
|
delete: {
|
|
195
197
|
method: 'DELETE',
|
|
196
198
|
url: `${baseUrl}/:${primaryKey}`,
|
|
197
|
-
schema: this.generateDeleteSchema(tableName, routeConfig, primaryKey, schema)
|
|
199
|
+
schema: this.generateDeleteSchema(tableName, routeConfig, primaryKey, schema, type)
|
|
198
200
|
},
|
|
199
201
|
upload: {
|
|
200
202
|
method: 'POST',
|
|
201
203
|
url: `${baseUrl}/:${primaryKey}/upload`,
|
|
202
|
-
schema: this.generateUploadSchema(tableName, routeConfig, primaryKey, schema),
|
|
204
|
+
schema: this.generateUploadSchema(tableName, routeConfig, primaryKey, schema, type),
|
|
203
205
|
validatorCompiler: ({ schema }) => {
|
|
204
206
|
return (data) => {
|
|
205
207
|
return true;
|
|
@@ -220,12 +222,12 @@ class JsonRouteLoader {
|
|
|
220
222
|
* @param {Object} filters - Filters object
|
|
221
223
|
* @returns {Object} Schema
|
|
222
224
|
*/
|
|
223
|
-
generateListSchema(tableName, routeConfig, primaryKey, schema) {
|
|
225
|
+
generateListSchema(tableName, routeConfig, primaryKey, schema, type = 'service') {
|
|
224
226
|
const itemSchema = this.generateItemSchema(schema, primaryKey);
|
|
225
227
|
|
|
226
228
|
return {
|
|
227
229
|
description: `Get all ${tableName} with pagination and search`,
|
|
228
|
-
tags: [general.titleCase(tableName)],
|
|
230
|
+
tags: [(type == 'service' ? general.titleCase(configStore.name) + ' | ' : 'Common | ') + 'Specs | ' + general.titleCase(tableName)],
|
|
229
231
|
summary: routeConfig.summary || `List of ${tableName} with pagination and search`,
|
|
230
232
|
querystring: {
|
|
231
233
|
type: 'object',
|
|
@@ -279,13 +281,13 @@ class JsonRouteLoader {
|
|
|
279
281
|
* @param {Object} routeConfig - Route configuration
|
|
280
282
|
* @returns {Object} Schema
|
|
281
283
|
*/
|
|
282
|
-
generateGetSchema(tableName, routeConfig, primaryKey, schema) {
|
|
284
|
+
generateGetSchema(tableName, routeConfig, primaryKey, schema, type = 'service') {
|
|
283
285
|
const itemSchema = this.generateItemSchema(schema, primaryKey);
|
|
284
286
|
primaryKey = primaryKey || 'id';
|
|
285
287
|
|
|
286
288
|
return {
|
|
287
289
|
description: `Get ${tableName} by ${primaryKey}`,
|
|
288
|
-
tags: [general.titleCase(tableName)],
|
|
290
|
+
tags: [(type == 'service' ? general.titleCase(configStore.name) + ' | ' : 'Common | ') + 'Specs | ' + general.titleCase(tableName)],
|
|
289
291
|
summary: routeConfig.summary || `Get ${tableName} by ${primaryKey}`,
|
|
290
292
|
params: {
|
|
291
293
|
type: 'object',
|
|
@@ -320,12 +322,12 @@ class JsonRouteLoader {
|
|
|
320
322
|
* @param {Object} routeConfig - Route configuration
|
|
321
323
|
* @returns {Object} Schema
|
|
322
324
|
*/
|
|
323
|
-
generateCreateSchema(tableName, routeConfig, primaryKey, schema) {
|
|
325
|
+
generateCreateSchema(tableName, routeConfig, primaryKey, schema, type = 'service') {
|
|
324
326
|
const bodySchema = this.generateBodySchema(schema, false, primaryKey);
|
|
325
327
|
|
|
326
328
|
return {
|
|
327
329
|
description: `Create new ${tableName}`,
|
|
328
|
-
tags: [general.titleCase(tableName)],
|
|
330
|
+
tags: [(type == 'service' ? general.titleCase(configStore.name) + ' | ' : 'Common | ') + 'Specs | ' + general.titleCase(tableName)],
|
|
329
331
|
summary: routeConfig.summary || `Create new ${tableName}`,
|
|
330
332
|
body: bodySchema,
|
|
331
333
|
response: {
|
|
@@ -354,12 +356,12 @@ class JsonRouteLoader {
|
|
|
354
356
|
* @param {Object} routeConfig - Route configuration
|
|
355
357
|
* @returns {Object} Schema
|
|
356
358
|
*/
|
|
357
|
-
generateUpdateSchema(tableName, routeConfig, primaryKey, schema) {
|
|
359
|
+
generateUpdateSchema(tableName, routeConfig, primaryKey, schema, type = 'service') {
|
|
358
360
|
const bodySchema = this.generateBodySchema(schema, true, primaryKey, 'updatable');
|
|
359
361
|
|
|
360
362
|
return {
|
|
361
363
|
description: `Update ${tableName} by ID`,
|
|
362
|
-
tags: [general.titleCase(tableName)],
|
|
364
|
+
tags: [(type == 'service' ? general.titleCase(configStore.name) + ' | ' : 'Common | ') + 'Specs | ' + general.titleCase(tableName)],
|
|
363
365
|
summary: routeConfig.summary || `Update ${tableName} by ${primaryKey}`,
|
|
364
366
|
params: {
|
|
365
367
|
type: 'object',
|
|
@@ -396,10 +398,10 @@ class JsonRouteLoader {
|
|
|
396
398
|
* @param {Object} routeConfig - Route configuration
|
|
397
399
|
* @returns {Object} Schema
|
|
398
400
|
*/
|
|
399
|
-
generateDeleteSchema(tableName, routeConfig, primaryKey, schema) {
|
|
401
|
+
generateDeleteSchema(tableName, routeConfig, primaryKey, schema, type = 'service') {
|
|
400
402
|
return {
|
|
401
403
|
description: `Delete ${tableName} by ID`,
|
|
402
|
-
tags: [general.titleCase(tableName)],
|
|
404
|
+
tags: [(type == 'service' ? general.titleCase(configStore.name) + ' | ' : 'Common | ') + 'Specs | ' + general.titleCase(tableName)],
|
|
403
405
|
summary: routeConfig.summary || `Delete ${tableName} by ${primaryKey}`,
|
|
404
406
|
params: {
|
|
405
407
|
type: 'object',
|
|
@@ -435,11 +437,11 @@ class JsonRouteLoader {
|
|
|
435
437
|
* @param {Object} routeConfig - Route configuration
|
|
436
438
|
* @returns {Object} Schema
|
|
437
439
|
*/
|
|
438
|
-
generateUploadSchema(tableName, routeConfig, primaryKey, schema) {
|
|
440
|
+
generateUploadSchema(tableName, routeConfig, primaryKey, schema, type = 'service') {
|
|
439
441
|
const uploadField = routeConfig.upload_field || 'file';
|
|
440
442
|
return {
|
|
441
443
|
description: `Upload file for ${tableName} by ${primaryKey}`,
|
|
442
|
-
tags: [general.titleCase(tableName)],
|
|
444
|
+
tags: [(type == 'service' ? general.titleCase(configStore.name) + ' | ' : 'Common | ') + 'Specs | ' + general.titleCase(tableName)],
|
|
443
445
|
summary: routeConfig.summary || `Upload file for ${tableName} by ${primaryKey}`,
|
|
444
446
|
params: {
|
|
445
447
|
type: 'object',
|
package/utils/middleware.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const i18n = require('./i18n');
|
|
2
|
-
const db = require('../libraries/knex');
|
|
3
2
|
const { config } = require('../stores/config');
|
|
4
3
|
/**
|
|
5
4
|
* Middleware utilities for Fastify
|
|
@@ -17,10 +16,6 @@ class Middleware {
|
|
|
17
16
|
// Add locale to request object
|
|
18
17
|
request.locale = locale;
|
|
19
18
|
request.t = (key, params = {}) => i18n.t(key, locale, params);
|
|
20
|
-
|
|
21
|
-
const language = await db.instance('languages').where('code', locale).first();
|
|
22
|
-
|
|
23
|
-
request.language = language ? language.language_id : 1;
|
|
24
19
|
|
|
25
20
|
// Add locale to reply headers
|
|
26
21
|
reply.header('Content-Language', locale);
|
|
@@ -30,8 +25,8 @@ class Middleware {
|
|
|
30
25
|
/**
|
|
31
26
|
* Error handler middleware with custom response format
|
|
32
27
|
*/
|
|
33
|
-
static errorHandler(error, request, reply) {
|
|
34
|
-
|
|
28
|
+
static errorHandler(error, request, reply, config) {
|
|
29
|
+
|
|
35
30
|
if(config.development) {
|
|
36
31
|
console.log(error);
|
|
37
32
|
}
|
|
@@ -68,7 +63,7 @@ class Middleware {
|
|
|
68
63
|
code: 404
|
|
69
64
|
});
|
|
70
65
|
}
|
|
71
|
-
|
|
66
|
+
|
|
72
67
|
// Handle other errors
|
|
73
68
|
const statusCode = error.statusCode || 500;
|
|
74
69
|
|
|
@@ -116,9 +111,11 @@ class Middleware {
|
|
|
116
111
|
*/
|
|
117
112
|
static responseFormatter() {
|
|
118
113
|
return async (request, reply) => {
|
|
114
|
+
|
|
115
|
+
const route_url = request?.routeOptions?.url || request.url;
|
|
119
116
|
|
|
120
117
|
// Skip response formatting for Swagger routes
|
|
121
|
-
if (
|
|
118
|
+
if (route_url.startsWith('/') || route_url.startsWith('/')) {
|
|
122
119
|
return;
|
|
123
120
|
}
|
|
124
121
|
|
package/utils/routeLoader.js
CHANGED
|
@@ -2,6 +2,7 @@ const fs = require('fs');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const JsonRouteLoader = require('./jsonRouteLoader');
|
|
4
4
|
const general = require('../libraries/general');
|
|
5
|
+
const { config: configStore } = require('../stores/config');
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Automatically loads routes from the routes directory
|
|
@@ -11,6 +12,7 @@ const general = require('../libraries/general');
|
|
|
11
12
|
* @param {boolean} includeAuto - Whether to include auto routes
|
|
12
13
|
*/
|
|
13
14
|
async function loadRoutes(fastify, routesDir = './routes', includeCommon = false, workerName) {
|
|
15
|
+
|
|
14
16
|
const routesPath = path.resolve(routesDir);
|
|
15
17
|
|
|
16
18
|
if (!fs.existsSync(routesPath)) {
|
|
@@ -31,17 +33,17 @@ async function loadRoutes(fastify, routesDir = './routes', includeCommon = false
|
|
|
31
33
|
|
|
32
34
|
for (const group of routeGroups) {
|
|
33
35
|
const groupPath = path.join(routesPath + '/spec', group);
|
|
34
|
-
await loadRouteGroup(fastify, group, groupPath, workerName);
|
|
36
|
+
await loadRouteGroup(fastify, group, groupPath, workerName, 'service');
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
// Load JSON routes from routes/admin folder
|
|
38
40
|
const jsonLoader = new JsonRouteLoader();
|
|
39
|
-
await jsonLoader.loadJsonRoutes(fastify, routesPath + '/auto', workerName);
|
|
41
|
+
await jsonLoader.loadJsonRoutes(fastify, routesPath + '/auto', workerName, 'service');
|
|
40
42
|
|
|
41
43
|
// // Load common routes if requested
|
|
42
44
|
if (includeCommon) {
|
|
43
|
-
const commonPath = path.resolve(
|
|
44
|
-
|
|
45
|
+
const commonPath = path.resolve('./routes/common');
|
|
46
|
+
|
|
45
47
|
if (fs.existsSync(commonPath)) {
|
|
46
48
|
|
|
47
49
|
if(!fs.existsSync(commonPath + '/spec')) {
|
|
@@ -56,10 +58,10 @@ async function loadRoutes(fastify, routesDir = './routes', includeCommon = false
|
|
|
56
58
|
|
|
57
59
|
for (const group of routeGroupsCommon) {
|
|
58
60
|
const groupPath = path.join(commonPath + '/spec', group);
|
|
59
|
-
await loadRouteGroup(fastify, group, groupPath, workerName);
|
|
61
|
+
await loadRouteGroup(fastify, group, groupPath, workerName, 'common');
|
|
60
62
|
}
|
|
61
63
|
|
|
62
|
-
await jsonLoader.loadJsonRoutes(fastify, commonPath + '/auto', workerName);
|
|
64
|
+
await jsonLoader.loadJsonRoutes(fastify, commonPath + '/auto', workerName, 'common');
|
|
63
65
|
}
|
|
64
66
|
}
|
|
65
67
|
}
|
|
@@ -70,8 +72,8 @@ async function loadRoutes(fastify, routesDir = './routes', includeCommon = false
|
|
|
70
72
|
* @param {string} groupName - Name of the route group
|
|
71
73
|
* @param {string} groupPath - Path to the route group directory
|
|
72
74
|
*/
|
|
73
|
-
async function loadRouteGroup(fastify, groupName, groupPath, workerName) {
|
|
74
|
-
await loadRouteModule(fastify, groupName, groupPath, workerName);
|
|
75
|
+
async function loadRouteGroup(fastify, groupName, groupPath, workerName, type = '--') {
|
|
76
|
+
await loadRouteModule(fastify, groupName, groupPath, workerName, type);
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
/**
|
|
@@ -81,7 +83,7 @@ async function loadRouteGroup(fastify, groupName, groupPath, workerName) {
|
|
|
81
83
|
* @param {string} moduleName - Name of the route module
|
|
82
84
|
* @param {string} modulePath - Path to the route module directory
|
|
83
85
|
*/
|
|
84
|
-
async function loadRouteModule(fastify, groupName, modulePath, workerName) {
|
|
86
|
+
async function loadRouteModule(fastify, groupName, modulePath, workerName, type = '--') {
|
|
85
87
|
|
|
86
88
|
// Check if route file exists
|
|
87
89
|
if (!fs.existsSync(modulePath)) {
|
|
@@ -106,14 +108,16 @@ async function loadRouteModule(fastify, groupName, modulePath, workerName) {
|
|
|
106
108
|
console.warn(`Route handler is required for route ${route.path}`);
|
|
107
109
|
continue;
|
|
108
110
|
}
|
|
111
|
+
|
|
112
|
+
const prefix = configStore.prefix ? configStore.prefix + '/' : '';
|
|
109
113
|
|
|
110
114
|
if(route.path) {
|
|
111
|
-
route.path = `/${moduleName}/${route.path}`;
|
|
115
|
+
route.path = `/${prefix}${moduleName}/${route.path}`;
|
|
112
116
|
} else {
|
|
113
|
-
route.path = `/${moduleName}`;
|
|
117
|
+
route.path = `/${prefix}${moduleName}`;
|
|
114
118
|
}
|
|
115
119
|
|
|
116
|
-
await registerRoute(fastify, route, moduleName, workerName);
|
|
120
|
+
await registerRoute(fastify, route, moduleName, workerName, type);
|
|
117
121
|
}
|
|
118
122
|
}
|
|
119
123
|
|
|
@@ -130,7 +134,7 @@ async function loadRouteModule(fastify, groupName, modulePath, workerName) {
|
|
|
130
134
|
* @param {Object} validation - Route validation
|
|
131
135
|
* @param {string} prefix - Route prefix
|
|
132
136
|
*/
|
|
133
|
-
async function registerRoute(fastify, routeConfig, moduleName, workerName) {
|
|
137
|
+
async function registerRoute(fastify, routeConfig, moduleName, workerName, type = '--') {
|
|
134
138
|
const {
|
|
135
139
|
method = 'GET',
|
|
136
140
|
path = '',
|
|
@@ -156,7 +160,7 @@ async function registerRoute(fastify, routeConfig, moduleName, workerName) {
|
|
|
156
160
|
}
|
|
157
161
|
|
|
158
162
|
const schemaRoute = {
|
|
159
|
-
tags: [general.titleCase(moduleName)],
|
|
163
|
+
tags: [(type == 'service' ? general.titleCase(configStore.name) + ' | ' : 'Common | ') + 'Specs | ' + general.titleCase(moduleName)],
|
|
160
164
|
response: {
|
|
161
165
|
200: schema.success_response ? { ...schema.success_response, additionalProperties: schema.success_response.additionalProperties || false } : {
|
|
162
166
|
type: 'object',
|