diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 0000000..ebad867 --- /dev/null +++ b/.jscsrc @@ -0,0 +1,114 @@ +{ + "disallowKeywords": [ + "with" + ], + "disallowKeywordsOnNewLine": [ + "else" + ], + "disallowMixedSpacesAndTabs": true, + "disallowMultipleVarDecl": { + "allExcept": [ + "undefined", + "required" + ] + }, + "disallowNewlineBeforeBlockStatements": true, + "disallowPaddingNewlinesInBlocks": { + "close": false, + "open": true + }, + "disallowQuotedKeysInObjects": { + "allExcept": [ + "reserved" + ] + }, + "disallowSpaceAfterObjectKeys": { + "allExcept": [ + "aligned" + ] + }, + "disallowSpaceAfterPrefixUnaryOperators": true, + "disallowSpaceBeforeComma": true, + "disallowSpaceBeforePostfixUnaryOperators": true, + "disallowSpaceBeforeSemicolon": true, + "disallowSpacesInAnonymousFunctionExpression": { + "beforeOpeningRoundBrace": true + }, + "disallowSpacesInCallExpression": true, + "disallowSpacesInFunctionDeclaration": { + "beforeOpeningRoundBrace": true + }, + "disallowSpacesInFunctionExpression": { + "beforeOpeningRoundBrace": true + }, + "disallowSpacesInsideArrayBrackets": "nested", + "disallowSpacesInsideBrackets": { + "allExcept": [ "[", "]", "{", "}" ] + }, + "disallowSpacesInsideParentheses": true, + "disallowTrailingComma": true, + "disallowTrailingWhitespace": true, + "disallowYodaConditions": true, + "requireBlocksOnNewline": 1, + "requireCapitalizedConstructors": true, + "requireCurlyBraces": { + "keywords": [ + "if", + "else", + "for", + "while", + "do", + "try", + "catch" + ], + "allExcept": [ + "return", + "continue", + "break" + ] + }, + "requireDotNotation": true, + "requireLineFeedAtFileEnd": true, + "requireOperatorBeforeLineBreak": true, + "requireParenthesesAroundIIFE": true, + "requireSemicolons": true, + "requireSpaceAfterBinaryOperators": true, + "requireSpaceAfterComma": true, + "requireSpaceAfterKeywords": [ + "if", + "else", + "for", + "while", + "do", + "switch", + "return", + "try", + "catch", + "typeof" + ], + "requireSpaceAfterLineComment": { + "allExcept": ["/"] + }, + "requireSpaceBeforeBinaryOperators": true, + "requireSpaceBeforeBlockStatements": true, + "requireSpaceBeforeKeywords": [ + "else", + "while", + "catch" + ], + "requireSpaceBeforeObjectValues": true, + "requireSpaceBetweenArguments": true, + "requireSpacesInConditionalExpression": true, + "requireSpacesInForStatement": true, + "requireSpacesInFunctionExpression": { + "beforeOpeningCurlyBrace": true + }, + "requireSpacesInsideObjectBrackets": { + "allExcept": [ "}", ")" ] + }, + "safeContextKeyword": [ + "self" + ], + "validateIndentation": 4, + "validateQuoteMarks": "'" +} diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..1a47423 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,17 @@ +{ + "esnext": true, + "node": true, + "browser": true, + "bitwise": true, + "eqeqeq": true, + "forin": true, + "latedef": true, + "noarg": true, + "nonew": true, + "undef": true, + "unused": true, + "latedef": "nofunc", + "predef": { + } +} + diff --git a/Gruntfile.js b/Gruntfile.js index 1c150bd..75991e3 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,14 +1,19 @@ var os = require('os'); +var grunt = require('grunt'); +var path = require('path'); var pkg = require('./package.json'); +require('load-grunt-tasks')(grunt); + module.exports = function(grunt) { - require('load-grunt-tasks')(grunt); + var files = ['./index.js', './Gruntfile.js', 'lib/**/*.js', 'test/**/*.js']; var buildOutputFile = os.platform() !== 'win32' ? 'logdna' : 'logdna.exe'; + grunt.initConfig({ lineremover: { nukebrowser: { files: { - 'node_modules/ws/package.json': 'node_modules/ws/package.json' + 'node_modules/ws/package.json': path.join('node_modules', 'ws', 'package.json') }, options: { exclusionPattern: /browser/ @@ -16,7 +21,7 @@ module.exports = function(grunt) { } }, exec: { - nexe: 'nexe -i index.js -o ' + buildOutputFile + ' -f -t ~/tmp -r 5.9.0', + nexe: { cmd: 'nexe -i index.js -o ' + buildOutputFile + ' -f -t ~/tmp -r 5.9.0', maxBuffer: 20000 * 1024 }, save_version: 'echo ' + pkg.version + ' > version', fpm_osxpkg: 'fpm -s dir -t osxpkg --osxpkg-identifier-prefix com.logdna -n logdna-cli -v ' + pkg.version + ' --post-install ./scripts/post-install -f ./logdna=/usr/local/logdna/bin/logdna', sign_pkg: 'productsign --sign "Developer ID Installer: Answerbook, Inc. (TT7664HMU3)" logdna-cli-' + pkg.version + '.pkg logdna-cli.pkg', @@ -51,10 +56,26 @@ module.exports = function(grunt) { dest: './.builds/windows/tools/' }] } + }, + jshint: { + files: files, + options: { + jshintrc: '.jshintrc' + } + }, + jscs: { + files: { + src: files + }, + options: { + config: '.jscsrc', + esnext: true, + verbose: true, + fix: true + } } }); - grunt.loadNpmTasks('grunt-line-remover'); - grunt.loadNpmTasks('grunt-exec'); + grunt.registerTask('test', ['jscs', 'jshint']); grunt.registerTask('build', ['lineremover', 'exec:nexe', 'exec:save_version']); grunt.registerTask('linux', ['build', 'exec:fpm_rpm', 'exec:fpm_deb', 'exec:cp_rpm', 'exec:cp_deb', 'exec:gzip_linuxbin', 'exec:upload_linuxbin', 'exec:upload_linuxver', 'exec:upload_rpm', 'exec:upload_deb']); grunt.registerTask('mac', ['build', 'exec:fpm_osxpkg', 'exec:sign_pkg', 'exec:rm_unsignedpkg', 'exec:gzip_macbin', 'exec:upload_macbin', 'exec:upload_macver', 'exec:upload_pkg']); // 'exec:verify_pkg', 'exec:install_pkg' diff --git a/index.js b/index.js index cc9a721..7a5f8b2 100644 --- a/index.js +++ b/index.js @@ -2,22 +2,24 @@ var program = require('commander'); var pkg = require('./package.json'); -var properties = require("properties"); -var _ = require("lodash"); +var properties = require('properties'); +var _ = require('lodash'); +/* jshint ignore:start */ var WebSocket = require('./lib/logdna-websocket'); +/* jshint ignore:end */ var got = require('got'); -var input = require("./lib/input"); -var semver = require("semver"); -var os = require("os"); -var qs = require("querystring"); -var crypto = require("crypto"); +var input = require('./lib/input'); +var semver = require('semver'); +var os = require('os'); +var qs = require('querystring'); +var crypto = require('crypto'); var spawn = require('child_process').spawn; -var UPDATE_CHECK_URL = "http://repo.logdna.com/PLATFORM/version"; -var UPDATE_UPDATE_URL = "http://repo.logdna.com/PLATFORM/logdna.gz"; +var UPDATE_CHECK_URL = 'http://repo.logdna.com/PLATFORM/version'; +var UPDATE_UPDATE_URL = 'http://repo.logdna.com/PLATFORM/logdna.gz'; var UPDATE_CHECK_INTERVAL = 86400000; // 1 day -var DEFAULT_CONF_FILE = "~/.logdna.conf".replace("~", process.env.HOME || process.env.USERPROFILE); -var LOGDNA_APIHOST = process.env.LDAPIHOST || "api.logdna.com"; +var DEFAULT_CONF_FILE = '~/.logdna.conf'.replace('~', process.env.HOME || process.env.USERPROFILE); +var LOGDNA_APIHOST = process.env.LDAPIHOST || 'api.logdna.com'; var LOGDNA_APISSL = isNaN(process.env.USESSL) ? true : +process.env.USESSL; var EMAIL_REGEX = /[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/; @@ -25,8 +27,8 @@ var EMAIL_REGEX = /[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~- process.title = 'logdna'; program._name = 'logdna'; program - .version(pkg.version, "-v, --version") - .usage("[options] [commands]\n\n This CLI duplicates useful functionality of the LogDNA web app.") + .version(pkg.version, '-v, --version') + .usage('[options] [commands]\n\n This CLI duplicates useful functionality of the LogDNA web app.') // .description('This CLI duplicates useful functionality of the LogDNA web app.') .on('--help', function() { log(' Examples:'); @@ -39,42 +41,41 @@ program log(); }); -var ua = program._name + "-cli/" + pkg.version; +var ua = program._name + '-cli/' + pkg.version; properties.parse(DEFAULT_CONF_FILE, { path: true }, function(error, config) { config = config || {}; performUpgrade(config, function() { - program.command('register [key]') .description('Register a new LogDNA account. [key] is optional and will autogenerate') .action(function(email, key) { email = email.toLowerCase(); if (!EMAIL_REGEX.test(email)) - return log("Invalid email address"); + return log('Invalid email address'); - input.required("First name: ", function(firstname) { - input.required("Last name: ", function(lastname) { - input.required("Company/Organization: ", function(company) { + input.required('First name: ', function(firstname) { + input.required('Last name: ', function(lastname) { + input.required('Company/Organization: ', function(company) { input.done(); key = (key || '').toLowerCase(); - apiPost(config, "register", { auth: false, email: email, key: key, firstname: firstname, lastname: lastname, company: company }, function(body) { + apiPost(config, 'register', { auth: false, email: email, key: key, firstname: firstname, lastname: lastname, company: company }, function(body) { config.email = email; - if (config.account != body.account) { + if (config.account !== body.account) { config.account = body.account; config.token = null; } config.key = body.key; - if (body.token) config.token = body.token; // save token if available + if (body.token) { config.token = body.token; } // save token if available saveConfig(config, function() { - log("Thank you for signing up! Your API Key is: " + body.key + ". Saving credentials to local config."); + log('Thank you for signing up! Your API Key is: ' + body.key + '. Saving credentials to local config.'); log(); - log("Next steps:"); - log("==========="); - log("1) We've sent you a welcome email to create your password. Once set, come back here and use 'logdna login'"); - log("2) Type 'logdna install' for more info on collecting your logs via our agent, syslog, Heroku, API, etc."); + log('Next steps:'); + log('==========='); + log('1) We\'ve sent you a welcome email to create your password. Once set, come back here and use \'logdna login\''); + log('2) Type \'logdna install\' for more info on collecting your logs via our agent, syslog, Heroku, API, etc.'); log(); return; }); @@ -87,25 +88,25 @@ properties.parse(DEFAULT_CONF_FILE, { path: true }, function(error, config) { program.command('login') .description('Login to a LogDNA user account') .action(function() { - input.required("Email: ", function(email) { - input.hidden("Password: ", function(password) { + input.required('Email: ', function(email) { + input.hidden('Password: ', function(password) { input.done(); email = email.toLowerCase(); if (!EMAIL_REGEX.test(email)) - return log("Invalid email address"); + return log('Invalid email address'); - apiPost(config, "login", { auth: email + ':' + password }, function(body) { + apiPost(config, 'login', { auth: email + ':' + password }, function(body) { config.email = email; - if (body.accounts.length && config.account != body.accounts[0]) { + if (body.accounts.length && config.account !== body.accounts[0]) { config.account = body.accounts[0]; config.key = null; } - if (body.keys && body.keys.length) config.key = body.keys[0]; + if (body.keys && body.keys.length) { config.key = body.keys[0]; } config.token = body.token; saveConfig(config, function() { - log("Logged in successfully as: " + email + ". Saving credentials to local config."); + log('Logged in successfully as: ' + email + '. Saving credentials to local config.'); }); }); }); @@ -113,124 +114,136 @@ properties.parse(DEFAULT_CONF_FILE, { path: true }, function(error, config) { }); program.command('tail [query]') - .description("Live tail with optional filtering. See 'logdna tail --help'") - .option('-d, --debug', "Show debug level messages. Filtered by default") - .option('-h, --hosts ', "Filter on hosts (separate by comma)") - .option('-a, --apps ', "Filter on apps (separate by comma)") - .option('-l, --levels ', "Filter on levels (separate by comma)") + .description('Live tail with optional filtering. See \'logdna tail --help\'') + .option('-d, --debug', 'Show debug level messages. Filtered by default') + .option('-h, --hosts ', 'Filter on hosts (separate by comma)') + .option('-a, --apps ', 'Filter on apps (separate by comma)') + .option('-l, --levels ', 'Filter on levels (separate by comma)') .action(function(query, options) { var params = authParams(config); - params.q = query || ""; + params.q = query || ''; - if (!options.debug) - params.q += " level:-debug"; + if (!options.debug) { + params.q += ' level:-debug'; + } - if (options.hosts) - params.hosts = options.hosts.replace(/, /g, ","); + if (options.hosts) { + params.hosts = options.hosts.replace(/, /g, ','); + } - if (options.apps) - params.apps = options.apps.replace(/, /g, ","); + if (options.apps) { + params.apps = options.apps.replace(/, /g, ','); + } - if (options.levels) - params.levels = options.levels.replace(/, /g, ","); + if (options.levels) { + params.levels = options.levels.replace(/, /g, ','); + } params.q = params.q.trim(); - var ws = new WebSocket( (LOGDNA_APISSL ? "https://" : "http://") + LOGDNA_APIHOST + "/ws/tail?" + qs.stringify(params) ); + var ws = new WebSocket((LOGDNA_APISSL ? 'https://' : 'http://') + LOGDNA_APIHOST + '/ws/tail?' + qs.stringify(params)); var t; ws.on('open', function open() { - log("tail started. hosts: " + (options.hosts || "all") + ". apps: " + (options.apps || "all") + ". levels: " + (options.levels || (options.debug ? "all" : "-debug")) + ". query: " + (query || "none")); + log('tail started. hosts: ' + (options.hosts || 'all') + '. apps: ' + (options.apps || 'all') + '. levels: ' + (options.levels || (options.debug ? 'all' : '-debug')) + '. query: ' + (query || 'none')); }); ws.on('reconnecting', function(num) { - log("tail reconnect attmpt #" + num + "..."); + log('tail reconnect attmpt #' + num + '...'); }); ws.on('message', function(data) { - if (data.substring(0, 1) == "{") + if (data.substring(0, 1) === '{') { data = JSON.parse(data); + } else { + log('Malformed line: ' + data); + return; + } t = new Date(data.p._ts); - log(t.toString().substring(4,11) + t.toString().substring(16,24) + " " + data.p._host + " " + data.p._app + " " + (data.p.level ? "[" + data.p.level + "] " : "") + data.p._line); + log(t.toString().substring(4, 11) + t.toString().substring(16, 24) + ' ' + data.p._host + ' ' + data.p._app + ' ' + (data.p.level ? '[' + data.p.level + '] ' : '') + data.p._line); }); - ws.on('error', function (err) { + ws.on('error', function(err) { err = err.toString(); if (err.indexOf('401') > -1) { // invalid token - log("Access token invalid. If you created or changed your password recently, please 'logdna login' again. Type 'logdna --help' for more info."); + log('Access token invalid. If you created or changed your password recently, please \'logdna login\' again. Type \'logdna --help\' for more info.'); return process.exit(); } - log("Error: " + err); + log('Error: ' + err); }); - ws.on('close', function () { + ws.on('close', function() { log('tail lost connection'); }); }); program.command('search [query]') - .description("Limited search functionality with optional filtering. See 'logdna search --help'") - .option('-d, --debug', "Show debug level messages. Filtered by default") - .option('-h, --hosts ', "Filter on hosts (separate by comma)") - .option('-a, --apps ', "Filter on apps (separate by comma)") - .option('-l, --levels ', "Filter on levels (separate by comma)") + .description('Limited search functionality with optional filtering. See \'logdna search --help\'') + .option('-d, --debug', 'Show debug level messages. Filtered by default') + .option('-h, --hosts ', 'Filter on hosts (separate by comma)') + .option('-a, --apps ', 'Filter on apps (separate by comma)') + .option('-l, --levels ', 'Filter on levels (separate by comma)') .action(function(query, options) { var params = { - q: query || "" + q: query || '' }; - if (!options.debug) - params.q += " level:-debug"; + if (!options.debug) { + params.q += ' level:-debug'; + } - if (options.hosts) - params.hosts = options.hosts.replace(/, /g, ","); + if (options.hosts) { + params.hosts = options.hosts.replace(/, /g, ','); + } - if (options.apps) - params.apps = options.apps.replace(/, /g, ","); + if (options.apps) { + params.apps = options.apps.replace(/, /g, ','); + } - if (options.levels) - params.levels = options.levels.replace(/, /g, ","); + if (options.levels) { + params.levels = options.levels.replace(/, /g, ','); + } var t, t2, range; - apiGet(config, "search", params, function(body) { + apiGet(config, 'search', params, function(body) { if (body.range && body.range.from && body.range.to) { t = new Date(body.range.from); t2 = new Date(body.range.to); - range = " between " + t.toString().substring(4,11) + t.toString().substring(16,24) + "-" + t2.toString().substring(4,11) + t2.toString().substring(16,24); + range = ' between ' + t.toString().substring(4, 11) + t.toString().substring(16, 24) + '-' + t2.toString().substring(4, 11) + t2.toString().substring(16, 24); } - log("search finished: " + body.lines.length + " line(s)" + (range || "") + ". hosts: " + (options.hosts || "all") + ". apps: " + (options.apps || "all") + ". levels: " + (options.levels || (options.debug ? "all" : "-debug")) + ". query: " + (query || "none")); + log('search finished: ' + body.lines.length + ' line(s)' + (range || '') + '. hosts: ' + (options.hosts || 'all') + '. apps: ' + (options.apps || 'all') + '. levels: ' + (options.levels || (options.debug ? 'all' : '-debug')) + '. query: ' + (query || 'none')); _.each(body.lines, function(line) { t = new Date(line._ts); - log(t.toString().substring(4,11) + t.toString().substring(16,24) + " " + line._host + " " + line._app + " " + (line.level ? "[" + line.level + "] " : "") + line._line); + log(t.toString().substring(4, 11) + t.toString().substring(16, 24) + ' ' + line._host + ' ' + line._app + ' ' + (line.level ? '[' + line.level + '] ' : '') + line._line); }); }); }); program.command('heroku ') // .description("Generates a Heroku Drain URL for log shipping to LogDNA") - .description("Deprecated: Use 'logdna install heroku' instead") + .description('Deprecated: Use \'logdna install heroku\' instead') .action(function(app) { if (!config.token) - return log("Please login first. Type 'logdna login' or 'logdna --help' for more info."); + return log('Please login first. Type \'logdna login\' or \'logdna --help\' for more info.'); - log("Use the following Heroku CLI command to start log shipping:"); - log('heroku drains:add https://' + config.account + ':' + (config.key || "YOUR_API_KEY_HERE") + '@heroku.logdna.com/heroku/logplex?app=' + app + ' --app ' + app); + log('Use the following Heroku CLI command to start log shipping:'); + log('heroku drains:add https://' + config.account + ':' + (config.key || 'YOUR_API_KEY_HERE') + '@heroku.logdna.com/heroku/logplex?app=' + app + ' --app ' + app); log(); - log("Once shipping begins, you can tail using 'logdna tail -h " + app + "'"); + log('Once shipping begins, you can tail using \'logdna tail -h ' + app + '\''); }); program.command('install [os]') - .description("Instructions for collecting logs from staging/production hosts and systems") + .description('Instructions for collecting logs from staging/production hosts and systems') .action(function(os) { try { - log(require("./install")[os].replace(/ZZZZZZZZ/g, (config.key || "YOUR_API_KEY_HERE"))); + log(require('./install')[os].replace(/ZZZZZZZZ/g, (config.key || 'YOUR_API_KEY_HERE'))); } catch (e) { log('Try one of the following:'); log('logdna install deb # Debian/Ubuntu/Linux Mint'); @@ -246,18 +259,18 @@ properties.parse(DEFAULT_CONF_FILE, { path: true }, function(error, config) { }); program.command('info') - .description("Show current logged in user info") + .description('Show current logged in user info') .action(function() { - apiGet(config, "info", function(body) { + apiGet(config, 'info', function(body) { log(body); }); }); - program.command("update") - .description("Update CLI to latest version") + program.command('update') + .description('Update CLI to latest version') .action(function() { performUpgrade(config, true, function() { - log("No update available. You have the latest version: " + pkg.version); + log('No update available. You have the latest version: ' + pkg.version); }); }); @@ -267,21 +280,21 @@ properties.parse(DEFAULT_CONF_FILE, { path: true }, function(error, config) { }); function apiGet(config, endpoint, params, callback) { - apiCall(config, endpoint, "get", params, callback); + apiCall(config, endpoint, 'get', params, callback); } function apiPost(config, endpoint, params, callback) { - apiCall(config, endpoint, "post", params, callback); + apiCall(config, endpoint, 'post', params, callback); } function apiCall(config, endpoint, method, params, callback) { - if (typeof params == "function") { + if (typeof params === 'function') { callback = params; params = null; } var opts = { headers: { 'user-agent': ua }}; - if (params && params.auth != null) { + if (params && params.auth !== undefined) { if (params.auth) { opts.auth = params.auth; } delete params.auth; opts.query = params; @@ -292,34 +305,34 @@ function apiCall(config, endpoint, method, params, callback) { opts.query = params; } - if (method == 'post') { opts.method = 'post'; } + if (method === 'post') { opts.method = 'post'; } - got((LOGDNA_APISSL ? "https://" : "http://") + LOGDNA_APIHOST + "/" + endpoint, opts) + got((LOGDNA_APISSL ? 'https://' : 'http://') + LOGDNA_APIHOST + '/' + endpoint, opts) .then(res => { - if (res.body && res.body.substring(0, 1) == "{") { + if (res.body && res.body.substring(0, 1) === '{') { res.body = JSON.parse(res.body); } callback(res.body); }) .catch(err => { - if (err.statusCode == "403") { - return log("Access token invalid. If you created or changed your password recently, please 'logdna login' again. Type 'logdna --help' for more info."); + if (err.statusCode === '403') { + return log('Access token invalid. If you created or changed your password recently, please \'logdna login\' again. Type \'logdna --help\' for more info.'); } else { - return log("Error " + err.statusCode + ": " + err.response.body); + return log('Error ' + err.statusCode + ': ' + err.response.body); } }); } function authParams(config) { if (!config.token) { - log("Please login first. Type 'logdna login' or 'logdna --help' for more info."); + log('Please login first. Type \'logdna login\' or \'logdna --help\' for more info.'); return process.exit(); } var hmacParams = { - email: config.email - , id: config.account - , ts: Date.now() + email: config.email, + id: config.account, + ts: Date.now() }; hmacParams.hmac = generateHmac(hmacParams, config.token); @@ -327,24 +340,24 @@ function authParams(config) { } function performUpgrade(config, force, callback) { - if (typeof force == "function") { + if (typeof force === 'function') { callback = force; force = null; } if (force || Date.now() - (config.updatecheck || 0) > UPDATE_CHECK_INTERVAL) { - if (os.platform() == "darwin") { - UPDATE_CHECK_URL = UPDATE_CHECK_URL.replace("PLATFORM", "mac"); - UPDATE_UPDATE_URL = UPDATE_UPDATE_URL.replace("PLATFORM", "mac"); + if (os.platform() === 'darwin') { + UPDATE_CHECK_URL = UPDATE_CHECK_URL.replace('PLATFORM', 'mac'); + UPDATE_UPDATE_URL = UPDATE_UPDATE_URL.replace('PLATFORM', 'mac'); - } else if (os.platform() == "linux") { - UPDATE_CHECK_URL = UPDATE_CHECK_URL.replace("PLATFORM", "linux"); - UPDATE_UPDATE_URL = UPDATE_UPDATE_URL.replace("PLATFORM", "linux"); + } else if (os.platform() === 'linux') { + UPDATE_CHECK_URL = UPDATE_CHECK_URL.replace('PLATFORM', 'linux'); + UPDATE_UPDATE_URL = UPDATE_UPDATE_URL.replace('PLATFORM', 'linux'); } - if (force) log("Checking for updates..."); + if (force) { log('Checking for updates...'); } got(UPDATE_CHECK_URL, { timeout: (force ? 30000 : 2500) }) .then(res => { - if (res.body) { res.body = res.body.replace(/\r/g, "").replace(/\n/g, ""); } + if (res.body) { res.body = res.body.replace(/\r/g, '').replace(/\n/g, ''); } if (!semver.valid(res.body)) { // error during update check, set to check again in a day config.updatecheck = Date.now() - UPDATE_CHECK_INTERVAL + 86400000; @@ -357,13 +370,14 @@ function performUpgrade(config, force, callback) { if (semver.gt(res.body, pkg.version)) { // update needed - log("Performing upgrade from " + pkg.version + " to " + res.body + "..."); + log('Performing upgrade from ' + pkg.version + ' to ' + res.body + '...'); var shell = spawn('/bin/bash', ['-c', 'if [[ ! -z $(which curl) ]]; then curl -so /tmp/logdna.gz ' + UPDATE_UPDATE_URL + '; elif [[ ! -z $(which wget) ]]; then wget -qO /tmp/logdna.gz ' + UPDATE_UPDATE_URL + '; fi; gunzip -f /tmp/logdna.gz; cp -f /tmp/logdna /usr/local/logdna/bin/logdna; chmod 777 /usr/local/logdna/bin/logdna 2> /dev/null; echo -n "Successfully upgraded logdna-cli to "; /usr/local/bin/logdna -v' ], { stdio: 'inherit' }); - shell.on("close", function() { - if (!force && process.argv[process.argv.length-1].toLowerCase() != "update") - log("Please run your command again"); + shell.on('close', function() { + if (!force && process.argv[process.argv.length - 1].toLowerCase() !== 'update') { + log('Please run your command again'); + } }); return; @@ -371,6 +385,9 @@ function performUpgrade(config, force, callback) { // no update necessary, run rest of program return callback && callback(); } + }) + .catch(err => { + return log('Error ' + err.statusCode + ': ' + err.response.body); }); } else { @@ -383,18 +400,19 @@ function saveConfig(config, callback) { properties.stringify(config, { path: DEFAULT_CONF_FILE }, function(err) { - if (err) - console.error("Error while saving to: " + (DEFAULT_CONF_FILE) + ": " + err); - else + if (err) { + console.error('Error while saving to: ' + (DEFAULT_CONF_FILE) + ': ' + err); + } else { return callback && callback(); + } }); } function generateHmac(payload, secret) { var msg = qs.stringify(payload); - return crypto.createHmac("sha256", secret.toString()).update(msg).digest("hex"); + return crypto.createHmac('sha256', secret.toString()).update(msg).digest('hex'); } function log(msg) { - console.log(msg || ""); + console.log(msg || ''); } diff --git a/lib/input.js b/lib/input.js index 1ba1e88..d07055b 100644 --- a/lib/input.js +++ b/lib/input.js @@ -10,11 +10,12 @@ var init = function() { }; var required = exports.required = function(query, callback) { - if (!rl) init(); + if (!rl) { init(); } function ask() { rl.question(query, function(value) { - if (!value.trim()) + if (!value.trim()) { return ask(); + } callback(value); }); @@ -23,19 +24,20 @@ var required = exports.required = function(query, callback) { }; exports.hidden = function(query, callback) { - if (!rl) init(); + if (!rl) { init(); } var stdin = process.openStdin(); - process.stdin.on("data", function(char) { - char = char + ""; + process.stdin.on('data', function(char) { + char = char + ''; switch (char) { - case "\n": - case "\r": - case "\u0004": - if (rl.line.length > 0) + case '\n': + case '\r': + case '\u0004': + if (rl.line.length > 0) { stdin.pause(); + } break; default: - process.stdout.write("\033[2K\033[200D" + query + Array(rl.line.length+1).join("*")); + process.stdout.write('\033[2K\033[200D' + query + Array(rl.line.length + 1).join('*')); break; } }); diff --git a/lib/logdna-websocket.js b/lib/logdna-websocket.js index 89385c2..2df07a3 100644 --- a/lib/logdna-websocket.js +++ b/lib/logdna-websocket.js @@ -1,11 +1,13 @@ -var events = require("events"); -var util = require("util"); -var url = require("url"); -var WebSocket = require("ws"); +var events = require('events'); +var util = require('util'); +var url = require('url'); +/* jshint ignore:start */ +var WebSocket = require('ws'); +/* jshint ignore:end */ function LDWebSocket(address, protocols, options) { options = options || {}; - if (typeof protocols === "object") { + if (typeof protocols === 'object') { options = protocols; this.protocols = null; } else { @@ -13,7 +15,7 @@ function LDWebSocket(address, protocols, options) { } this.address = address; - this.reconnection = (typeof options.reconnection === "boolean" ? options.reconnection : true); + this.reconnection = (typeof options.reconnection === 'boolean' ? options.reconnection : true); this.reconnectionDelay = options.reconnectionDelay || 1000; this.reconnectionDelayMax = options.reconnectionDelayMax || 5000; this.connectTimeout = options.connectTimeout || 20000; @@ -38,12 +40,12 @@ LDWebSocket.prototype.open = function() { } this.ws = new WebSocket(uri, this.protocols, this.options); - this.ws.once("open", this.onopen.bind(this)); - this.ws.once("close", this.onclose.bind(this)); - this.ws.once("error", this.onerror.bind(this)); - this.ws.on("message", this.onmessage.bind(this)); - this.ws.on("ping", this.onping.bind(this)); - this.ws.on("pong", this.onpong.bind(this)); + this.ws.once('open', this.onopen.bind(this)); + this.ws.once('close', this.onclose.bind(this)); + this.ws.once('error', this.onerror.bind(this)); + this.ws.on('message', this.onmessage.bind(this)); + this.ws.on('ping', this.onping.bind(this)); + this.ws.on('pong', this.onpong.bind(this)); this.connectTimeoutHandler = setTimeout(function() { this.reconnect(); }.bind(this), this.connectTimeout); }; @@ -53,30 +55,30 @@ LDWebSocket.prototype.onopen = function() { this.connected = true; clearTimeout(this.connectTimeoutHandler); clearTimeout(this.reconnectTimeoutHandler); - this.emit("open"); + this.emit('open'); }; LDWebSocket.prototype.onclose = function(code, message) { this.connected = false; - this.emit("close", code, message); + this.emit('close', code, message); this.reconnect(); }; LDWebSocket.prototype.onerror = function(err) { - this.emit("error", err); + this.emit('error', err); this.reconnect(); }; LDWebSocket.prototype.onmessage = function(data, flags) { - this.emit("message", data, flags); + this.emit('message', data, flags); }; LDWebSocket.prototype.onping = function(data, flags) { - this.emit("ping", data, flags); + this.emit('ping', data, flags); }; LDWebSocket.prototype.onpong = function(data, flags) { - this.emit("pong", data, flags); + this.emit('pong', data, flags); }; LDWebSocket.prototype.reconnect = function() { @@ -97,23 +99,23 @@ LDWebSocket.prototype.reconnect = function() { this.connectAttempt++; this.reconnectTimeoutHandler = setTimeout(function() { - this.emit("reconnecting", this.connectAttempt); + this.emit('reconnecting', this.connectAttempt); this.open(); }.bind(this), timeout); }; [ -"send", -"stream", -"close", -"pause", -"resume", -"ping", -"pong", -"terminate", -"addEventListener" +'send', +'stream', +'close', +'pause', +'resume', +'ping', +'pong', +'terminate', +'addEventListener' ].forEach(function(method) { - if (method == "close") { + if (method === 'close') { this.reconnection = false; } @@ -123,13 +125,13 @@ LDWebSocket.prototype.reconnect = function() { }); [ -"bytesReceived", -"readyState", -"protocolVersion", -"supports", -"upgradeReq", -"url", -"_socket" +'bytesReceived', +'readyState', +'protocolVersion', +'supports', +'upgradeReq', +'url', +'_socket' ].forEach(function(getter) { LDWebSocket.prototype.__defineGetter__(getter, function() { return this.ws[getter]; diff --git a/package.json b/package.json index 39ba8da..2a2120b 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "devDependencies": { "grunt": "^0.4.5", "grunt-contrib-copy": "^1.0.0", + "grunt-contrib-jshint": "^0.11.3", "grunt-exec": "^0.4.6", + "grunt-jscs": "^2.5.0", "grunt-line-remover": "0.0.2", "load-grunt-tasks": "^3.4.1" },