From 890ce0145f0a95f25794778ca87cb4f4f27db1c6 Mon Sep 17 00:00:00 2001 From: David Wick Date: Mon, 12 Jan 2015 14:58:26 -0800 Subject: [PATCH] Add linters and fix style errors --- .jscsrc | 111 +++++++++++++++++++++++++++++++++++++++++++++ .jshintrc | 51 +++++++++++++++++++++ example/config.js | 18 ++++---- example/index.js | 5 +- package.json | 1 + src/data/log.js | 10 ++-- src/data/statsd.js | 32 ++++++------- src/metron.js | 45 +++++++++++------- src/parameter.js | 53 +++++++++++----------- src/utils.js | 9 ++-- test/.jshintrc | 62 +++++++++++++++++++++++++ test/log.js | 17 ++++--- test/metron.js | 37 ++++++++------- test/parameter.js | 10 ++-- test/statsd.js | 23 +++++----- 15 files changed, 360 insertions(+), 124 deletions(-) create mode 100644 .jscsrc create mode 100644 .jshintrc create mode 100644 test/.jshintrc diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 0000000..7ab5d91 --- /dev/null +++ b/.jscsrc @@ -0,0 +1,111 @@ +{ + "disallowQuotedKeysInObjects": true, + "validateQuoteMarks": "'", + "disallowSpacesInFunctionExpression": { + "beforeOpeningRoundBrace": true + }, + "disallowSpacesInFunctionDeclaration": { + "beforeOpeningRoundBrace": true + }, + "requireSpacesInFunctionExpression": { + "beforeOpeningCurlyBrace": true + }, + "requireSpacesInFunctionDeclaration": { + "beforeOpeningCurlyBrace": true + }, + "requireParenthesesAroundIIFE": true, + "requireDotNotation": true, + "disallowMultipleVarDecl": true, + "requireCurlyBraces": [ + "if", + "else", + "for", + "while", + "do", + "try", + "catch" + ], + "disallowTrailingWhitespace": true, + "disallowMixedSpacesAndTabs": true, + "validateIndentation": 2, + "disallowSpaceAfterPrefixUnaryOperators": [ + "++", + "--", + "+", + "-", + "~", + "!" + ], + "disallowSpaceBeforePostfixUnaryOperators": [ + "++", + "--" + ], + "requireSpaceBeforeBinaryOperators": true, + "requireSpaceAfterBinaryOperators": true, + "disallowNewlineBeforeBlockStatements": true, + "validateLineBreaks": "LF", + "validateParameterSeparator": ", ", + "requireCommaBeforeLineBreak": true, + "requireTrailingComma": { + "ignoreSingleLine": true + }, + "requireCamelCaseOrUpperCaseIdentifiers": "ignoreProperties", + "requireCapitalizedConstructors": true, + "requireSpaceAfterKeywords": [ + "do", + "for", + "if", + "else", + "switch", + "case", + "try", + "catch", + "void", + "while", + "with", + "return", + "typeof" + ], + "requireSpaceBeforeBlockStatements": true, + "requireSpacesInConditionalExpression": { + "afterTest": true, + "beforeConsequent": true, + "afterConsequent": true, + "beforeAlternate": true + }, + "disallowSpacesInCallExpression": true, + "requireBlocksOnNewline": true, + "disallowEmptyBlocks": true, + "disallowSpacesInsideParentheses": true, + "requireSpacesInsideObjectBrackets": "all", + "disallowSpacesInsideArrayBrackets": "all", + "disallowSpaceAfterObjectKeys": true, + "requireSpaceBeforeObjectValues": true, + "requireOperatorBeforeLineBreak": [ + "?", + "=", + "+", + "-", + "/", + "*", + "==", + "===", + "!=", + "!==", + ">", + ">=", + "<", + "<=" + ], + "disallowKeywords": [ + "with" + ], + "disallowMultipleLineStrings": true, + "disallowMultipleLineBreaks": true, + "disallowKeywordsOnNewLine": [ + "else" + ], + "requireLineFeedAtFileEnd": true, + "disallowYodaConditions": true, + "requireSpaceAfterLineComment": true +} diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..ec82a12 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,51 @@ +{ + /* + * ENVIRONMENTS + * ================= + */ + + // Define globals exposed by Node.js. + "node": true, + + /* + * ENFORCING OPTIONS + * ================= + */ + + // Force all variable names to use either camelCase style or UPPER_CASE + // with underscores. + "camelcase": true, + + // Prohibit use of == and != in favor of === and !==. + "eqeqeq": true, + + // Suppress warnings about == null comparisons. + "eqnull": true, + + // Enforce tab width of 2 spaces. + "indent": 2, + + // Prohibit use of a variable before it is defined. + "latedef": true, + + // Require capitalized names for constructor functions. + "newcap": true, + + // Enforce use of single quotation marks for strings. + "quotmark": "single", + + // Prohibit trailing whitespace. + "trailing": true, + + // Prohibit use of explicitly undeclared variables. + "undef": true, + + // Warn when variables are defined but never used. + "unused": "var", + + // Enforce line length to 80 characters + "maxlen": 80, + + // Enforce placing 'use strict' at the top function scope + "strict": true +} diff --git a/example/config.js b/example/config.js index 3854504..2b4d718 100644 --- a/example/config.js +++ b/example/config.js @@ -1,18 +1,20 @@ +'use strict'; + var Statsd = require('metron').dataAdapters.Statsd; var statsd = new Statsd({ - host: process.env.statsd_host, - port: process.env.statsd_port, + host: process.env.STATDSD_HOST, + port: process.env.STATSD_PORT, }); var intConfig = { type: 'number', min: 0, - max: 100 + max: 100, }; var stringConfig = { type: 'string', - length: 256 + length: 256, }; var config = { @@ -30,9 +32,9 @@ var config = { domContentLoadedTiming: intConfig, actionName: stringConfig, verification: stringConfig, - } - } - } -} + }, + }, + }, +}; module.exports = config; diff --git a/example/index.js b/example/index.js index 3d28a50..26d196e 100644 --- a/example/index.js +++ b/example/index.js @@ -1,8 +1,7 @@ -var Metron = require('../src/metron'), - config = require ('./config.js'); +var Metron = require('../src/metron'); +var config = require('./config.js'); var server = new Metron(config); server.start(); console.log('Server started at http://localhost:' + server.get('port')); - diff --git a/package.json b/package.json index 9ff7ad2..2eaccd4 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "simple whitelisted statsd passthrough.", "main": "src/metron.js", "scripts": { + "lint": "jshint . && jscs .", "test": "./node_modules/mocha/bin/mocha" }, "repository": { diff --git a/src/data/log.js b/src/data/log.js index 2a9ede1..6dc68fe 100644 --- a/src/data/log.js +++ b/src/data/log.js @@ -1,4 +1,5 @@ -/* jshint strict:false */ +'use strict'; + var crypto = require('crypto'); var utils = require('../utils'); @@ -25,14 +26,14 @@ Log.prototype.format = function(segment, config, req) { var format = config.log.format || this.config.format; return format(segment, req); -} +}; Log.prototype.save = function(logString, config) { config.log = config.log || {}; var save = config.log.save || this.config.save; return save(logString, config); -} +}; Log.prototype.send = function(segment, config, req) { config.log = config.log || {}; @@ -44,7 +45,6 @@ Log.prototype.send = function(segment, config, req) { var logString = this.format(segment, config, req); this.save(logString, config); -} +}; module.exports = Log; - diff --git a/src/data/statsd.js b/src/data/statsd.js index 7be8380..3e55419 100644 --- a/src/data/statsd.js +++ b/src/data/statsd.js @@ -1,8 +1,8 @@ -/* jshint strict:false */ +'use strict'; var dgram = require('dgram'); var dns = require('dns'); -var utils = require('../utils') +var utils = require('../utils'); var defaultStatsdConfig = { host: 'localhost', @@ -10,7 +10,7 @@ var defaultStatsdConfig = { socketTimeout: 500, prefix: '', preCacheDNS: true, - bufferTimeout: 500 + bufferTimeout: 500, }; function Statsd(config) { @@ -35,7 +35,7 @@ function Statsd(config) { Statsd.prototype.stop = function() { this.socket.close(); -} +}; Statsd.prototype.send = function(segment, config, req) { config.statsd = config.statsd || {}; @@ -57,18 +57,18 @@ Statsd.prototype.send = function(segment, config, req) { message = Statsd[config.statsd.eventType](name, value); if (config.statsd.sampleRate) { - message += '|@' + config.statsd.sampleRate + message += '|@' + config.statsd.sampleRate; } if (config.statsd.tags) { - message += '|#' + config.statsd.tags.join(',') + message += '|#' + config.statsd.tags.join(','); } this.buffer.push(message); }).bind(this)); this.flushBuffer(); -} +}; Statsd.prototype.flushBuffer = function() { if (!this.config.bufferTimeout) { @@ -92,13 +92,13 @@ Statsd.prototype.flushBuffer = function() { this.config.bufferTimeout); } } -} +}; Statsd.prototype.flushToSocket = function() { var buffer = new Buffer(this.buffer.join('\n')); this.buffer = []; - if(buffer.length === 0) { + if (buffer.length === 0) { return; } @@ -117,30 +117,30 @@ Statsd.prototype.flushToSocket = function() { this.log(buffer.length); this.log(this.config.host + ':' + this.config.port); } -} +}; Statsd.counter = function(name, value) { return name + ':' + value + '|c'; -} +}; Statsd.increment = function(name, value) { return Statsd.counter(name, value || 1); -} +}; Statsd.decrement = function(name, value) { return Statsd.counter(name, -value || -1); -} +}; Statsd.gauge = function(name, value) { return name + ':' + value + '|g'; -} +}; Statsd.timing = function(name, value) { return name + ':' + value + '|ms'; -} +}; Statsd.set = function(name, value) { return name + ':' + value + '|s'; -} +}; module.exports = Statsd; diff --git a/src/metron.js b/src/metron.js index 136b2e0..0d88a65 100644 --- a/src/metron.js +++ b/src/metron.js @@ -32,11 +32,11 @@ Metron.prototype.start = function() { this.server = server; server.listen(this.config.port); -} +}; Metron.prototype.stop = function() { this.server.close(); -} +}; Metron.prototype.processRequest = function(req, res) { var params = {}; @@ -50,26 +50,26 @@ Metron.prototype.processRequest = function(req, res) { try { req.params = JSON.parse(parsedUrl.query.data); this.processParameters(req, res); - } catch(e) { + } catch (e) { return this.endRequest(req, res, 400, e); } } else { var body = []; - req.on('data', function (data) { + req.on('data', function(data) { body.push(data.toString()); }); - req.on('end', (function () { + req.on('end', (function() { body = body.join(''); - var isJSON = req.headers['content-type'] && + var isJSON = req.headers['content-type'] && req.headers['content-type'].toLowerCase().indexOf('json') > -1; if (isJSON) { try { req.params = JSON.parse(body); - } catch(e) { + } catch (e) { return this.endRequest(req, res, 400, e); } } else { @@ -79,13 +79,13 @@ Metron.prototype.processRequest = function(req, res) { this.processParameters(req, res); }).bind(this)); } -} +}; Metron.prototype.endRequest = function(req, res, statusCode, error) { statusCode = statusCode || 204; if (error && !statusCode) { - error = error.message ? error.message : error + error = error.message ? error.message : error; statusCode = 500; } @@ -98,7 +98,19 @@ Metron.prototype.endRequest = function(req, res, statusCode, error) { req.ended = true; res.setHeader('Access-Control-Allow-Origin', '*'); - res.setHeader('Access-Control-Allow-Headers', 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since'); + res.setHeader('Access-Control-Allow-Headers', [ + 'Authorization', + 'Content-Type', + 'Accept', + 'Origin', + 'User-Agent', + 'DNT', + 'Cache-Control', + 'X-Mx-ReqToken', + 'Keep-Alive', + 'X-Requested-With', + 'If-Modified-Since', + ].join(',')); res.writeHead(statusCode); @@ -113,7 +125,7 @@ Metron.prototype.processParameters = function(req, res) { var params = req.params; this.middleware.forEach((function(m) { - if(m.predicate && !m.predicate(req)) { + if (m.predicate && !m.predicate(req)) { return; } @@ -144,17 +156,18 @@ Metron.prototype.processParameters = function(req, res) { continue; } - stat = new Parameter(statName, statValue, statConfig, req); + var stat = new Parameter(statName, statValue, statConfig, req); if (stat.val !== undefined) { formattedSegment.push(stat); } } - if(formattedSegment) { + if (formattedSegment) { var store = segmentConfig.dataStore || [console.log]; + /* jshint loopfunc: true */ store.forEach(function(s) { s(formattedSegment, segmentConfig, req); }); @@ -162,12 +175,12 @@ Metron.prototype.processParameters = function(req, res) { } this.endRequest(req, res); -} +}; Metron.dataAdapters = { Statsd: require('./data/statsd'), - Log: require('./data/log') -} + Log: require('./data/log'), +}; Metron.utils = utils; diff --git a/src/parameter.js b/src/parameter.js index 19c8174..917d7bc 100644 --- a/src/parameter.js +++ b/src/parameter.js @@ -1,31 +1,32 @@ -/* jshint strict:false */ +'use strict'; var conversion = { - 'integer': function(val) { - val = parseInt(val); - if (isNaN(val)) { - return; - } + integer: function(val) { + val = parseInt(val); - return val; + if (isNaN(val)) { + return; + } + + return val; }, - 'float': function(val) { - val = parseFloat(val); + float: function(val) { + val = parseFloat(val); - if (isNaN(val)) { - return; - } + if (isNaN(val)) { + return; + } - return val; + return val; }, - 'string': function(val) { + string: function(val) { return val.toString(); }, - 'date': function(val) { + date: function(val) { var date = new Date(val); if (isNaN(date.getTime())) { @@ -37,11 +38,12 @@ var conversion = { } return date; - } -} + }, + +}; function Parameter(name, val, config, req) { - if(val === undefined || name === undefined){ + if (val === undefined || name === undefined) { return undefined; } @@ -58,11 +60,11 @@ Parameter.prototype.convert = function() { if (this.config.type) { try { this.val = conversion[this.config.type](this.val); - } catch(e) { + } catch (e) { this.val = undefined; } } -} +}; Parameter.prototype.validate = function() { var val = this.val; @@ -79,7 +81,7 @@ Parameter.prototype.validate = function() { if (config.validate) { this.val = config.validate(val); } -} +}; Parameter.prototype.format = function(req) { var config = this.config; @@ -89,21 +91,20 @@ Parameter.prototype.format = function(req) { } if (config.truncate) { - this.val = this.val.substring(0, config.truncate) + this.val = this.val.substring(0, config.truncate); } if (config.format) { this.val = config.format(this.val, config); } - if(this.config.formatName) { + if (this.config.formatName) { this.name = this.config.formatName(this.name, this.val, this.config, req); } - if(this.config.formatValue) { + if (this.config.formatValue) { this.val = this.config.formatValue(this.val); } -} +}; module.exports = Parameter; - diff --git a/src/utils.js b/src/utils.js index 6f4717b..28657d3 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,12 +1,13 @@ +'use strict'; + var utils = {}; -utils.merge = function(){ +utils.merge = function() { var obj = {}; - var args = Array.prototype.slice.call(arguments); args.forEach(function(arg) { - for (key in arg) { + for (var key in arg) { if (arg.hasOwnProperty(key)) { obj[key] = arg[key]; } @@ -14,6 +15,6 @@ utils.merge = function(){ }); return obj; -} +}; module.exports = utils; diff --git a/test/.jshintrc b/test/.jshintrc new file mode 100644 index 0000000..461b207 --- /dev/null +++ b/test/.jshintrc @@ -0,0 +1,62 @@ +{ + /* + * ENVIRONMENTS + * ================= + */ + + // Define globals exposed by Node.js. + "node": true, + + "globals": { + "describe": true, + "it": true, + "beforeEach": true, + "afterEach": true, + "before": true, + "after": true + }, + + /* + * ENFORCING OPTIONS + * ================= + */ + + // Force all variable names to use either camelCase style or UPPER_CASE + // with underscores. + "camelcase": true, + + // Prohibit use of == and != in favor of === and !==. + "eqeqeq": true, + + // Suppress warnings about == null comparisons. + "eqnull": true, + + // Supress warnings about expressions, mocha getters frequently use this. + "expr": true, + + // Enforce tab width of 2 spaces. + "indent": 2, + + // Prohibit use of a variable before it is defined. + "latedef": true, + + // Require capitalized names for constructor functions. + "newcap": true, + + // Enforce use of single quotation marks for strings. + "quotmark": "single", + + // Prohibit trailing whitespace. + "trailing": true, + + // Prohibit use of explicitly undeclared variables. + "undef": true, + + // Warn when variables are defined but never used. + "unused": "var", + + "maxlen": false, + + // Enforce placing 'use strict' at the top function scope + "strict": true +} diff --git a/test/log.js b/test/log.js index 703d51b..a0bcaee 100644 --- a/test/log.js +++ b/test/log.js @@ -1,5 +1,4 @@ -/* jshint strict:false */ -/* global describe,it,beforeEach */ +'use strict'; var Log = require('../src/data/log'); var sinon = require('sinon'); @@ -22,18 +21,18 @@ describe('Log adapter', function() { headers: { host: '127.0.0.1', 'user-agent': 'curl/7.22.0', - 'accept': '*/*' - } + accept: '*/*', + }, }; beforeEach(function() { log = new Log({ - log: sinon.spy() + log: sinon.spy(), }); eventConfig = { log: { - } + }, }; }); @@ -49,7 +48,7 @@ describe('Log adapter', function() { }); it('applies sampling', function() { - eventConfig.log.sampleRate = 0 + eventConfig.log.sampleRate = 0; log.send('test', 1, eventConfig, req); expect(log.config.log.args.length).to.equal(0); }); @@ -59,10 +58,10 @@ describe('Log adapter', function() { shasum.update(req.headers.host + req.headers['user-agent']); var id = shasum.digest('hex'); - eventConfig.log.format = sinon.spy() + eventConfig.log.format = sinon.spy(); log.send('test', 1, eventConfig, req); expect(eventConfig.log.format).to.be.calledWith( 'test', 1, eventConfig, id); }); -}) +}); diff --git a/test/metron.js b/test/metron.js index ad5d0d9..97a7104 100644 --- a/test/metron.js +++ b/test/metron.js @@ -1,5 +1,4 @@ -/* jshint strict:false */ -/* global describe,it,beforeEach,afterEach */ +'use strict'; var Metron = require('../src/metron'); var sinon = require('sinon'); @@ -15,21 +14,21 @@ var qs = require('querystring'); describe('Metron', function() { var config = { - port: 80 - } + port: 80, + }; it('initializes with config', function() { - var metron = new Metron(config) + var metron = new Metron(config); expect(metron.get('port')).to.equal(80); }); it('can get config values', function() { - var metron = new Metron(config) + var metron = new Metron(config); expect(metron.get('port')).to.equal(metron.config.port); }); it('can set config values', function() { - var metron = new Metron(config) + var metron = new Metron(config); metron.set({ port: 8080 }); expect(metron.get('port')).to.equal(8080); @@ -39,7 +38,7 @@ describe('Metron', function() { describe('Metron server', function() { var config = { port: 8080, - debug: true + debug: true, }; var metron; @@ -77,11 +76,11 @@ describe('Metron server', function() { stats: { totalLoadTime: { type: 'integer', - dataStore: [ sinon.spy() ] - } - } - } - } + dataStore: [sinon.spy()], + }, + }, + }, + }, }; metron.set(metronConfig); @@ -99,6 +98,7 @@ describe('Metron server', function() { }); }); + /* jshint maxlen: false */ it('logs data specified in the Metron config to multiple stores', function(done) { var metronConfig = { segments: { @@ -106,11 +106,11 @@ describe('Metron server', function() { stats: { totalLoadTime: { type: 'integer', - dataStore: [sinon.spy(), sinon.spy()] - } - } - } - } + dataStore: [sinon.spy(), sinon.spy()], + }, + }, + }, + }, }; metron.set(metronConfig); @@ -132,4 +132,3 @@ describe('Metron server', function() { }); }); - diff --git a/test/parameter.js b/test/parameter.js index c810583..36738de 100644 --- a/test/parameter.js +++ b/test/parameter.js @@ -1,5 +1,4 @@ -/* jshint strict:false */ -/* global describe,it,beforeEach */ +'use strict'; var Parameter = require('../src/parameter'); var sinon = require('sinon'); @@ -72,7 +71,7 @@ describe('Parameter', function() { if (val === 'A') { return val; } - } + }; var param = new Parameter('A', config); expect(param.value()).to.equal('A'); @@ -83,8 +82,8 @@ describe('Parameter', function() { it('formats results', function() { config.format = function(val) { - return val.replace(/-/,'.'); - } + return val.replace(/-/, '.'); + }; var param = new Parameter('A-B', config); expect(param.value()).to.equal('A.B'); @@ -130,4 +129,3 @@ describe('Parameter', function() { expect(param.value()).to.equal('AB'); }); }); - diff --git a/test/statsd.js b/test/statsd.js index 71cabd7..bd18c89 100644 --- a/test/statsd.js +++ b/test/statsd.js @@ -1,5 +1,4 @@ -/* jshint strict:false */ -/* global describe,it,beforeEach */ +'use strict'; var Statsd = require('../src/data/statsd'); var sinon = require('sinon'); @@ -10,14 +9,14 @@ var sinonChai = require('sinon-chai'); chai.use(sinonChai); require('sinon-mocha').enhance(sinon); -function socketStub(config) { - for(var key in config) { +var SocketStub = function(config) { + for (var key in config) { this[key] = config[key]; } this.close = sinon.spy(); this.send = sinon.spy(); -} +}; describe('Statsd adapter', function() { var statsd; @@ -27,15 +26,15 @@ describe('Statsd adapter', function() { beforeEach(function() { statsd = new Statsd({ prefix: 'pre', - socket: new socketStub(), + socket: new SocketStub(), preCacheDNS: false, - bufferTimeout: 0 + bufferTimeout: 0, }); eventConfig = { statsd: { eventType: 'increment', - } + }, }; spy = statsd.socket.send; @@ -109,7 +108,7 @@ describe('Statsd adapter', function() { }); it('applies sampling', function() { - eventConfig.statsd.sampleRate = 1.00 + eventConfig.statsd.sampleRate = 1.00; statsd.send('test', 1, eventConfig); var expectedMessage = 'pre.test:1|c|@1'; var buffer = spy.args[0][0]; @@ -127,9 +126,9 @@ describe('Statsd adapter', function() { it('works with buffering', function(done) { statsd = new Statsd({ prefix: 'pre', - socket: new socketStub(), + socket: new SocketStub(), preCacheDNS: false, - bufferTimeout: 100 + bufferTimeout: 100, }); spy = statsd.socket.send; @@ -146,4 +145,4 @@ describe('Statsd adapter', function() { done(); }, 150); }); -}) +});