koa-actuator
Advanced tools
Comparing version 0.4.1 to 0.5.0
const compose = require('koa-compose'); | ||
const assert = require('assert'); | ||
const {loadPackageJson} = require('./utils'); | ||
const {loadPackageJson, loadGitProperties, unescape} = require('./utils'); | ||
const package_json = loadPackageJson(); | ||
const git_properties = loadGitProperties(); | ||
@@ -71,15 +72,27 @@ const HEALTH_PATH = '/health'; | ||
if (INFO_ENDPOINT === ctx.path) { | ||
const infoResponseBody = {}; | ||
if (package_json) { | ||
ctx.body = { | ||
build: | ||
{ | ||
version: package_json.version, | ||
name: package_json.name, | ||
main: package_json.main, | ||
description: package_json.description | ||
} | ||
}; | ||
} else { | ||
ctx.body = {}; | ||
infoResponseBody.build = | ||
{ | ||
version: package_json.version, | ||
name: package_json.name, | ||
main: package_json.main, | ||
description: package_json.description | ||
}; | ||
} | ||
if (git_properties) { | ||
infoResponseBody.git = | ||
{ | ||
commit: { | ||
time: { | ||
epochSecond: Math.ceil(new Date(unescape(git_properties.path().git.commit.time, /\\/g)).getTime()/1000), | ||
nano: 0 | ||
}, | ||
id: git_properties.path().git.commit.id.abbrev | ||
}, | ||
branch: git_properties.path().git.branch | ||
}; | ||
} | ||
ctx.body = infoResponseBody; | ||
} else { | ||
@@ -86,0 +99,0 @@ await next(); |
const path = require('path'); | ||
const appRootPath = require('app-root-path'); | ||
const fs = require('fs'); | ||
const PropertiesReader = require('properties-reader'); | ||
module.exports.loadPackageJson = function loadPackageJson() { | ||
const pathToPackageJson = findFilePathInProjectRootDir('package.json'); | ||
if (!pathToPackageJson) | ||
return null; | ||
try { | ||
return require(appRootPath + path.sep + 'package.json'); | ||
return require(pathToPackageJson); | ||
} catch (e) { | ||
try { | ||
return require(process.cwd() + path.sep + 'package.json'); | ||
} catch (e) { | ||
try { | ||
return require('../../../package.json'); | ||
} catch (e) { | ||
return null; | ||
} | ||
} | ||
return null; | ||
} | ||
}; | ||
module.exports.loadGitProperties = function loadGitProperties() { | ||
const pathToGitProperties = findFilePathInProjectRootDir('git.properties'); | ||
return pathToGitProperties ? new PropertiesReader(pathToGitProperties) : null; | ||
}; | ||
module.exports.unescape = function unescape(str, symbols) { | ||
return str ? str.replace(symbols, '') : ''; | ||
}; | ||
/** | ||
* The function tries to find the file with the given name in apps root dir. | ||
* @param fileName - end file name, e.g. 'package.json' | ||
* @returns path to found file or null; | ||
*/ | ||
function findFilePathInProjectRootDir(fileName) { | ||
const pathsToSearchIn = [appRootPath + path.sep + fileName, process.cwd() + path.sep + fileName, '../../../' + fileName]; | ||
for (let idx in pathsToSearchIn) { | ||
const filePath = pathsToSearchIn[idx]; | ||
if (fs.existsSync(filePath)) | ||
return filePath; | ||
} | ||
return null; | ||
} |
{ | ||
"name": "koa-actuator", | ||
"version": "0.4.1", | ||
"version": "0.5.0", | ||
"description": "Healthcheck and monitoring middleware for koa inspired by java spring's actuators", | ||
@@ -19,3 +19,4 @@ "main": "lib/index.js", | ||
"app-root-path": "^2.0.1", | ||
"koa-compose": "^4.0.0" | ||
"koa-compose": "^4.0.0", | ||
"properties-reader": "0.0.16" | ||
}, | ||
@@ -22,0 +23,0 @@ "devDependencies": { |
@@ -75,2 +75,23 @@ # koa-actuator | ||
} | ||
``` | ||
If git.properties file is present in application root directory, git section will also be available. In this case the response will look like: | ||
```json | ||
{ | ||
"build": { | ||
"version": "1.0.0", | ||
"name": "koa-act-test", | ||
"main": "index.js", | ||
"description": "test" | ||
}, | ||
"git": { | ||
"commit": { | ||
"time": { | ||
"epochSecond": 1531473434, | ||
"nano": 0 | ||
}, | ||
"id": "a94ff08" | ||
}, | ||
"branch": "origin/master" | ||
} | ||
} | ||
``` |
128
test/test.js
@@ -1,2 +0,1 @@ | ||
const actuator = require('../lib/index'); | ||
const Koa = require('koa'); | ||
@@ -7,2 +6,5 @@ const request = require('supertest'); | ||
const sinon = require('sinon'); | ||
const fs = require('fs'); | ||
const {copyFileSync} = require('./utils'); | ||
const actuator = require('../lib/index'); | ||
@@ -155,55 +157,91 @@ describe('koa-actuator', () => { | ||
it('should return 200 and version', (done) => { | ||
//arrange | ||
const app = new Koa(); | ||
app.use(actuator()); | ||
describe('build info', () => { | ||
it('should return 200 and version', (done) => { | ||
//arrange | ||
const app = new Koa(); | ||
app.use(actuator()); | ||
//act & assert | ||
request(app.callback()) | ||
.get('/actuator/info') | ||
.expect(200) | ||
.end((err, res) => { | ||
if (err) return done(err); | ||
assert.isDefined(res.body.build.version); | ||
done(); | ||
}); | ||
}); | ||
//act & assert | ||
request(app.callback()) | ||
.get('/actuator/info') | ||
.expect(200) | ||
.end((err, res) => { | ||
if (err) return done(err); | ||
assert.isDefined(res.body.build.version); | ||
done(); | ||
}); | ||
}); | ||
it('should use parameter actuatorPath if it is defined', (done) => { | ||
//arrange | ||
const options = {actuatorPath: '/custom-actuator-path'}; | ||
it('should use parameter actuatorPath if it is defined', (done) => { | ||
//arrange | ||
const options = {actuatorPath: '/custom-actuator-path'}; | ||
const app = new Koa(); | ||
app.use(actuator({}, options)); | ||
const app = new Koa(); | ||
app.use(actuator({}, options)); | ||
//act & assert | ||
request(app.callback()) | ||
.get('/custom-actuator-path/info') | ||
.expect(200) | ||
.end((err, res) => { | ||
if (err) return done(err); | ||
assert.isDefined(res.body.build.version); | ||
done(); | ||
}); | ||
//act & assert | ||
request(app.callback()) | ||
.get('/custom-actuator-path/info') | ||
.expect(200) | ||
.end((err, res) => { | ||
if (err) return done(err); | ||
assert.isDefined(res.body.build.version); | ||
done(); | ||
}); | ||
}); | ||
it('should return 200 and empty object if package.json not found', (done) => { | ||
//arrange | ||
sinon.stub(utils, 'loadPackageJson').returns(null); | ||
delete require.cache[require.resolve('../lib/index')]; | ||
const actuator = require('../lib/index'); | ||
const app = new Koa(); | ||
app.use(actuator()); | ||
//act & assert | ||
request(app.callback()) | ||
.get('/actuator/info') | ||
.expect(200) | ||
.end((err, res) => { | ||
if (err) return done(err); | ||
assert.deepEqual(res.body, {}); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
describe('git info', () => { | ||
let actuator; | ||
it('should return 200 and empty object if package.json not found', (done) => { | ||
//arrange | ||
sinon.stub(utils, 'loadPackageJson').returns(null); | ||
delete require.cache[require.resolve('../lib/index')]; | ||
const actuator = require('../lib/index'); | ||
//copy git.properties file to app root dir and delete the app from require cache in order to re-read properties file | ||
before((done)=>{ | ||
copyFileSync('./test/git.properties.example', './git.properties'); | ||
delete require.cache[require.resolve('../lib/index')]; | ||
actuator = require('../lib/index'); | ||
done(); | ||
}); | ||
const app = new Koa(); | ||
app.use(actuator()); | ||
after((done) => { | ||
fs.unlink('./git.properties', done); | ||
}); | ||
//act & assert | ||
request(app.callback()) | ||
.get('/actuator/info') | ||
.expect(200) | ||
.end((err, res) => { | ||
if (err) return done(err); | ||
assert.deepEqual(res.body, {}); | ||
done(); | ||
}); | ||
it('should expose git-related info if git.properties file is present', (done) => { | ||
//arrange | ||
const app = new Koa(); | ||
app.use(actuator()); | ||
//act & assert | ||
request(app.callback()) | ||
.get('/actuator/info') | ||
.expect(200) | ||
.end((err, res) => { | ||
if (err) return done(err); | ||
assert.equal(res.body.git.commit.id, 'a94ff08'); | ||
assert.equal(res.body.git.branch, 'master'); | ||
assert.equal(res.body.git.commit.time.epochSecond, 1531473434); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
@@ -210,0 +248,0 @@ }); |
const appRootPath = require('app-root-path'); | ||
const path = require('path'); | ||
const mock = require('mock-require'); | ||
const sinon = require('sinon'); | ||
const fs = require('fs'); | ||
const {assert} = require('chai'); | ||
@@ -8,2 +10,3 @@ | ||
describe('loadPackageJson', () => { | ||
const sandbox = sinon.createSandbox(); | ||
after(() => { | ||
@@ -13,2 +16,4 @@ mock.stopAll(); | ||
afterEach(() => {sandbox.restore();}); | ||
it('should require package.json using app-root-path', () => { | ||
@@ -32,2 +37,3 @@ const mockedPackageJson = {description: 'package.json from app-root-path'}; | ||
it('should require package.json from relative path if CWD fails', () => { | ||
sandbox.stub(fs, 'existsSync').withArgs('../../../package.json').returns(true); | ||
const mockedPackageJson = {description: 'package.json from relative path'}; | ||
@@ -34,0 +40,0 @@ mock(appRootPath + path.sep + 'package.json', 'not_exiting'); |
Sorry, the diff of this file is not supported yet
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
20014
11
392
96
3
5
+ Addedproperties-reader@0.0.16
+ Addedminimist@1.2.8(transitive)
+ Addedmkdirp@0.5.6(transitive)
+ Addedproperties-reader@0.0.16(transitive)