@mimik/init 6.0.3 → 6.1.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 +12 -9
- package/index.js +33 -24
- package/lib/common.js +0 -3
- package/lib/exit.js +18 -4
- package/lib/logs.js +53 -42
- package/lib/metrics.js +7 -0
- package/lib/route.js +20 -1
- package/package.json +28 -27
- package/.husky/pre-commit +0 -4
- package/.husky/pre-push +0 -4
- package/.nycrc +0 -4
- package/eslint.config.js +0 -66
package/README.md
CHANGED
|
@@ -5,17 +5,17 @@
|
|
|
5
5
|
```js
|
|
6
6
|
import init from '@mimik/init';
|
|
7
7
|
|
|
8
|
-
init(config, dbValidate, { postOps: [subscribe] }).then(result => config = result);
|
|
8
|
+
init(app, rootDir, config, [dbValidate], cluster, { postOps: [subscribe] }).then(result => config = result);
|
|
9
9
|
```
|
|
10
10
|
<a name="module_init..init"></a>
|
|
11
11
|
|
|
12
|
-
### init~init(app, rootDir, config, validates, cluster, options) ⇒ <code>object
|
|
12
|
+
### init~init(app, rootDir, config, validates, cluster, options) ⇒ <code>Promise.<object></code>
|
|
13
13
|
Init process for a micro-service.
|
|
14
14
|
|
|
15
15
|
**Kind**: inner method of [<code>init</code>](#module_init)
|
|
16
|
-
**Returns**: <code>object
|
|
16
|
+
**Returns**: <code>Promise.<object></code> - The updated configuration.
|
|
17
17
|
|
|
18
|
-
The
|
|
18
|
+
The options parameter has the following structure:
|
|
19
19
|
``` javascript
|
|
20
20
|
{
|
|
21
21
|
preOps: [function], // functions to process before starting the micro-service
|
|
@@ -24,6 +24,8 @@ The secOptions has the following structure:
|
|
|
24
24
|
secOptions: { securityDefinition: function }, // extra security options to validate the API request
|
|
25
25
|
extractName: string, // ability to extract data from the req and send it to a logging environment
|
|
26
26
|
metrics: object, // to generate information for `/metrics`
|
|
27
|
+
oidcOps: function, // OIDC operations to be called during init
|
|
28
|
+
formats: object, // custom formats for API validation
|
|
27
29
|
}
|
|
28
30
|
```
|
|
29
31
|
The `return` object has the following structure:
|
|
@@ -32,16 +34,17 @@ The `return` object has the following structure:
|
|
|
32
34
|
config: The configuration object,
|
|
33
35
|
}
|
|
34
36
|
```
|
|
35
|
-
For the preOps, postOps and exitOps the
|
|
37
|
+
For the preOps, postOps and exitOps the functions are executed with 3 parameters (correlationId, config, server).
|
|
38
|
+
When `config.registration.afterPostOpsSet` is `'on'`, postOps run before cluster registration; otherwise registration happens first.
|
|
36
39
|
The following routes are reserved: `/healthcheck` and `/metrics`.
|
|
37
|
-
The base path is defined by taking the
|
|
40
|
+
The base path is defined by taking the URL property of the first item of the servers array in the API definition file. Only relative URL addresses will be handled (e.g. /mss/v1) and templates in the URL are not allowed.
|
|
38
41
|
|
|
39
42
|
| Param | Type | Description |
|
|
40
43
|
| --- | --- | --- |
|
|
41
44
|
| app | <code>object</code> | The app implementing the micro-service. |
|
|
42
|
-
| rootDir | <code>
|
|
45
|
+
| rootDir | <code>string</code> | The root directory of the micro-service. |
|
|
43
46
|
| config | <code>object</code> | Configuration of the micro-service. |
|
|
44
47
|
| validates | <code>array</code> | Array of Promises to validate dependent systems (database, topic). |
|
|
45
|
-
| cluster | <code>
|
|
46
|
-
| options | <code>object</code> |
|
|
48
|
+
| cluster | <code>object</code> | Object with `register` and `unRegister` methods for cluster management. |
|
|
49
|
+
| options | <code>object</code> | Options to start the micro-service. Can be `null`. |
|
|
47
50
|
|
package/index.js
CHANGED
|
@@ -11,11 +11,12 @@ import {
|
|
|
11
11
|
import { apiSetup, setupServerFiles } from '@mimik/api-helper';
|
|
12
12
|
import { bodyParserRoute, healthCheckRoute, metricsRoute } from './lib/route.js';
|
|
13
13
|
import Promise from 'bluebird';
|
|
14
|
+
import { contentSecurityPolicy } from 'helmet';
|
|
14
15
|
import cors from 'cors';
|
|
15
16
|
import { extractLogs } from './lib/logs.js';
|
|
16
17
|
import { getCorrelationId } from '@mimik/request-helper';
|
|
17
18
|
import { getPublic } from '@mimik/public-helper';
|
|
18
|
-
import
|
|
19
|
+
import http from 'node:http';
|
|
19
20
|
import logger from '@mimik/sumologic-winston-logger';
|
|
20
21
|
import pathLib from 'node:path';
|
|
21
22
|
import { sigProcess } from './lib/exit.js';
|
|
@@ -27,7 +28,7 @@ import { startupHealthInfo } from '@mimik/healthcheck';
|
|
|
27
28
|
* @example
|
|
28
29
|
* import init from '@mimik/init';
|
|
29
30
|
*
|
|
30
|
-
* init(config, dbValidate, { postOps: [subscribe] }).then(result => config = result);
|
|
31
|
+
* init(app, rootDir, config, [dbValidate], cluster, { postOps: [subscribe] }).then(result => config = result);
|
|
31
32
|
*
|
|
32
33
|
*/
|
|
33
34
|
|
|
@@ -38,14 +39,14 @@ const FIRST_PATH_ELEMENT = 0;
|
|
|
38
39
|
* Init process for a micro-service.
|
|
39
40
|
*
|
|
40
41
|
* @param {object} app - The app implementing the micro-service.
|
|
41
|
-
* @param {
|
|
42
|
+
* @param {string} rootDir - The root directory of the micro-service.
|
|
42
43
|
* @param {object} config - Configuration of the micro-service.
|
|
43
44
|
* @param {array} validates - Array of Promises to validate dependent systems (database, topic).
|
|
44
|
-
* @param {
|
|
45
|
-
* @param {object} options -
|
|
46
|
-
* @returns {object} The updated configuration.
|
|
45
|
+
* @param {object} cluster - Object with `register` and `unRegister` methods for cluster management.
|
|
46
|
+
* @param {?object} options - Options to start the micro-service. Can be `null`.
|
|
47
|
+
* @returns {Promise<object>} The updated configuration.
|
|
47
48
|
*
|
|
48
|
-
* The
|
|
49
|
+
* The options parameter has the following structure:
|
|
49
50
|
* ``` javascript
|
|
50
51
|
* {
|
|
51
52
|
* preOps: [function], // functions to process before starting the micro-service
|
|
@@ -54,6 +55,8 @@ const FIRST_PATH_ELEMENT = 0;
|
|
|
54
55
|
* secOptions: { securityDefinition: function }, // extra security options to validate the API request
|
|
55
56
|
* extractName: string, // ability to extract data from the req and send it to a logging environment
|
|
56
57
|
* metrics: object, // to generate information for `/metrics`
|
|
58
|
+
* oidcOps: function, // OIDC operations to be called during init
|
|
59
|
+
* formats: object, // custom formats for API validation
|
|
57
60
|
* }
|
|
58
61
|
*```
|
|
59
62
|
* The `return` object has the following structure:
|
|
@@ -62,15 +65,17 @@ const FIRST_PATH_ELEMENT = 0;
|
|
|
62
65
|
* config: The configuration object,
|
|
63
66
|
* }
|
|
64
67
|
* ```
|
|
65
|
-
* For the preOps, postOps and exitOps the
|
|
68
|
+
* For the preOps, postOps and exitOps the functions are executed with 3 parameters (correlationId, config, server).
|
|
69
|
+
* When `config.registration.afterPostOpsSet` is `'on'`, postOps run before cluster registration; otherwise registration happens first.
|
|
66
70
|
* The following routes are reserved: `/healthcheck` and `/metrics`.
|
|
67
|
-
* The base path is defined by taking the
|
|
71
|
+
* The base path is defined by taking the URL property of the first item of the servers array in the API definition file. Only relative URL addresses will be handled (e.g. /mss/v1) and templates in the URL are not allowed.
|
|
68
72
|
*/
|
|
69
73
|
const init = (app, rootDir, config, validates, cluster, options) => {
|
|
70
74
|
const fatalError = (error, correlationId) => {
|
|
71
75
|
if (config) logger.error('fatal error: could not start server', { name: config.serverSettings.name, id: config.serverSettings.id, error }, correlationId);
|
|
72
76
|
else logger.error('fatal error: could not start server', { error }, getCorrelationId('system-start'));
|
|
73
77
|
logger.flushAndExit(EXIT_ERROR);
|
|
78
|
+
return Promise.reject(error);
|
|
74
79
|
};
|
|
75
80
|
|
|
76
81
|
if (!config) return fatalError(new Error('config is required'));
|
|
@@ -78,14 +83,12 @@ const init = (app, rootDir, config, validates, cluster, options) => {
|
|
|
78
83
|
const updateOptions = (origOpts) => {
|
|
79
84
|
const apiInfo = {
|
|
80
85
|
provider: serverSettings.swaggerFile.provider,
|
|
81
|
-
|
|
86
|
+
apiApiKey: serverSettings.apiApiKey,
|
|
82
87
|
apiBasicAuth: serverSettings.apiBasicAuth,
|
|
83
88
|
};
|
|
84
|
-
let opts = origOpts;
|
|
85
89
|
|
|
86
|
-
if (
|
|
87
|
-
|
|
88
|
-
return opts;
|
|
90
|
+
if (origOpts) return { ...origOpts, apiInfo };
|
|
91
|
+
return { apiInfo };
|
|
89
92
|
};
|
|
90
93
|
const serverPort = serverSettings.port;
|
|
91
94
|
const correlationIdStart = getCorrelationId(`system-start:${serverSettings.id}`);
|
|
@@ -109,21 +112,23 @@ const init = (app, rootDir, config, validates, cluster, options) => {
|
|
|
109
112
|
else logger.warn('registration disabled: cluster will not work', correlationIdStart);
|
|
110
113
|
if (extractName) {
|
|
111
114
|
if (!dependencies || !dependencies.mLG) return fatalError(new Error('requesting extraction without mLG configuration'), correlationIdStart);
|
|
112
|
-
dependencies.mLG
|
|
115
|
+
config.dependencies.mLG = { ...dependencies.mLG, extractName };
|
|
113
116
|
}
|
|
114
117
|
if (metrics && !metrics.register) return fatalError(new Error('register is required in metrics'), correlationIdStart);
|
|
115
118
|
|
|
119
|
+
const sigContext = { registration, options, config, server, unRegister };
|
|
120
|
+
|
|
116
121
|
process.on(SIGINT, () => {
|
|
117
|
-
sigProcess(SIGINT,
|
|
122
|
+
sigProcess(SIGINT, sigContext, getCorrelationId(`system-shutdown(${SIGINT}):${serverSettings.id}`));
|
|
118
123
|
});
|
|
119
124
|
process.on(SIGTERM, () => {
|
|
120
|
-
sigProcess(SIGTERM,
|
|
125
|
+
sigProcess(SIGTERM, sigContext, getCorrelationId(`system-shutdown(${SIGTERM}):${serverSettings.id}`));
|
|
121
126
|
});
|
|
122
127
|
|
|
123
128
|
app.use(bodyParserRoute());
|
|
124
|
-
app.use(
|
|
129
|
+
app.use(contentSecurityPolicy({
|
|
125
130
|
directives: {
|
|
126
|
-
...
|
|
131
|
+
...contentSecurityPolicy.getDefaultDirectives(),
|
|
127
132
|
'script-src': ['\'self\'', '\'unsafe-inline\''],
|
|
128
133
|
'connect-src': ['\'self\'', '*.swagger.io'],
|
|
129
134
|
},
|
|
@@ -146,13 +151,14 @@ const init = (app, rootDir, config, validates, cluster, options) => {
|
|
|
146
151
|
.then((setupResult) => {
|
|
147
152
|
serverSettings.basePath = setupResult.apiDefinition.servers[FIRST].url; // need to address that later
|
|
148
153
|
// this will be deprecated by init 7.0, to handle lower case paths
|
|
154
|
+
const baseParts = serverSettings.basePath.split('/');
|
|
155
|
+
|
|
149
156
|
app.use((req, res, next) => {
|
|
150
157
|
const parts = req.url.split('/');
|
|
151
158
|
const partsLength = parts.length;
|
|
152
|
-
const baseParts = serverSettings.basePath.split('/');
|
|
153
159
|
|
|
154
160
|
baseParts.every((basePart, index) => {
|
|
155
|
-
if (index
|
|
161
|
+
if (index >= partsLength || basePart.toLowerCase() !== parts[index].toLowerCase()) return false;
|
|
156
162
|
parts[index] = basePart;
|
|
157
163
|
return true;
|
|
158
164
|
});
|
|
@@ -176,7 +182,7 @@ const init = (app, rootDir, config, validates, cluster, options) => {
|
|
|
176
182
|
if (options && options.preOps) return Promise.each(options.preOps, ops => ops(correlationIdStart, config, server));
|
|
177
183
|
return null;
|
|
178
184
|
})
|
|
179
|
-
.then(() => {
|
|
185
|
+
.then(() => new Promise((resolve, reject) => {
|
|
180
186
|
server.listen(serverPort, () => {
|
|
181
187
|
startupHealthInfo(config, correlationIdStart);
|
|
182
188
|
const afterPostOps = config.registration.afterPostOpsSet === SET_ON;
|
|
@@ -197,9 +203,12 @@ const init = (app, rootDir, config, validates, cluster, options) => {
|
|
|
197
203
|
}
|
|
198
204
|
if (options && options.postOps) return Promise.each(options.postOps, ops => ops(correlationIdStart, config, server));
|
|
199
205
|
return null;
|
|
200
|
-
})
|
|
206
|
+
})
|
|
207
|
+
.then(resolve)
|
|
208
|
+
.catch(reject);
|
|
201
209
|
});
|
|
202
|
-
|
|
210
|
+
server.on('error', reject);
|
|
211
|
+
}));
|
|
203
212
|
});
|
|
204
213
|
})
|
|
205
214
|
.catch(error => fatalError(error, correlationIdStart))
|
package/lib/common.js
CHANGED
|
@@ -2,8 +2,6 @@ import logger from '@mimik/sumologic-winston-logger';
|
|
|
2
2
|
|
|
3
3
|
const METRICS_ROUTE = '/metrics';
|
|
4
4
|
const HEALTHCHECK_ROUTE = '/healthcheck';
|
|
5
|
-
const OUT_OF_SPEC_ROUTE = 'outOfSpecificationRoute';
|
|
6
|
-
|
|
7
5
|
const CONTENT_TYPE = 'Content-Type';
|
|
8
6
|
const JSON_CONTENT = 'application/json';
|
|
9
7
|
|
|
@@ -29,7 +27,6 @@ const EXTRACT_LOG_LEVEL = logger.LEVELS[DEBUG];
|
|
|
29
27
|
export {
|
|
30
28
|
METRICS_ROUTE,
|
|
31
29
|
HEALTHCHECK_ROUTE,
|
|
32
|
-
OUT_OF_SPEC_ROUTE,
|
|
33
30
|
CONTENT_TYPE,
|
|
34
31
|
JSON_CONTENT,
|
|
35
32
|
SIGINT,
|
package/lib/exit.js
CHANGED
|
@@ -13,13 +13,27 @@ const shutdown = (res, correlationId) => {
|
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Handles process signals (SIGINT/SIGTERM) by unregistering from the cluster,
|
|
18
|
+
* running exit operations, and shutting down gracefully.
|
|
19
|
+
*
|
|
20
|
+
* @param {string} signal - The signal name (`'SIGINT'` or `'SIGTERM'`).
|
|
21
|
+
* @param {object} context - Shutdown context.
|
|
22
|
+
* @param {boolean} context.registration - Whether the service is registered with a cluster.
|
|
23
|
+
* @param {?object} context.options - Init options (optional `exitOps` array). Can be `null`.
|
|
24
|
+
* @param {object} context.config - Service configuration.
|
|
25
|
+
* @param {object} context.server - The HTTP server instance.
|
|
26
|
+
* @param {Function} context.unRegister - Cluster unregister function.
|
|
27
|
+
* @param {string} correlationId - Correlation ID for log tracing.
|
|
28
|
+
* @returns {Promise|null} Promise from unregister chain, or `null` if not registered.
|
|
29
|
+
*/
|
|
30
|
+
export const sigProcess = (signal, context, correlationId) => {
|
|
31
|
+
const { registration, options, config, server, unRegister } = context;
|
|
32
|
+
|
|
17
33
|
if (registration) {
|
|
18
34
|
return unRegister(correlationId)
|
|
19
35
|
.then((origResult) => {
|
|
20
|
-
const result = origResult;
|
|
21
|
-
|
|
22
|
-
result.signal = signal;
|
|
36
|
+
const result = { ...origResult, signal };
|
|
23
37
|
if (!options || !options.exitOps) {
|
|
24
38
|
return shutdown(result, correlationId);
|
|
25
39
|
}
|
package/lib/logs.js
CHANGED
|
@@ -6,53 +6,64 @@ import oauthHelper from '@mimik/oauth-helper';
|
|
|
6
6
|
import { publicIpFromRequest } from '@mimik/address-helper';
|
|
7
7
|
import urlLib from 'node:url';
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
const baseCorrelationId = getCorrelationId('log-extraction');
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Returns Express middleware that extracts a named field from the request body
|
|
13
|
+
* and forwards it to the mLG logging service.
|
|
14
|
+
*
|
|
15
|
+
* @param {object} config - Service configuration (must include `dependencies.mLG`).
|
|
16
|
+
* @param {string} extractName - Property name to extract from `req.body`.
|
|
17
|
+
* @param {?object} options - Init options (optional `metrics` for request tracking). Can be `null`.
|
|
18
|
+
* @returns {Function} Express middleware `(req, res, next)`.
|
|
19
|
+
*/
|
|
20
|
+
export const extractLogs = (config, extractName, options) => {
|
|
12
21
|
const { rpAuth } = oauthHelper(config);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
22
|
+
|
|
23
|
+
return (req, res, next) => {
|
|
24
|
+
let url = `${config.dependencies.mLG.url}${NOTIFICATION}`;
|
|
25
|
+
const params = new urlLib.URLSearchParams();
|
|
26
|
+
let correlationId = baseCorrelationId;
|
|
27
|
+
|
|
28
|
+
if (req.headers['x-correlation-id']) correlationId = `${req.headers['x-correlation-id']}:${correlationId}`;
|
|
29
|
+
if (req.tokenType) params.append('serverType', req.tokenType);
|
|
30
|
+
if (req.clientId) params.append('serverId', req.clientId);
|
|
31
|
+
if (params.size) url = `${url}?${params.toString()}`;
|
|
32
|
+
if (req.body && extractName in req.body) {
|
|
33
|
+
let xForwardedFor = publicIpFromRequest(req);
|
|
34
|
+
|
|
35
|
+
if (xForwardedFor) {
|
|
36
|
+
if (config.serverSettings.ip.public) xForwardedFor = `${xForwardedFor},${config.serverSettings.ip.public}`;
|
|
37
|
+
}
|
|
38
|
+
else if (config.serverSettings.ip.public) xForwardedFor = config.serverSettings.ip.public;
|
|
39
|
+
logger.silly('extracting data', { extractName, url }, correlationId);
|
|
40
|
+
const headers = { 'x-correlation-id': correlationId };
|
|
41
|
+
|
|
42
|
+
if (xForwardedFor) headers['x-forwarded-for'] = xForwardedFor;
|
|
43
|
+
const opts = {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
headers,
|
|
46
|
+
url,
|
|
47
|
+
data: {
|
|
48
|
+
Message: req.body[extractName],
|
|
49
|
+
},
|
|
50
|
+
retry: {
|
|
51
|
+
logLevel: {
|
|
52
|
+
request: EXTRACT_LOG_LEVEL,
|
|
53
|
+
response: EXTRACT_LOG_LEVEL,
|
|
54
|
+
error: EXTRACT_LOG_LEVEL,
|
|
55
|
+
},
|
|
43
56
|
},
|
|
44
|
-
}
|
|
45
|
-
};
|
|
57
|
+
};
|
|
46
58
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
59
|
+
if (options && options.metrics) {
|
|
60
|
+
opts.metrics = { ...options.metrics, url };
|
|
61
|
+
}
|
|
62
|
+
rpAuth('mLG', opts)
|
|
63
|
+
.catch(err => getRichError('System', 'could not send extracted data', { url, extractName }, err, 'warn', correlationId));
|
|
50
64
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
delete req.body[extractName];
|
|
54
|
-
}
|
|
55
|
-
next();
|
|
65
|
+
next();
|
|
66
|
+
};
|
|
56
67
|
};
|
|
57
68
|
|
|
58
69
|
export default {
|
package/lib/metrics.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns Express middleware that attaches high-resolution timing data to the request
|
|
3
|
+
* for measuring API request duration.
|
|
4
|
+
*
|
|
5
|
+
* @param {object} APIRequestDuration - Prometheus histogram or metric object for recording duration.
|
|
6
|
+
* @returns {Function} Express middleware `(req, res, next)`.
|
|
7
|
+
*/
|
|
1
8
|
export const startHrTimeSet = APIRequestDuration => (req, res, next) => {
|
|
2
9
|
req.metrics = { startHrTime: process.hrtime(), APIRequestDuration };
|
|
3
10
|
next();
|
package/lib/route.js
CHANGED
|
@@ -2,20 +2,33 @@ import { CONTENT_TYPE, JSON_CONTENT, TAB } from './common.js';
|
|
|
2
2
|
import { getCorrelationId, getUserAgent } from '@mimik/request-helper';
|
|
3
3
|
import { ERROR_CODE } from '@mimik/response-helper';
|
|
4
4
|
import { healthInfo } from '@mimik/systeminfo';
|
|
5
|
+
import http from 'node:http';
|
|
5
6
|
import logger from '@mimik/sumologic-winston-logger';
|
|
6
7
|
import { publicIpFromRequest } from '@mimik/address-helper';
|
|
7
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Returns Express middleware that responds with system health information.
|
|
11
|
+
*
|
|
12
|
+
* @returns {Function} Express route handler `(req, res)`.
|
|
13
|
+
*/
|
|
8
14
|
export const healthCheckRoute = () => (req, res) => {
|
|
9
15
|
res.setHeader(CONTENT_TYPE, JSON_CONTENT);
|
|
10
16
|
res.end(JSON.stringify({ data: healthInfo() }, null, TAB));
|
|
11
17
|
};
|
|
12
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Returns Express middleware that responds with Prometheus-style metrics.
|
|
21
|
+
*
|
|
22
|
+
* @param {object} options - Init options containing a `metrics.register` object.
|
|
23
|
+
* @returns {Function} Express route handler `(req, res)`.
|
|
24
|
+
*/
|
|
13
25
|
export const metricsRoute = options => (req, res) => options.metrics.register.metrics()
|
|
14
26
|
.then((result) => {
|
|
15
27
|
res.setHeader(CONTENT_TYPE, options.metrics.register.contentType);
|
|
16
28
|
res.end(result);
|
|
17
29
|
})
|
|
18
30
|
.catch((err) => {
|
|
31
|
+
res.statusCode = ERROR_CODE.SYSTEM;
|
|
19
32
|
res.setHeader(CONTENT_TYPE, JSON_CONTENT);
|
|
20
33
|
const errResponse = {
|
|
21
34
|
statusCode: ERROR_CODE.SYSTEM,
|
|
@@ -23,9 +36,15 @@ export const metricsRoute = options => (req, res) => options.metrics.register.me
|
|
|
23
36
|
message: err.message,
|
|
24
37
|
};
|
|
25
38
|
|
|
26
|
-
res.end(JSON.stringify(errResponse
|
|
39
|
+
res.end(JSON.stringify(errResponse, null, TAB));
|
|
27
40
|
});
|
|
28
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Returns Express error-handling middleware that catches JSON body-parser syntax errors
|
|
44
|
+
* and responds with a 400 status.
|
|
45
|
+
*
|
|
46
|
+
* @returns {Function} Express error middleware `(err, req, res, next)`.
|
|
47
|
+
*/
|
|
29
48
|
export const bodyParserRoute = () => (err, req, res, next) => {
|
|
30
49
|
if (err instanceof SyntaxError && err.status === ERROR_CODE.PARAMETER && 'body' in err) {
|
|
31
50
|
const { originalUrl } = req;
|
package/package.json
CHANGED
|
@@ -1,26 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mimik/init",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"description": "Init process for micro-service",
|
|
5
5
|
"main": "./index.js",
|
|
6
|
-
"type": "module",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": "./index.js",
|
|
7
8
|
"engines": {
|
|
8
|
-
"node": ">=
|
|
9
|
+
"node": ">=24.0.0"
|
|
9
10
|
},
|
|
10
11
|
"scripts": {
|
|
11
12
|
"lint": "eslint . --no-error-on-unmatched-pattern",
|
|
12
13
|
"docs": "jsdoc2md index.js > README.md",
|
|
13
|
-
"test": "
|
|
14
|
-
"test-ci": "
|
|
14
|
+
"test": "mocha",
|
|
15
|
+
"test-ci": "c8 npm test",
|
|
15
16
|
"prepublishOnly": "npm run docs && npm run lint && npm run test-ci",
|
|
16
17
|
"commit-ready": "npm run docs && npm run lint && npm run test-ci"
|
|
17
18
|
},
|
|
18
|
-
"husky": {
|
|
19
|
-
"hooks": {
|
|
20
|
-
"pre-commit": "npm run commit-ready",
|
|
21
|
-
"pre-push": "npm run test"
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
19
|
"keywords": [
|
|
25
20
|
"mimik",
|
|
26
21
|
"microservice"
|
|
@@ -32,26 +27,32 @@
|
|
|
32
27
|
"url": "https://bitbucket.org/mimiktech/init"
|
|
33
28
|
},
|
|
34
29
|
"dependencies": {
|
|
35
|
-
"@mimik/address-helper": "^2.0.
|
|
36
|
-
"@mimik/api-helper": "^
|
|
37
|
-
"@mimik/healthcheck": "^2.
|
|
38
|
-
"@mimik/oauth-helper": "^4.
|
|
39
|
-
"@mimik/public-helper": "^3.0.
|
|
40
|
-
"@mimik/request-helper": "^2.0.
|
|
41
|
-
"@mimik/response-helper": "^4.0.
|
|
42
|
-
"@mimik/sumologic-winston-logger": "^2.
|
|
43
|
-
"@mimik/systeminfo": "^4.
|
|
30
|
+
"@mimik/address-helper": "^2.0.8",
|
|
31
|
+
"@mimik/api-helper": "^3.0.2",
|
|
32
|
+
"@mimik/healthcheck": "^2.1.0",
|
|
33
|
+
"@mimik/oauth-helper": "^4.1.2",
|
|
34
|
+
"@mimik/public-helper": "^3.0.5",
|
|
35
|
+
"@mimik/request-helper": "^2.0.6",
|
|
36
|
+
"@mimik/response-helper": "^4.0.11",
|
|
37
|
+
"@mimik/sumologic-winston-logger": "^2.2.2",
|
|
38
|
+
"@mimik/systeminfo": "^4.1.1",
|
|
44
39
|
"bluebird": "3.7.2",
|
|
45
|
-
"cors": "2.8.
|
|
40
|
+
"cors": "2.8.6",
|
|
46
41
|
"helmet": "8.1.0"
|
|
47
42
|
},
|
|
48
43
|
"devDependencies": {
|
|
49
|
-
"@eslint/js": "
|
|
50
|
-
"@mimik/eslint-plugin-document-env": "^2.0.
|
|
51
|
-
"@
|
|
52
|
-
"eslint": "
|
|
53
|
-
"
|
|
44
|
+
"@eslint/js": "10.0.1",
|
|
45
|
+
"@mimik/eslint-plugin-document-env": "^2.0.9",
|
|
46
|
+
"@mimik/eslint-plugin-logger": "^1.0.3",
|
|
47
|
+
"@stylistic/eslint-plugin": "5.10.0",
|
|
48
|
+
"c8": "11.0.0",
|
|
49
|
+
"chai": "6.2.2",
|
|
50
|
+
"eslint": "10.1.0",
|
|
51
|
+
"eslint-plugin-import-x": "4.16.2",
|
|
52
|
+
"globals": "17.4.0",
|
|
54
53
|
"husky": "9.1.7",
|
|
55
|
-
"jsdoc-to-markdown": "9.1.3"
|
|
54
|
+
"jsdoc-to-markdown": "9.1.3",
|
|
55
|
+
"mocha": "11.7.5",
|
|
56
|
+
"mochawesome": "7.1.4"
|
|
56
57
|
}
|
|
57
58
|
}
|
package/.husky/pre-commit
DELETED
package/.husky/pre-push
DELETED
package/.nycrc
DELETED
package/eslint.config.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import importPlugin from 'eslint-plugin-import';
|
|
2
|
-
import js from '@eslint/js';
|
|
3
|
-
import processDoc from '@mimik/eslint-plugin-document-env';
|
|
4
|
-
import stylistic from '@stylistic/eslint-plugin';
|
|
5
|
-
|
|
6
|
-
const ECMA_VERSION = 'latest';
|
|
7
|
-
const MAX_LENGTH_LINE = 180;
|
|
8
|
-
const MAX_FUNCTION_PARAMETERS = 7;
|
|
9
|
-
const MAX_LINES_IN_FILES = 600;
|
|
10
|
-
const MAX_LINES_IN_FUNCTION = 150;
|
|
11
|
-
const MAX_STATEMENTS_IN_FUNCTION = 45;
|
|
12
|
-
const MIN_KEYS_IN_OBJECT = 10;
|
|
13
|
-
const MAX_COMPLEXITY = 30;
|
|
14
|
-
|
|
15
|
-
export default [
|
|
16
|
-
{
|
|
17
|
-
ignores: ['mochawesome-report/**', 'node_modules/**', 'dist/**'],
|
|
18
|
-
},
|
|
19
|
-
importPlugin.flatConfigs.recommended,
|
|
20
|
-
stylistic.configs.recommended,
|
|
21
|
-
js.configs.all,
|
|
22
|
-
{
|
|
23
|
-
plugins: {
|
|
24
|
-
processDoc,
|
|
25
|
-
},
|
|
26
|
-
languageOptions: {
|
|
27
|
-
ecmaVersion: ECMA_VERSION,
|
|
28
|
-
globals: {
|
|
29
|
-
console: 'readonly',
|
|
30
|
-
describe: 'readonly',
|
|
31
|
-
http: 'readonly',
|
|
32
|
-
it: 'readonly',
|
|
33
|
-
process: 'readonly',
|
|
34
|
-
require: 'readonly',
|
|
35
|
-
},
|
|
36
|
-
sourceType: 'module',
|
|
37
|
-
},
|
|
38
|
-
rules: {
|
|
39
|
-
'@stylistic/brace-style': ['warn', 'stroustrup', { allowSingleLine: true }],
|
|
40
|
-
'@stylistic/line-comment-position': ['off'],
|
|
41
|
-
'@stylistic/semi': ['error', 'always'],
|
|
42
|
-
'capitalized-comments': ['off'],
|
|
43
|
-
'complexity': ['error', MAX_COMPLEXITY],
|
|
44
|
-
'curly': ['off'],
|
|
45
|
-
'id-length': ['error', { exceptions: ['x', 'y', 'z', 'i', 'j', 'k'] }],
|
|
46
|
-
'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
|
|
47
|
-
'import/no-unresolved': ['error', { amd: true, caseSensitiveStrict: true, commonjs: true }],
|
|
48
|
-
'init-declarations': ['off'],
|
|
49
|
-
'linebreak-style': ['off'],
|
|
50
|
-
'max-len': ['warn', MAX_LENGTH_LINE, { ignoreComments: true }],
|
|
51
|
-
'max-lines': ['warn', { max: MAX_LINES_IN_FILES, skipComments: true }],
|
|
52
|
-
'max-lines-per-function': ['warn', { max: MAX_LINES_IN_FUNCTION, skipComments: true }],
|
|
53
|
-
'max-params': ['error', MAX_FUNCTION_PARAMETERS],
|
|
54
|
-
'max-statements': ['warn', MAX_STATEMENTS_IN_FUNCTION],
|
|
55
|
-
'no-confusing-arrow': ['off'],
|
|
56
|
-
'no-inline-comments': ['off'],
|
|
57
|
-
'no-process-env': ['error'],
|
|
58
|
-
'no-ternary': ['off'],
|
|
59
|
-
'no-undefined': ['off'],
|
|
60
|
-
'one-var': ['error', 'never'],
|
|
61
|
-
'processDoc/validate-document-env': ['error'],
|
|
62
|
-
'quotes': ['warn', 'single'],
|
|
63
|
-
'sort-keys': ['error', 'asc', { caseSensitive: true, minKeys: MIN_KEYS_IN_OBJECT, natural: false }],
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
];
|