@mimik/init 3.9.5 → 5.0.1
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 -3
- package/index.js +59 -93
- package/lib/common.js +18 -0
- package/lib/metrics.js +2 -25
- package/lib/route.js +31 -0
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
<a name="
|
|
1
|
+
<a name="module_init"></a>
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## init
|
|
4
4
|
**Example**
|
|
5
5
|
```js
|
|
6
6
|
const init = require('@mimik/init');
|
|
7
7
|
|
|
8
8
|
init(config, dbValidate, { postOps: [suscribe] }).then(result => config = result);
|
|
9
9
|
```
|
|
10
|
-
<a name="
|
|
10
|
+
<a name="exp_module_init--module.exports"></a>
|
|
11
11
|
|
|
12
12
|
### module.exports(app, rootDir, config, validates, cluster, options) ⇒ <code>object</code> ⏏
|
|
13
13
|
Init process for a micro-service.
|
package/index.js
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
const swaggerTools = require('swagger-tools');
|
|
2
|
-
const http = require('http');
|
|
3
1
|
const cors = require('cors');
|
|
4
|
-
const
|
|
2
|
+
const http = require('http');
|
|
3
|
+
const pathLib = require('path');
|
|
5
4
|
const Promise = require('bluebird');
|
|
6
5
|
const helmet = require('helmet');
|
|
7
6
|
|
|
8
7
|
const logger = require('@mimik/sumologic-winston-logger');
|
|
9
|
-
const swagger = require('@mimik/swagger-helper');
|
|
10
|
-
const oauthHelper = require('@mimik/oauth-helper');
|
|
11
8
|
const { startupHealthInfo } = require('@mimik/healthcheck');
|
|
12
|
-
const { healthInfo } = require('@mimik/systeminfo');
|
|
13
9
|
const { getPublic } = require('@mimik/public-helper');
|
|
14
10
|
const { getCorrelationId } = require('@mimik/request-helper');
|
|
11
|
+
const { apiSetup, setupServerFiles } = require('@mimik/api-helper');
|
|
12
|
+
|
|
15
13
|
const { extractLogs } = require('./lib/logs');
|
|
16
14
|
const { sigProcess } = require('./lib/exit');
|
|
17
|
-
const {
|
|
18
|
-
const {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
const { startHrTimeSet } = require('./lib/metrics');
|
|
16
|
+
const { healthCheckRoute, metricsRoute } = require('./lib/route');
|
|
17
|
+
const {
|
|
18
|
+
HEALTHCHECK_ROUTE,
|
|
19
|
+
METRICS_ROUTE,
|
|
20
|
+
SIGINT,
|
|
21
|
+
SIGTERM,
|
|
22
|
+
LOCAL,
|
|
23
|
+
SET_ON,
|
|
24
|
+
BUILD_FILENAME,
|
|
25
|
+
} = require('./lib/common');
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* @module
|
|
28
|
+
* @module init
|
|
29
29
|
* @example
|
|
30
30
|
* const init = require('@mimik/init');
|
|
31
31
|
*
|
|
@@ -72,19 +72,41 @@ module.exports = (app, rootDir, config, validates, cluster, options) => {
|
|
|
72
72
|
|
|
73
73
|
if (!config) return fatalError(new Error('config is required'));
|
|
74
74
|
const { serverSettings, dependencies } = config;
|
|
75
|
+
const updateOptions = (origOpts) => {
|
|
76
|
+
const apiInfo = {
|
|
77
|
+
provider: serverSettings.swaggerFile.provider,
|
|
78
|
+
apiApikey: serverSettings.apiApiKey,
|
|
79
|
+
apiBasicAuth: serverSettings.apiBasicAuth,
|
|
80
|
+
};
|
|
81
|
+
let opts = origOpts;
|
|
82
|
+
|
|
83
|
+
if (opts) opts.apiInfo = apiInfo;
|
|
84
|
+
else opts = { apiInfo };
|
|
85
|
+
return opts;
|
|
86
|
+
};
|
|
75
87
|
const serverPort = serverSettings.port;
|
|
76
88
|
const correlationIdStart = getCorrelationId(`system-start:${serverSettings.id}`);
|
|
77
89
|
|
|
78
90
|
if (!cluster) return fatalError(new Error('cluster lib required'), correlationIdStart);
|
|
79
91
|
if (!app) return fatalError(new Error('app is required'), correlationIdStart);
|
|
80
92
|
const { register, unRegister } = cluster;
|
|
81
|
-
const oauth = oauthHelper(config);
|
|
82
93
|
const server = http.createServer(app);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
94
|
+
const controllersDirectory = pathLib.join(rootDir, './controllers');
|
|
95
|
+
const buildDirectory = pathLib.join(rootDir, './build');
|
|
96
|
+
const buildRequire = pathLib.join(buildDirectory, BUILD_FILENAME);
|
|
97
|
+
const extractName = options ? options.extractName : null;
|
|
98
|
+
const metrics = options ? options.metrics : null;
|
|
99
|
+
let apiFilename = serverSettings.api;
|
|
86
100
|
let registration = false;
|
|
87
101
|
|
|
102
|
+
if ((config.nodeEnvironment.toLowerCase() !== LOCAL) || (config.registration.set === SET_ON)) { registration = true; }
|
|
103
|
+
else logger.warn('registration disabled: cluster will not work', correlationIdStart);
|
|
104
|
+
if (extractName) {
|
|
105
|
+
if (!dependencies || !dependencies.mLG) return fatalError(new Error('requesting extraction without mLG configuration'), correlationIdStart);
|
|
106
|
+
dependencies.mLG.extractName = extractName;
|
|
107
|
+
}
|
|
108
|
+
if (metrics && !metrics.register) return fatalError(new Error('register is required in metrics'), correlationIdStart);
|
|
109
|
+
|
|
88
110
|
process.on(SIGINT, () => {
|
|
89
111
|
sigProcess(SIGINT, registration, options, config, server, unRegister, getCorrelationId(`system-shutdown(${SIGINT}):${serverSettings.id}`));
|
|
90
112
|
});
|
|
@@ -100,78 +122,22 @@ module.exports = (app, rootDir, config, validates, cluster, options) => {
|
|
|
100
122
|
},
|
|
101
123
|
}));
|
|
102
124
|
app.use(cors({ origin: '*' }));
|
|
103
|
-
app.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (options.metrics && options.metrics.register) {
|
|
108
|
-
app.use(METRICS_ROUTE, (req, res) => options.metrics.register.metrics()
|
|
109
|
-
.then((result) => {
|
|
110
|
-
res.setHeader(CONTENT_TYPE, options.metrics.register.contentType);
|
|
111
|
-
res.end(result);
|
|
112
|
-
})
|
|
113
|
-
.catch((err) => {
|
|
114
|
-
res.setHeader(CONTENT_TYPE, JSON_CONTENT);
|
|
115
|
-
const errResponse = {
|
|
116
|
-
statusCode: 500,
|
|
117
|
-
title: http.STATUS_CODES[500],
|
|
118
|
-
message: err.message,
|
|
119
|
-
};
|
|
120
|
-
res.end(JSON.stringify(errResponse), null, 2);
|
|
121
|
-
}));
|
|
125
|
+
app.get(HEALTHCHECK_ROUTE, healthCheckRoute());
|
|
126
|
+
if (metrics) {
|
|
127
|
+
app.get(METRICS_ROUTE, metricsRoute(options));
|
|
128
|
+
app.use(startHrTimeSet(metrics.APIRequestDuration));
|
|
122
129
|
}
|
|
123
|
-
if (
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (swaggerFilename[0] !== '/') swaggerFilename = path.join(rootDir, swaggerFilename);
|
|
133
|
-
logger.debug('location of the swagger file', { swaggerFilename }, correlationIdStart);
|
|
134
|
-
return swagger.getAPIFile(swaggerFilename, correlationIdStart, serverSettings.apiBasicAuth, options)
|
|
135
|
-
.then((swaggerJson) => swaggerTools.initializeMiddleware(swaggerJson, (middleware) => {
|
|
136
|
-
serverSettings.basePath = swaggerJson.basePath;
|
|
137
|
-
app.use(startHrTimeSet());
|
|
138
|
-
app.use(middleware.swaggerMetadata());
|
|
139
|
-
if (options && options.metrics) {
|
|
140
|
-
app.use(APIRequestMetrics(options.metrics.APIRequestDuration, serverSettings.basePath));
|
|
141
|
-
}
|
|
142
|
-
app.use(middleware.swaggerValidator());
|
|
143
|
-
if ((config.nodeEnvironment && config.nodeEnvironment.toLowerCase() !== LOCAL) || (serverSettings.securitySet === SET_ON)) {
|
|
144
|
-
const securityOptions = {
|
|
145
|
-
AdminSecurity: oauth.apiTokenAdminSecurityHelper,
|
|
146
|
-
SystemSecurity: oauth.apiTokenSecurityHelper,
|
|
147
|
-
UserSecurity: oauth.apiTokenSecurityHelper,
|
|
148
|
-
APIKeySecurity: oauth.apiKeySecurityHelper,
|
|
149
|
-
};
|
|
130
|
+
if (extractName) { app.use(extractLogs(config, extractName, options)); }
|
|
131
|
+
if (apiFilename[0] !== '/') apiFilename = pathLib.join(rootDir, apiFilename);
|
|
132
|
+
logger.debug('location of the api file', { apiFilename }, correlationIdStart);
|
|
133
|
+
return setupServerFiles(apiFilename, controllersDirectory, buildDirectory, correlationIdStart, updateOptions(options))
|
|
134
|
+
.then((setupResult) => {
|
|
135
|
+
serverSettings.basePath = setupResult.apiDefinition.servers[0].url; // need to address that later
|
|
136
|
+
// eslint-disable-next-line import/no-dynamic-require,global-require
|
|
137
|
+
const registeredOperations = require(buildRequire);
|
|
138
|
+
const api = apiSetup(setupResult, registeredOperations, options?.secOptions, options?.formats, config, correlationIdStart);
|
|
150
139
|
|
|
151
|
-
|
|
152
|
-
Object.keys(options.secOptions).forEach((key) => {
|
|
153
|
-
securityOptions[key] = options.secOptions[key];
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
app.use(middleware.swaggerSecurity(securityOptions));
|
|
157
|
-
}
|
|
158
|
-
else logger.warn('security disabled: tokens will not be used and /me and /onbehalf will not work', correlationIdStart);
|
|
159
|
-
if ((config.nodeEnvironment && config.nodeEnvironment.toLowerCase() !== LOCAL) || (config.registration.set === SET_ON)) {
|
|
160
|
-
registration = true;
|
|
161
|
-
}
|
|
162
|
-
else logger.warn('registration disabled: cluster will not work', correlationIdStart);
|
|
163
|
-
if (extractName) {
|
|
164
|
-
app.use(extractLogs(config, extractName, options));
|
|
165
|
-
}
|
|
166
|
-
app.use(middleware.swaggerRouter({
|
|
167
|
-
useStubs: config.nodeEnvironment === LOCAL,
|
|
168
|
-
controllers: `${rootDir}/controllers`,
|
|
169
|
-
}));
|
|
170
|
-
app.use(middleware.swaggerUi());
|
|
171
|
-
app.use(swagger.sendError);
|
|
172
|
-
if (serverSettings.interceptError === SET_ON) {
|
|
173
|
-
app.use(swagger.interceptError);
|
|
174
|
-
}
|
|
140
|
+
app.use((req, res) => api.handleRequest(req, req, res));
|
|
175
141
|
return Promise.each(validates, (validate) => validate())
|
|
176
142
|
.then(() => getPublic(config.locationProvider, config.cloudProvider, correlationIdStart, options).then((publicConfig) => {
|
|
177
143
|
logger.info('public environment', { status: publicConfig.status }, correlationIdStart);
|
|
@@ -189,8 +155,8 @@ module.exports = (app, rootDir, config, validates, cluster, options) => {
|
|
|
189
155
|
if (registration) register(correlationIdStart);
|
|
190
156
|
if (options && options.postOps) options.postOps.forEach((ops) => ops(correlationIdStart, config, server));
|
|
191
157
|
});
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
|
|
158
|
+
});
|
|
159
|
+
})
|
|
160
|
+
.catch((error) => fatalError(error, correlationIdStart))
|
|
195
161
|
.then(() => ({ config }));
|
|
196
162
|
};
|
package/lib/common.js
CHANGED
|
@@ -2,8 +2,26 @@ const METRICS_ROUTE = '/metrics';
|
|
|
2
2
|
const HEALTHCHECK_ROUTE = '/healthcheck';
|
|
3
3
|
const OUT_OF_SPEC_ROUTE = 'outOfSpecificationRoute';
|
|
4
4
|
|
|
5
|
+
const CONTENT_TYPE = 'Content-Type';
|
|
6
|
+
const JSON_CONTENT = 'application/json';
|
|
7
|
+
|
|
8
|
+
const SIGINT = 'SIGINT';
|
|
9
|
+
const SIGTERM = 'SIGTERM';
|
|
10
|
+
|
|
11
|
+
const LOCAL = 'local';
|
|
12
|
+
const SET_ON = 'on';
|
|
13
|
+
|
|
14
|
+
const BUILD_FILENAME = 'register';
|
|
15
|
+
|
|
5
16
|
module.exports = {
|
|
6
17
|
METRICS_ROUTE,
|
|
7
18
|
HEALTHCHECK_ROUTE,
|
|
8
19
|
OUT_OF_SPEC_ROUTE,
|
|
20
|
+
CONTENT_TYPE,
|
|
21
|
+
JSON_CONTENT,
|
|
22
|
+
SIGINT,
|
|
23
|
+
SIGTERM,
|
|
24
|
+
LOCAL,
|
|
25
|
+
SET_ON,
|
|
26
|
+
BUILD_FILENAME,
|
|
9
27
|
};
|
package/lib/metrics.js
CHANGED
|
@@ -1,31 +1,8 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
const APIRequestMetrics = (APIRequestDuration, basePath) => (req, res, next) => {
|
|
4
|
-
const { swagger } = req;
|
|
5
|
-
let apiPath = req.originalUrl;
|
|
6
|
-
|
|
7
|
-
if (swagger) apiPath = swagger.apiPath;
|
|
8
|
-
const startHrTime = req.metrics ? req.metrics.startHrTime : process.hrtime();
|
|
9
|
-
|
|
10
|
-
res.on('finish', () => {
|
|
11
|
-
if (apiPath !== METRICS_ROUTE && apiPath !== HEALTHCHECK_ROUTE) {
|
|
12
|
-
const elapsedHrTime = process.hrtime(startHrTime);
|
|
13
|
-
const elapsedTimeInMs = elapsedHrTime[0] * 1000 + elapsedHrTime[1] / 1e6;
|
|
14
|
-
|
|
15
|
-
APIRequestDuration
|
|
16
|
-
.labels(req.method, swagger ? `${basePath}${apiPath}` : OUT_OF_SPEC_ROUTE, req.originalUrl.includes('?'), res.statusCode)
|
|
17
|
-
.observe(elapsedTimeInMs);
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
next();
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const startHrTimeSet = () => (req, res, next) => {
|
|
24
|
-
req.metrics = { startHrTime: process.hrtime() };
|
|
1
|
+
const startHrTimeSet = (APIRequestDuration) => (req, res, next) => {
|
|
2
|
+
req.metrics = { startHrTime: process.hrtime(), APIRequestDuration };
|
|
25
3
|
next();
|
|
26
4
|
};
|
|
27
5
|
|
|
28
6
|
module.exports = {
|
|
29
7
|
startHrTimeSet,
|
|
30
|
-
APIRequestMetrics,
|
|
31
8
|
};
|
package/lib/route.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const http = require('http');
|
|
2
|
+
|
|
3
|
+
const { healthInfo } = require('@mimik/systeminfo');
|
|
4
|
+
|
|
5
|
+
const { CONTENT_TYPE, JSON_CONTENT } = require('./common');
|
|
6
|
+
|
|
7
|
+
const healthCheckRoute = () => (req, res) => {
|
|
8
|
+
res.setHeader(CONTENT_TYPE, JSON_CONTENT);
|
|
9
|
+
res.end(JSON.stringify({ data: healthInfo() }, null, 2));
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const metricsRoute = (options) => (req, res) => options.metrics.register.metrics()
|
|
13
|
+
.then((result) => {
|
|
14
|
+
res.setHeader(CONTENT_TYPE, options.metrics.register.contentType);
|
|
15
|
+
res.end(result);
|
|
16
|
+
})
|
|
17
|
+
.catch((err) => {
|
|
18
|
+
res.setHeader(CONTENT_TYPE, JSON_CONTENT);
|
|
19
|
+
const errResponse = {
|
|
20
|
+
statusCode: 500,
|
|
21
|
+
title: http.STATUS_CODES[500],
|
|
22
|
+
message: err.message,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
res.end(JSON.stringify(errResponse), null, 2);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
module.exports = {
|
|
29
|
+
healthCheckRoute,
|
|
30
|
+
metricsRoute,
|
|
31
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mimik/init",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.1",
|
|
4
4
|
"description": "Init process for micro-service",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -29,15 +29,15 @@
|
|
|
29
29
|
"url": "https://bitbucket.org/mimiktech/init"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@mimik/address-helper": "^1.6.
|
|
32
|
+
"@mimik/address-helper": "^1.6.9",
|
|
33
|
+
"@mimik/api-helper": "^1.0.1",
|
|
33
34
|
"@mimik/healthcheck": "^1.5.10",
|
|
34
|
-
"@mimik/oauth-helper": "^
|
|
35
|
-
"@mimik/public-helper": "^
|
|
35
|
+
"@mimik/oauth-helper": "^3.0.0",
|
|
36
|
+
"@mimik/public-helper": "^2.0.0",
|
|
36
37
|
"@mimik/request-helper": "^1.7.8",
|
|
37
|
-
"@mimik/response-helper": "^
|
|
38
|
+
"@mimik/response-helper": "^3.0.0",
|
|
38
39
|
"@mimik/sumologic-winston-logger": "^1.6.15",
|
|
39
|
-
"@mimik/
|
|
40
|
-
"@mimik/systeminfo": "^2.3.12",
|
|
40
|
+
"@mimik/systeminfo": "^3.0.0",
|
|
41
41
|
"bluebird": "3.7.2",
|
|
42
42
|
"cors": "2.8.5",
|
|
43
43
|
"helmet": "6.1.5",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@mimik/eslint-plugin-dependencies": "^2.4.5",
|
|
48
48
|
"@mimik/eslint-plugin-document-env": "^1.0.5",
|
|
49
|
-
"eslint": "8.
|
|
49
|
+
"eslint": "8.39.0",
|
|
50
50
|
"eslint-config-airbnb": "19.0.4",
|
|
51
51
|
"eslint-plugin-import": "2.27.5",
|
|
52
52
|
"eslint-plugin-jsx-a11y": "6.7.1",
|