├── .gitignore ├── .travis.yml ├── images └── node-info.png ├── example └── node-info.js ├── package.json ├── LICENSE ├── README.md ├── lib ├── index.js └── tpl │ └── nodeinfo.ejs ├── test └── unit │ └── ni.js └── model └── ni.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .DS_Store 4 | .DS_Store? 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | - "0.11" 5 | -------------------------------------------------------------------------------- /images/node-info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yahoo/node-info/master/images/node-info.png -------------------------------------------------------------------------------- /example/node-info.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Yahoo! Inc. All rights reserved. 3 | * Copyrights licensed under the New BSD License. 4 | * See the accompanying LICENSE file for terms. 5 | */ 6 | 7 | var express = require('express'), 8 | nodeinfo = require('../lib/index.js'), 9 | app = express(); 10 | 11 | app.use(nodeinfo({ 12 | url: '/node-info', 13 | check: function(req) { 14 | if (req.something === false) { 15 | 16 | // don't show nodeinfo 17 | return false; 18 | } 19 | 20 | // show nodeinfo 21 | return true; 22 | } 23 | })); 24 | 25 | console.log('Go to: http://127.0.0.1:8000/node-info'); 26 | app.listen(8000); 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-info", 3 | "description": "view nodejs environment information", 4 | "version": "2.0.0", 5 | "author": "Suresh Kumar. M ", 6 | "dependencies": { 7 | "ejs": "^2.5.5", 8 | "github-url-from-git": "~1.4.0", 9 | "read-installed": "~3.1.0", 10 | "read-package-json": "^2.0.13", 11 | "timethat": "~0.0.2" 12 | }, 13 | "devDependencies": { 14 | "express": "^4.16.3", 15 | "istanbul": "^0.4.5", 16 | "jshint": "^2.9.6", 17 | "mocha": "^5.2.0", 18 | "mockery": "^1.4.0" 19 | }, 20 | "main": "./lib/index.js", 21 | "keywords": [ 22 | "environment info", 23 | "environment details", 24 | "information", 25 | "node-information", 26 | "node-info", 27 | "environment-info" 28 | ], 29 | "scripts": { 30 | "test": "istanbul cover --hook-run-in-context node_modules/mocha/bin/_mocha -- -R spec ./test/unit/ni.js" 31 | }, 32 | "licenses": [ 33 | { 34 | "type": "BSD", 35 | "url": "https://github.com/yahoo/node-info/blob/master/LICENSE" 36 | } 37 | ], 38 | "bugs": { 39 | "url": "https://github.com/yahoo/node-info/issues" 40 | }, 41 | "repository": { 42 | "type": "git", 43 | "url": "https://github.com/yahoo/node-info.git" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Yahoo! Inc. All rights reserved. 2 | 3 | Redistribution and use of this software in source and binary forms, 4 | with or without modification, are permitted provided that the following 5 | conditions are met: 6 | 7 | * Redistributions of source code must retain the above 8 | copyright notice, this list of conditions and the 9 | following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the 13 | following disclaimer in the documentation and/or other 14 | materials provided with the distribution. 15 | 16 | * Neither the name of Yahoo! Inc. nor the names of its 17 | contributors may be used to endorse or promote products 18 | derived from this software without specific prior 19 | written permission of Yahoo! Inc. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 22 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 24 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ARCHIVED 2 | 3 | 4 | Node environment information [![Build Status](https://travis-ci.org/yahoo/node-info.svg?branch=master)](https://travis-ci.org/yahoo/node-info) 5 | =========================== 6 | It's a simple middleware which would give the node environment details as follow 7 | 8 | * basic node environment details such as node version, cpu, memory and platform 9 | * all the installed node packages and their dependencies 10 | * shows dependencies and dev dependencies packages separately 11 | * additionally it gives a little more info about each package details like author, url etc. 12 | 13 | Installation 14 | -------------- 15 | 16 | `npm install node-info` 17 | 18 | Usage 19 | ----------- 20 | Add the below lines in your express middleware to view the node env information. 21 | 22 | ```javascript 23 | var nodeinfo = require('node-info'); 24 | app.use(nodeinfo()); 25 | ``` 26 | 27 | Please check the [example code](example/node-info.js) 28 | 29 | Screenshot 30 | -------------- 31 | ![nodeinfo](images/node-info.png) 32 | 33 | This module is supported by the [ejs](https://github.com/visionmedia/ejs), [github-url-from-git](https://github.com/visionmedia/node-github-url-from-git), [read-installed](https://www.npmjs.org/package/read-installed), [timethat](https://github.com/davglass/timethat), [read-package-json](https://github.com/npm/read-package-json) and [node-github-url-from-git](https://github.com/visionmedia/node-github-url-from-git) node modules. 34 | 35 | License 36 | ----------- 37 | 38 | Code licensed under the BSD license. See [LICENSE file][] file for terms. 39 | 40 | [LICENSE file]: https://github.com/yahoo/node-info/blob/master/LICENSE 41 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Yahoo! Inc. All rights reserved. 3 | * Copyrights licensed under the New BSD License. 4 | * See the accompanying LICENSE file for terms. 5 | */ 6 | 7 | var url = require('url'), 8 | ejs = require('ejs'), 9 | fs = require('fs'), 10 | ni = require('../model/ni'), 11 | ejsStr, 12 | n, d; 13 | 14 | module.exports = function (config) { 15 | 16 | config = config || {}; 17 | config.url = config.url || '/node-info'; 18 | config.errMessage = config.errMessage || 'Not Found'; 19 | config.errCode = config.errCode || 404; 20 | 21 | // valid values are html or json 22 | config.responseContentType = config.responseContentType || 'html'; 23 | 24 | if (config.responseContentType !== 'json') { 25 | config.ejsTemplate = config.ejsTemplate || require('path').join(__dirname, 'tpl/nodeinfo.ejs'); 26 | 27 | ejsStr = fs.readFileSync(config.ejsTemplate, 'utf8'); 28 | } 29 | 30 | return function (req, res, next) { 31 | if (url.parse(req.url).pathname === config.url) { 32 | if (typeof config.check !== "function" || config.check(req)) { 33 | 34 | // nodeinfo instance variable 35 | n = ni(req); 36 | n.getModulesInfo(process.cwd(), function (err, data) { 37 | 38 | //TODO: error handling 39 | if (err) { 40 | res.writeHead(500, {'Content-Type' : 'text/plain'}); 41 | res.end("problem getting the modules info"); 42 | } 43 | 44 | d = data; 45 | n.getSystemInfo(function (err, data) { 46 | data.pkgs = d.pkgs; 47 | if (config.responseContentType === 'json') { 48 | res.writeHead(200, {'Content-Type' : 'application/json'}); 49 | res.end(JSON.stringify(data)); 50 | } else { 51 | res.writeHead(200, {'Content-Type' : 'text/html'}); 52 | 53 | // check if its defined 54 | data.isDefined = function(obj) { 55 | return typeof(obj) !== "undefined"; 56 | }; 57 | 58 | // check if its an object 59 | data.isObject = function(obj) { 60 | return Object.keys(obj).length > 0; 61 | }; 62 | 63 | res.end(ejs.render(ejsStr, data)); 64 | } 65 | }); 66 | }); 67 | } else { 68 | res.writeHead(config.errCode, {'Content-Type' : 'text/plain'}); 69 | res.end(config.errMessage); 70 | } 71 | } else { 72 | next(); 73 | } 74 | }; 75 | }; 76 | -------------------------------------------------------------------------------- /test/unit/ni.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Yahoo! Inc. All rights reserved. 3 | * Copyrights licensed under the New BSD License. 4 | * See the accompanying LICENSE file for terms. 5 | */ 6 | 7 | /* global describe, it, beforeEach */ 8 | 'use strict'; 9 | 10 | var assert = require('assert'), 11 | mockery = require('mockery'), 12 | error, 13 | ni, 14 | devDependency, 15 | selfPkg; 16 | 17 | 18 | mockery.registerMock('read-installed', function (err, options, cb) { 19 | var deps = {dependencies: null, devDependencies: null}; 20 | 21 | if (error) { 22 | cb(null, deps); 23 | return; 24 | } 25 | 26 | // mocking the dependency module 27 | deps.dependencies = [{ 28 | 'name': 'moduleName', 29 | 'description': 'description', 30 | 'version': '1.0.0', 31 | 'author': 'author info', 32 | 'repository': { url: 'git://repo-URL' }, 33 | 'dependencies': 'deps info', 34 | 'dist': 'dist URL' 35 | }]; 36 | 37 | if (devDependency) { 38 | deps.devDependencies = { 39 | 'moduleName': 'version', 40 | }; 41 | } else { 42 | deps.dependencies[0].repository = null; 43 | deps.devDependencies = { 44 | 'module': 'version' 45 | }; 46 | } 47 | 48 | cb(null, deps); 49 | }); 50 | 51 | mockery.registerMock('github-url-from-git', function () { 52 | return 'https://URL'; 53 | }); 54 | 55 | mockery.registerMock('read-package-json', function(file, err, bool, cb) { 56 | if (selfPkg) { 57 | cb(null, {name: 'node-info'}); 58 | } 59 | cb({}, null); 60 | }); 61 | 62 | mockery.enable({ 63 | warnOnReplace: false, 64 | warnOnUnregistered: false 65 | }); 66 | 67 | ni = require('../../model/ni'); 68 | 69 | describe('node-info -> model -> ni', function () { 70 | var n, f; 71 | 72 | beforeEach(function () { 73 | error = false; 74 | n = new ni(null); 75 | devDependency = false; 76 | }); 77 | 78 | describe('ni()', function () { 79 | 80 | it('should be a function.', function () { 81 | assert.equal(typeof ni, 'function'); 82 | }); 83 | 84 | it('should return an object.', function () { 85 | assert.equal(typeof n, 'object'); 86 | }); 87 | }); 88 | 89 | describe('ni.getModulesInfo()', function () { 90 | f = 'path/to/node_modules'; 91 | 92 | it('should return null if there is no deps modules', function (next) { 93 | error = true; 94 | n.getModulesInfo(f, function (err, data) { 95 | assert.equal(data, null); 96 | next(); 97 | }); 98 | }); 99 | 100 | it('should return all the dependencies if there is no error', function (next) { 101 | devDependency = true; 102 | n.getModulesInfo(f, function (err, data) { 103 | assert.equal(typeof data.pkgs, 'object'); 104 | next(); 105 | }); 106 | }); 107 | 108 | it('should return only the dependencies if there is no dev deps', function (next) { 109 | n.getModulesInfo(f, function (err, data) { 110 | assert.equal(typeof data.pkgs, 'object'); 111 | next(); 112 | }); 113 | }); 114 | 115 | it('should return the self info if there is no error reading the package.json', function (next) { 116 | selfPkg = true; 117 | n.getModulesInfo(f, function (err, data) { 118 | assert.equal(data.pkgs[0].name, 'node-info'); 119 | assert.equal(data.pkgs[0].selfPkg, true); 120 | }); 121 | next(); 122 | }); 123 | }); 124 | 125 | describe('ni.getSystemInfo()', function () { 126 | 127 | it('should return all the sys info if there is no error', function (next) { 128 | delete process.env.USER; 129 | delete process.env.LANG; 130 | delete process.platform; 131 | delete process.arch; 132 | delete process.pid; 133 | 134 | n.getSystemInfo(function (err, data) { 135 | assert.equal(typeof data.sys, 'object'); 136 | next(); 137 | }); 138 | }); 139 | 140 | it('should return all the proc info if there is no error', function (next) { 141 | n.getSystemInfo(function (err, data) { 142 | assert.equal(Object.keys(data.sys[0].proc).length > 0, true); 143 | next(); 144 | }); 145 | }); 146 | 147 | it('should return all the os info if there is no error', function (next) { 148 | n.getSystemInfo(function (err, data) { 149 | assert.equal(Object.keys(data.sys[1].os).length > 0, true); 150 | next(); 151 | }); 152 | }); 153 | }); 154 | 155 | describe('ni.compare()', function () { 156 | 157 | it('should return true if the first value is greater than the second', function (next) { 158 | var obj = [ {'name': 2}, {'name': 1}], 159 | sortedObj = n.compare (obj); 160 | assert.equal(sortedObj[0].name, 1); 161 | next(); 162 | }); 163 | 164 | it('should return true if the first value is smaller than the second', function (next) { 165 | var obj = [ {'name': 1}, {'name': 2}], 166 | sortedObj = n.compare (obj); 167 | assert.equal(sortedObj[0].name, 1); 168 | next(); 169 | }); 170 | 171 | it('should return true if the first value is same as the second', function (next) { 172 | var obj = [ {'name': 1}, {'name': 1}], 173 | sortedObj = n.compare (obj); 174 | assert.equal(sortedObj[0].name, 1); 175 | next(); 176 | }); 177 | }); 178 | }); 179 | -------------------------------------------------------------------------------- /model/ni.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Yahoo! Inc. All rights reserved. 3 | * Copyrights licensed under the New BSD License. 4 | * See the accompanying LICENSE file for terms. 5 | */ 6 | 7 | /* jshint camelcase: false */ 8 | 'use strict'; 9 | 10 | // require all the libs 11 | var ri = require('read-installed'); 12 | var tt = require('timethat'); 13 | var path = require('path'); 14 | var gitURL = require('github-url-from-git'); 15 | var readJSON = require('read-package-json'); 16 | 17 | /** 18 | * Data Access Object to handle the node pkgs, system info 19 | * @module NodeInfo 20 | */ 21 | 22 | /** 23 | * NodeInfo (node info) constructor to handle the info 24 | * 25 | * @class NodeInfo 26 | * @constructor 27 | * @param {Object} req node express request object 28 | */ 29 | var NodeInfo = function (req) { 30 | this.request = req; 31 | }; 32 | 33 | /** 34 | * get all the installed node modules info 35 | * 36 | * @method getModulesInfo 37 | * @param {String} f the folder to be traversed 38 | * @param {Function} cb a callback 39 | */ 40 | NodeInfo.prototype.getModulesInfo = function (f, cb) { 41 | var options = { dev: false, depth: 1 }, 42 | resp, 43 | depsList, 44 | devDepsList, 45 | deps, 46 | devDeps, 47 | selfInfo, 48 | pkg, 49 | defaultString = '-'; 50 | 51 | // read all the modules in the given directory 52 | ri(f, options, function (err, data) { 53 | deps = data.dependencies || null; 54 | 55 | if (!deps) { 56 | 57 | // return the response 58 | cb(err, null); 59 | return; 60 | } 61 | 62 | devDeps = data.devDependencies; 63 | resp = []; 64 | depsList = []; 65 | devDepsList = []; 66 | 67 | Object.keys(deps).forEach(function (key) { 68 | pkg = { 69 | name: deps[key].name, 70 | description: deps[key].description, 71 | version: deps[key].version, 72 | homepage: deps[key].homepage || defaultString, 73 | author: deps[key].author, 74 | bugs: deps[key].bugs || defaultString, 75 | repository: deps[key].repository, 76 | license: deps[key].license || defaultString, 77 | dependencies: deps[key].dependencies, 78 | dist: deps[key].dependencies.dist 79 | }; 80 | 81 | // convert git:// form url to github URL 82 | if (pkg.repository && pkg.repository.url) { 83 | pkg.repository.url = gitURL(pkg.repository.url, null); 84 | } 85 | 86 | if (devDeps && !devDeps[pkg.name]) { 87 | pkg.deps = true; 88 | depsList.push(pkg); 89 | } else { 90 | pkg.dev = true; 91 | devDepsList.push(pkg); 92 | } 93 | }); 94 | 95 | depsList = this.compare(depsList); 96 | devDepsList = this.compare(devDepsList); 97 | 98 | // add this package info if exists 99 | readJSON(path.join(process.cwd(), 'package.json'), console.error, false, function (err, pkg) { 100 | if (!err) { 101 | selfInfo = { 102 | name: pkg.name, 103 | description: pkg.description, 104 | version: pkg.version, 105 | homepage: pkg.homepage || defaultString, 106 | author: pkg.author, 107 | bugs: pkg.bugs || defaultString, 108 | repository: pkg.repository || defaultString, 109 | license: pkg.license || defaultString, 110 | selfPkg: true 111 | }; 112 | depsList.unshift(selfInfo); 113 | } 114 | resp = { pkgs: depsList.concat(devDepsList) }; 115 | cb(err, resp); 116 | }.bind(this)); 117 | }.bind(this)); 118 | }; 119 | 120 | /** 121 | * compare the objects 122 | * 123 | * @method compare 124 | * @param {Boolean} Boolean 125 | */ 126 | NodeInfo.prototype.compare = function (obj) { 127 | obj.sort(function (a, b) { 128 | if (a.name > b.name) { 129 | return 1; 130 | } 131 | if (a.name < b.name) { 132 | return -1; 133 | } 134 | 135 | // a must be equal to b 136 | return 0; 137 | }); 138 | 139 | return obj; 140 | }; 141 | 142 | /** 143 | * get the system info 144 | * 145 | * @method getSystemInfo 146 | * @param {Function} cb callback 147 | */ 148 | NodeInfo.prototype.getSystemInfo = function (cb) { 149 | var sys = [], 150 | info, 151 | proc = process, 152 | os = require('os'), 153 | cpu, 154 | memv8, 155 | MB = 1024 * 1000, 156 | GB = MB * 1000, 157 | defaultString = '-'; 158 | 159 | // filter out the required process info 160 | info = { 161 | version: proc.version.replace(/^[v|V]/, ""), 162 | path: proc.env.NODE_PATH || defaultString, 163 | user: proc.env.USER || defaultString, 164 | lang: proc.env.LANG || defaultString, 165 | platform: proc.platform || defaultString, 166 | uptime: tt.calc(Date.now() - (proc.uptime() * 1000)), 167 | arch: proc.arch || defaultString, 168 | pid: proc.pid || defaultString, 169 | memv8: proc.memoryUsage() 170 | }; 171 | 172 | memv8 = { 173 | rss: Math.round(info.memv8.rss/MB), 174 | heapUsed: Math.round(info.memv8.heapUsed/MB), 175 | heapTotal: Math.round(info.memv8.heapTotal/MB) 176 | }; 177 | info.memv8 = memv8; 178 | 179 | sys.push({ proc: info }); 180 | 181 | // filter out the required OS info 182 | cpu = os.cpus(); 183 | info = { 184 | totalmem: Math.round(os.totalmem()/GB), 185 | freemem: Math.round(os.freemem()/GB), 186 | core: cpu.length, 187 | model: cpu[0].model, 188 | speed: cpu[0].speed, 189 | hostname: os.hostname() 190 | }; 191 | sys.push({ os: info }); 192 | 193 | // return the response 194 | cb(null, { sys: sys }); 195 | }; 196 | 197 | // export the NodeInfo module 198 | module.exports = function (req) { 199 | return new NodeInfo(req); 200 | }; 201 | -------------------------------------------------------------------------------- /lib/tpl/nodeinfo.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Node environment information 5 | 6 | 166 | 167 | 168 |
169 | Node environment information 170 |
171 |
172 | <% sys.forEach(function(sys) { %> 173 | <% if (sys.proc) { %> 174 | 183 | <% } %> 184 | <% if (sys.os) { %> 185 | 193 | <% } %> 194 | <% }) %> 195 |
196 |
197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | <% 208 | var orderIndex = 0; 209 | var isDevDepsStarted = false; 210 | var isDepsStarted = false; 211 | var uniqueId = 0; 212 | %> 213 | <% pkgs.forEach(function(pkg) { %> 214 | 215 | <% if (isDefined(pkg.deps) && !isDepsStarted) { %> 216 | 217 | <% 218 | orderIndex = 0; 219 | isDepsStarted = true; 220 | %> 221 | <% } %> 222 | 223 | <% if (isDefined(pkg.dev) && !isDevDepsStarted) { %> 224 | 225 | <% 226 | orderIndex = 0; 227 | isDevDepsStarted = true; 228 | %> 229 | <% } %> 230 | class="self-pkg" <% } %>> 231 | 236 | 237 | 238 | 286 | 287 | <% }) %> 288 | 289 |
#NameVersionDescription
Dependency packages detail
Dev dependency packages detail
232 | <% if (!isDefined(pkg.selfPkg)) { %> 233 | <%=++orderIndex%> 234 | <% } %> 235 | <%=pkg.name%><%=pkg.version%> 239 | 240 | <%= pkg.description %> 241 | 242 | 243 | 244 | 245 |
246 |
Home page:
247 |
Author:
248 | <% if (isDefined(pkg.author)) { %> 249 |
250 | <% if (isDefined(pkg.author.url)) { %> 251 | <%= pkg.author.name %> 252 | <% } else if (isDefined(pkg.author)){ %> 253 | <%= pkg.author.name %> 254 | <% } %> 255 |
256 | <% if (isDefined(pkg.author.email)) { %> 257 |
Author email:
258 | <% } %> 259 | <% } %> 260 | <% if (isDefined(pkg.repository) && isDefined(pkg.repository.url)) { %> 261 |
Repository:
262 | <% } %> 263 | <% if (isDefined(pkg.license)) { %> 264 |
License:
<%= pkg.license %>
265 | <% } %> 266 | <% if (isDefined(pkg.bugs.url)) { %> 267 |
Bugs:
268 | <% } %> 269 | 270 | <% if (isDefined(pkg.dependencies)) { %> 271 |
Dependencies:
272 |
273 | <% if (isObject(pkg.dependencies)) { %> 274 | <% var dIndex = 1; %> 275 | <% for (i in pkg.dependencies) { %> 276 | <%= pkg.dependencies[i].name %><% if (Object.keys(pkg.dependencies).length !== dIndex) { %>,<% } %> 277 | <% dIndex++; %> 278 | <% } %> 279 | <% } else { %> 280 | - 281 | <% } %> 282 | <% } %> 283 |
284 |
285 |
290 |
291 | 292 | 293 | 294 | --------------------------------------------------------------------------------