@mimik/init 2.0.0 → 3.6.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/.eslintrc +20 -3
- package/.husky/pre-commit +4 -0
- package/.husky/pre-push +4 -0
- package/.nycrc +4 -0
- package/Gulpfile.js +8 -8
- package/README.md +6 -4
- package/index.js +45 -33
- package/lib/exit.js +44 -0
- package/lib/logs.js +5 -4
- package/package.json +29 -23
package/.eslintrc
CHANGED
|
@@ -1,17 +1,34 @@
|
|
|
1
|
-
// Use this file as a starting point for your project's .eslintrc.
|
|
2
|
-
// Copy this file, and add rule overrides as needed.
|
|
3
1
|
{
|
|
2
|
+
"plugins": [
|
|
3
|
+
"@mimik/document-env",
|
|
4
|
+
"@mimik/dependencies"
|
|
5
|
+
],
|
|
4
6
|
"env": {
|
|
5
7
|
"node": true
|
|
6
8
|
},
|
|
9
|
+
"parserOptions": {
|
|
10
|
+
"ecmaVersion": 2020
|
|
11
|
+
},
|
|
7
12
|
"extends": "airbnb",
|
|
8
13
|
"rules": {
|
|
14
|
+
"import/no-extraneous-dependencies": ["error", {"devDependencies": true}],
|
|
9
15
|
"brace-style": [1, "stroustrup", {"allowSingleLine": true}],
|
|
10
16
|
"no-confusing-arrow": [0], // arrow isnt confusing
|
|
11
17
|
"max-len": [1, 180, { "ignoreComments": true }],
|
|
12
18
|
"linebreak-style": 0,
|
|
13
19
|
"quotes": [1, "single"],
|
|
14
|
-
"semi": [1, "always"]
|
|
20
|
+
"semi": [1, "always"],
|
|
21
|
+
"no-process-env": ["error"],
|
|
22
|
+
"@mimik/document-env/validate-document-env": 2,
|
|
23
|
+
"@mimik/dependencies/case-sensitive": 2,
|
|
24
|
+
"@mimik/dependencies/no-cycles": 2,
|
|
25
|
+
"@mimik/dependencies/no-unresolved": 2,
|
|
26
|
+
"@mimik/dependencies/require-json-ext": 2
|
|
27
|
+
},
|
|
28
|
+
"settings":{
|
|
29
|
+
"react": {
|
|
30
|
+
"version": "latest"
|
|
31
|
+
}
|
|
15
32
|
},
|
|
16
33
|
"globals": {
|
|
17
34
|
"module": true,
|
package/.husky/pre-push
ADDED
package/.nycrc
ADDED
package/Gulpfile.js
CHANGED
|
@@ -9,25 +9,25 @@ const jsdoc2md = require('jsdoc-to-markdown');
|
|
|
9
9
|
const files = [
|
|
10
10
|
'index.js',
|
|
11
11
|
'Gulpfile.js',
|
|
12
|
-
'test
|
|
12
|
+
'test/**.js',
|
|
13
13
|
'lib/**.js',
|
|
14
14
|
];
|
|
15
15
|
|
|
16
|
-
const
|
|
16
|
+
const createDocs = (done) => {
|
|
17
17
|
jsdoc2md.render({ files: 'index.js' })
|
|
18
|
-
.then(output => fs.writeFileSync('README.md', output))
|
|
19
|
-
.catch(err => log.error('docs creation failed:', err.message))
|
|
20
|
-
|
|
18
|
+
.then((output) => fs.writeFileSync('README.md', output))
|
|
19
|
+
.catch((err) => log.error('docs creation failed:', err.message))
|
|
20
|
+
.finally(() => done());
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
const lint = () => gulp.src(files)
|
|
24
24
|
.pipe(eslint({}))
|
|
25
|
-
.pipe(eslint.format())
|
|
26
|
-
.pipe(eslint.failOnError());
|
|
25
|
+
.pipe(eslint.format());
|
|
27
26
|
|
|
28
27
|
const add = () => gulp.src('README.md')
|
|
29
28
|
.pipe(git.add({ quiet: true }));
|
|
30
29
|
|
|
30
|
+
const docs = gulp.series(createDocs, add);
|
|
31
|
+
|
|
31
32
|
gulp.task('docs', docs);
|
|
32
33
|
gulp.task('lint', lint);
|
|
33
|
-
gulp.task('add', add);
|
package/README.md
CHANGED
|
@@ -9,17 +9,18 @@ init(config, dbValidate, { postOps: [suscribe] }).then(result => config = result
|
|
|
9
9
|
```
|
|
10
10
|
<a name="exp_module_ini--module.exports"></a>
|
|
11
11
|
|
|
12
|
-
### module.exports(app, rootDir, config,
|
|
12
|
+
### module.exports(app, rootDir, config, validates, cluster, options) ⇒ <code>object</code> ⏏
|
|
13
13
|
Init process for a micro-service.
|
|
14
14
|
|
|
15
15
|
**Kind**: Exported function
|
|
16
16
|
**Returns**: <code>object</code> - The updated configuration.
|
|
17
17
|
|
|
18
|
-
The secOptions has the following
|
|
18
|
+
The secOptions has the following structure:
|
|
19
19
|
``` javascript
|
|
20
20
|
{
|
|
21
21
|
preOps: [function], // functions to process before starting the micro-service
|
|
22
22
|
postOps: [function], // functions to process after starting the micro-service
|
|
23
|
+
exitOps: [function], // functions to process before exiting the micro-service
|
|
23
24
|
secOptions: { securityDefinition: function }, // extra security options to validate the API request
|
|
24
25
|
extractName: string, // ability to extract data from the req and send it to a logging environment
|
|
25
26
|
}
|
|
@@ -30,13 +31,14 @@ The `return` object has the following strucuture:
|
|
|
30
31
|
config: The configuration object,
|
|
31
32
|
}
|
|
32
33
|
```
|
|
33
|
-
For the preOps and
|
|
34
|
+
For the preOps, postOps and exitOps the function are executed with 3 parameters (correlationId, config, server)
|
|
34
35
|
|
|
35
36
|
| Param | Type | Description |
|
|
36
37
|
| --- | --- | --- |
|
|
37
38
|
| app | <code>object</code> | The app implementing the micro-service. |
|
|
38
39
|
| rootDir | <code>PATH.<string></code> | The root directory of the micro-service. |
|
|
39
40
|
| config | <code>object</code> | Configuration of the micro-service. |
|
|
40
|
-
|
|
|
41
|
+
| validates | <code>array</code> | Array of Promises to validate dependent systems (database, topic). |
|
|
42
|
+
| cluster | <code>Promise</code> | Promise to be used for cluster management and registration. |
|
|
41
43
|
| options | <code>object</code> | options to start the micro-service. The options can be `null`. |
|
|
42
44
|
|
package/index.js
CHANGED
|
@@ -7,13 +7,15 @@ const helmet = require('helmet');
|
|
|
7
7
|
|
|
8
8
|
const logger = require('@mimik/sumologic-winston-logger');
|
|
9
9
|
const swagger = require('@mimik/swagger-helper');
|
|
10
|
-
const eventHelper = require('@mimik/event-helper');
|
|
11
10
|
const oauthHelper = require('@mimik/oauth-helper');
|
|
12
11
|
const { startupHealthInfo } = require('@mimik/healthcheck');
|
|
13
12
|
const { getPublic } = require('@mimik/public-helper');
|
|
14
|
-
const
|
|
15
|
-
|
|
13
|
+
const { getCorrelationId } = require('@mimik/request-helper');
|
|
16
14
|
const { extractLogs } = require('./lib/logs');
|
|
15
|
+
const { sigProcess } = require('./lib/exit');
|
|
16
|
+
|
|
17
|
+
const SIGINT = 'SIGINT';
|
|
18
|
+
const SIGTERM = 'SIGTERM';
|
|
17
19
|
|
|
18
20
|
/**
|
|
19
21
|
* @module ini
|
|
@@ -29,15 +31,17 @@ const { extractLogs } = require('./lib/logs');
|
|
|
29
31
|
* @param {object} app - The app implementing the micro-service.
|
|
30
32
|
* @param {PATH<string>} rootDir - The root directory of the micro-service.
|
|
31
33
|
* @param {object} config - Configuration of the micro-service.
|
|
32
|
-
* @param {
|
|
34
|
+
* @param {array} validates - Array of Promises to validate dependent systems (database, topic).
|
|
35
|
+
* @param {Promise} cluster - Promise to be used for cluster management and registration.
|
|
33
36
|
* @param {object} options - options to start the micro-service. The options can be `null`.
|
|
34
37
|
* @returns {object} The updated configuration.
|
|
35
38
|
*
|
|
36
|
-
* The secOptions has the following
|
|
39
|
+
* The secOptions has the following structure:
|
|
37
40
|
* ``` javascript
|
|
38
41
|
* {
|
|
39
42
|
* preOps: [function], // functions to process before starting the micro-service
|
|
40
43
|
* postOps: [function], // functions to process after starting the micro-service
|
|
44
|
+
* exitOps: [function], // functions to process before exiting the micro-service
|
|
41
45
|
* secOptions: { securityDefinition: function }, // extra security options to validate the API request
|
|
42
46
|
* extractName: string, // ability to extract data from the req and send it to a logging environment
|
|
43
47
|
* }
|
|
@@ -48,31 +52,44 @@ const { extractLogs } = require('./lib/logs');
|
|
|
48
52
|
* config: The configuration object,
|
|
49
53
|
* }
|
|
50
54
|
* ```
|
|
51
|
-
* For the preOps and
|
|
55
|
+
* For the preOps, postOps and exitOps the function are executed with 3 parameters (correlationId, config, server)
|
|
52
56
|
*/
|
|
53
|
-
module.exports = (app, rootDir, config,
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
module.exports = (app, rootDir, config, validates, cluster, options) => {
|
|
58
|
+
const fatalError = (error, correlationId) => {
|
|
59
|
+
if (!config) logger.error('fatal error: could not start server', { error }, getCorrelationId('system-start'));
|
|
60
|
+
else logger.error('fatal error: could not start server', { name: config.serverSettings.name, id: config.serverSettings.id, error }, correlationId);
|
|
61
|
+
logger.flushAndExit(1);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
if (!config) return fatalError(new Error('config is required'));
|
|
57
65
|
const { serverSettings, dependencies } = config;
|
|
58
|
-
const server = http.createServer(app);
|
|
59
|
-
const correlationIdStart = `system-start-${serverSettings.id}`;
|
|
60
|
-
const correlationIdShut = `system-shutdown-${serverSettings.id}`;
|
|
61
66
|
const serverPort = serverSettings.port;
|
|
67
|
+
const correlationIdStart = getCorrelationId(`system-start:${serverSettings.id}`);
|
|
68
|
+
|
|
69
|
+
if (!cluster) return fatalError(new Error('cluster lib required'), correlationIdStart);
|
|
70
|
+
if (!app) return fatalError(new Error('app is required'), correlationIdStart);
|
|
71
|
+
const { register, unRegister } = cluster;
|
|
72
|
+
const oauth = oauthHelper(config);
|
|
73
|
+
const server = http.createServer(app);
|
|
62
74
|
|
|
63
75
|
let swaggerFilename = serverSettings.api;
|
|
64
76
|
let extractName = null;
|
|
65
77
|
let registration = false;
|
|
66
78
|
|
|
67
|
-
process.on(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
79
|
+
process.on(SIGINT, () => {
|
|
80
|
+
sigProcess(SIGINT, registration, options, config, server, unRegister, getCorrelationId(`system-shutdown(${SIGINT}):${serverSettings.id}`));
|
|
81
|
+
});
|
|
82
|
+
process.on(SIGTERM, () => {
|
|
83
|
+
sigProcess(SIGTERM, registration, options, config, server, unRegister, getCorrelationId(`system-shutdown(${SIGTERM}):${serverSettings.id}`));
|
|
73
84
|
});
|
|
74
85
|
|
|
75
|
-
app.use(helmet(
|
|
86
|
+
app.use(helmet.contentSecurityPolicy({
|
|
87
|
+
directives: {
|
|
88
|
+
...helmet.contentSecurityPolicy.getDefaultDirectives(),
|
|
89
|
+
'script-src': ['\'self\'', '\'unsafe-inline\''],
|
|
90
|
+
'connect-src': ['\'self\'', '*.swagger.io'],
|
|
91
|
+
},
|
|
92
|
+
}));
|
|
76
93
|
if (options && options.extractName) {
|
|
77
94
|
({ extractName } = options);
|
|
78
95
|
if (!dependencies || !dependencies.mLG) {
|
|
@@ -85,7 +102,7 @@ module.exports = (app, rootDir, config, dbValidate, options) => {
|
|
|
85
102
|
if (swaggerFilename[0] !== '/') swaggerFilename = path.join(rootDir, swaggerFilename);
|
|
86
103
|
logger.debug('location of the swagger file', { swaggerFilename }, correlationIdStart);
|
|
87
104
|
return swagger.getAPIFile(swaggerFilename, correlationIdStart)
|
|
88
|
-
.then(swaggerJson => swaggerTools.initializeMiddleware(swaggerJson, (middleware) => {
|
|
105
|
+
.then((swaggerJson) => swaggerTools.initializeMiddleware(swaggerJson, (middleware) => {
|
|
89
106
|
serverSettings.basePath = swaggerJson.basePath;
|
|
90
107
|
app.use(cors({ origin: '*' }));
|
|
91
108
|
app.use(middleware.swaggerMetadata());
|
|
@@ -95,6 +112,7 @@ module.exports = (app, rootDir, config, dbValidate, options) => {
|
|
|
95
112
|
AdminSecurity: oauth.apiTokenAdminSecurityHelper,
|
|
96
113
|
SystemSecurity: oauth.apiTokenSecurityHelper,
|
|
97
114
|
UserSecurity: oauth.apiTokenSecurityHelper,
|
|
115
|
+
APIKeySecurity: oauth.apiKeySecurityHelper,
|
|
98
116
|
};
|
|
99
117
|
|
|
100
118
|
if (options && options.secOptions) {
|
|
@@ -114,38 +132,32 @@ module.exports = (app, rootDir, config, dbValidate, options) => {
|
|
|
114
132
|
}
|
|
115
133
|
app.use(middleware.swaggerRouter({
|
|
116
134
|
useStubs: config.nodeEnvironment === 'local',
|
|
117
|
-
controllers:
|
|
135
|
+
controllers: `${rootDir}/controllers`,
|
|
118
136
|
}));
|
|
119
137
|
app.use(middleware.swaggerUi());
|
|
120
138
|
app.use(swagger.sendError);
|
|
121
139
|
if (serverSettings.interceptError === 'on') {
|
|
122
140
|
app.use(swagger.interceptError);
|
|
123
141
|
}
|
|
124
|
-
return
|
|
125
|
-
.then(() =>
|
|
126
|
-
.then(() => getPublic(config.locationProvider, config.cloudProvider).then((publicConfig) => {
|
|
142
|
+
return Promise.each(validates, (validate) => validate())
|
|
143
|
+
.then(() => getPublic(config.locationProvider, config.cloudProvider, correlationIdStart).then((publicConfig) => {
|
|
127
144
|
logger.info('public environment', { status: publicConfig.status }, correlationIdStart);
|
|
128
145
|
serverSettings.ip.public = publicConfig.ip || serverSettings.ip.public;
|
|
129
146
|
serverSettings.instanceId = publicConfig.id;
|
|
130
147
|
serverSettings.public.location = publicConfig.location || serverSettings.public.location;
|
|
131
148
|
}))
|
|
132
149
|
.then(() => {
|
|
133
|
-
if (options && options.preOps) return Promise.each(options.preOps, ops => ops(correlationIdStart, config, server));
|
|
150
|
+
if (options && options.preOps) return Promise.each(options.preOps, (ops) => ops(correlationIdStart, config, server));
|
|
134
151
|
return null;
|
|
135
152
|
})
|
|
136
153
|
.then(() => {
|
|
137
154
|
server.listen(serverPort, () => {
|
|
138
155
|
startupHealthInfo(config, correlationIdStart);
|
|
139
156
|
if (registration) register(correlationIdStart);
|
|
140
|
-
if (options && options.postOps) options.postOps.forEach(ops => ops(correlationIdStart, config, server));
|
|
157
|
+
if (options && options.postOps) options.postOps.forEach((ops) => ops(correlationIdStart, config, server));
|
|
141
158
|
});
|
|
142
159
|
})
|
|
143
|
-
.catch((error) =>
|
|
144
|
-
logger.error('fatal error: could not start server', {
|
|
145
|
-
name: serverSettings.name, id: serverSettings.id, error,
|
|
146
|
-
}, correlationIdStart);
|
|
147
|
-
logger.flushAndExit(1);
|
|
148
|
-
});
|
|
160
|
+
.catch((error) => fatalError(error, correlationIdStart));
|
|
149
161
|
}))
|
|
150
162
|
.then(() => ({ config }));
|
|
151
163
|
};
|
package/lib/exit.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const Promise = require('bluebird');
|
|
2
|
+
|
|
3
|
+
const logger = require('@mimik/sumologic-winston-logger');
|
|
4
|
+
|
|
5
|
+
const SHUTDOWN = 'service shutdown successfully';
|
|
6
|
+
const SHUTDOWN_WITH_ERROR = 'service shutdown with error';
|
|
7
|
+
|
|
8
|
+
const shutdown = (res, correlationId) => {
|
|
9
|
+
if (res.errors) {
|
|
10
|
+
logger.warn(SHUTDOWN_WITH_ERROR, res, correlationId);
|
|
11
|
+
logger.flushAndExit(1);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
logger.info(SHUTDOWN, res, correlationId);
|
|
15
|
+
logger.flushAndExit(0);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const sigProcess = (signal, registration, options, config, server, unRegister, correlationId) => {
|
|
20
|
+
if (registration) {
|
|
21
|
+
return unRegister(correlationId)
|
|
22
|
+
.then((origResult) => {
|
|
23
|
+
const result = origResult;
|
|
24
|
+
|
|
25
|
+
result.signal = signal;
|
|
26
|
+
if (!options || !options.exitOps) {
|
|
27
|
+
return shutdown(result, correlationId);
|
|
28
|
+
}
|
|
29
|
+
return Promise.each(options.exitOps, (ops) => ops(correlationId, config, server)
|
|
30
|
+
.catch((err) => {
|
|
31
|
+
if (result.errors) result.errors.push(err);
|
|
32
|
+
else result.errors = [err];
|
|
33
|
+
}))
|
|
34
|
+
.then(() => shutdown(result, correlationId));
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
logger.info(SHUTDOWN, { serverId: config.serverSettings.id, signal }, correlationId);
|
|
38
|
+
logger.flushAndExit(0);
|
|
39
|
+
return null;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
module.exports = {
|
|
43
|
+
sigProcess,
|
|
44
|
+
};
|
package/lib/logs.js
CHANGED
|
@@ -3,8 +3,10 @@ const urlLib = require('url');
|
|
|
3
3
|
const { publicIpFromRequest } = require('@mimik/address-helper');
|
|
4
4
|
const oauthHelper = require('@mimik/oauth-helper');
|
|
5
5
|
const logger = require('@mimik/sumologic-winston-logger');
|
|
6
|
+
const { getRichError } = require('@mimik/response-helper');
|
|
7
|
+
const { getCorrelationId } = require('@mimik/request-helper');
|
|
6
8
|
|
|
7
|
-
const correlationId = 'log-extraction';
|
|
9
|
+
const correlationId = getCorrelationId('log-extraction');
|
|
8
10
|
const NOTIFICATION = '/notifications';
|
|
9
11
|
|
|
10
12
|
const extractLogs = (config, extractName) => (req, res, next) => {
|
|
@@ -27,15 +29,14 @@ const extractLogs = (config, extractName) => (req, res, next) => {
|
|
|
27
29
|
method: 'POST',
|
|
28
30
|
headers: {
|
|
29
31
|
'x-forwarded-for': xForwardedFor,
|
|
32
|
+
'x-correlation-id': correlationId,
|
|
30
33
|
},
|
|
31
34
|
url,
|
|
32
35
|
body: {
|
|
33
36
|
Message: req.body[extractName],
|
|
34
37
|
},
|
|
35
38
|
json: true,
|
|
36
|
-
}).catch(err =>
|
|
37
|
-
url, error: err.message, statusCode: err.statusCode || 500, extractName,
|
|
38
|
-
}, correlationId));
|
|
39
|
+
}).catch((err) => getRichError('System', 'could not send extracted data', { url, extractName }, err, 'warn', correlationId));
|
|
39
40
|
delete req.body[extractName];
|
|
40
41
|
}
|
|
41
42
|
next();
|
package/package.json
CHANGED
|
@@ -1,54 +1,60 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mimik/init",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.6.0",
|
|
4
4
|
"description": "Init process for micro-service",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"lint": "gulp lint",
|
|
8
8
|
"docs": "gulp docs",
|
|
9
|
-
"test": "exit 0"
|
|
9
|
+
"test": "exit 0",
|
|
10
|
+
"prepublishOnly": "gulp docs; gulp lint; npm run test",
|
|
11
|
+
"commit-ready": "gulp docs; gulp lint; npm run test",
|
|
12
|
+
"prepare": "husky install"
|
|
10
13
|
},
|
|
11
14
|
"husky": {
|
|
12
15
|
"hooks": {
|
|
13
|
-
"pre-commit": "npm run
|
|
14
|
-
"pre-push": "npm run
|
|
16
|
+
"pre-commit": "npm run commit-ready",
|
|
17
|
+
"pre-push": "npm run test"
|
|
15
18
|
}
|
|
16
19
|
},
|
|
17
20
|
"keywords": [
|
|
18
21
|
"mimik",
|
|
19
22
|
"microservice"
|
|
20
23
|
],
|
|
21
|
-
"author": "mimik",
|
|
24
|
+
"author": "mimik technology inc <support@mimik.com> (https://developer.mimik.com/)",
|
|
22
25
|
"license": "Apache-2.0",
|
|
23
26
|
"repository": {
|
|
24
27
|
"type": "git",
|
|
25
28
|
"url": "https://bitbucket.org/mimiktech/init"
|
|
26
29
|
},
|
|
27
30
|
"dependencies": {
|
|
28
|
-
"@mimik/address-helper": "1.2
|
|
29
|
-
"@mimik/
|
|
30
|
-
"@mimik/
|
|
31
|
-
"@mimik/
|
|
32
|
-
"@mimik/
|
|
33
|
-
"@mimik/
|
|
34
|
-
"@mimik/sumologic-winston-logger": "1.
|
|
35
|
-
"@mimik/swagger-helper": "2.
|
|
36
|
-
"bluebird": "3.
|
|
31
|
+
"@mimik/address-helper": "^1.6.2",
|
|
32
|
+
"@mimik/healthcheck": "^1.5.7",
|
|
33
|
+
"@mimik/oauth-helper": "^1.9.6",
|
|
34
|
+
"@mimik/public-helper": "^1.5.3",
|
|
35
|
+
"@mimik/request-helper": "^1.7.3",
|
|
36
|
+
"@mimik/response-helper": "^2.6.0",
|
|
37
|
+
"@mimik/sumologic-winston-logger": "^1.6.6",
|
|
38
|
+
"@mimik/swagger-helper": "^2.5.0",
|
|
39
|
+
"bluebird": "3.7.2",
|
|
37
40
|
"cors": "2.8.5",
|
|
38
|
-
"helmet": "
|
|
41
|
+
"helmet": "4.6.0",
|
|
39
42
|
"swagger-tools": "0.10.4"
|
|
40
43
|
},
|
|
41
44
|
"devDependencies": {
|
|
42
|
-
"eslint": "
|
|
43
|
-
"eslint-
|
|
44
|
-
"eslint
|
|
45
|
-
"eslint-
|
|
46
|
-
"eslint-plugin-
|
|
45
|
+
"@mimik/eslint-plugin-dependencies": "^2.4.1",
|
|
46
|
+
"@mimik/eslint-plugin-document-env": "^1.0.0",
|
|
47
|
+
"eslint": "8.4.1",
|
|
48
|
+
"eslint-config-airbnb": "18.2.1",
|
|
49
|
+
"eslint-plugin-import": "2.25.3",
|
|
50
|
+
"eslint-plugin-jsx-a11y": "6.5.1",
|
|
51
|
+
"eslint-plugin-react": "7.27.1",
|
|
52
|
+
"eslint-plugin-react-hooks": "4.3.0",
|
|
47
53
|
"fancy-log": "1.3.3",
|
|
48
54
|
"gulp": "4.0.2",
|
|
49
55
|
"gulp-eslint": "6.0.0",
|
|
50
|
-
"gulp-git": "2.
|
|
51
|
-
"husky": "
|
|
52
|
-
"jsdoc-to-markdown": "
|
|
56
|
+
"gulp-git": "2.10.1",
|
|
57
|
+
"husky": "7.0.4",
|
|
58
|
+
"jsdoc-to-markdown": "7.1.0"
|
|
53
59
|
}
|
|
54
60
|
}
|