diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..9099c1f --- /dev/null +++ b/.eslintrc @@ -0,0 +1,16 @@ +{ + "extends": "airbnb-base", + "rules": { + "no-console": 0, + "no-var": 0, + "comma-dangle": 0, + "prefer-template": 0, + "object-shorthand": 0, + "prefer-rest-params": 0, + "vars-on-top": 0, + "no-restricted-syntax": 0, + "prefer-arrow-callback": 0 + }, + "globals": { + } +} \ No newline at end of file diff --git a/README.md b/README.md index b756e11..dcaa4e7 100644 --- a/README.md +++ b/README.md @@ -56,10 +56,10 @@ Just include `logerr.js` file and the `init()` i.e initializer in the `` s > Make sure you have CORS enabled if logging cross-domain. ```javascript -//Request type is POST +// Request type is POST Logerr.init({ - remoteLogging: true, //Checkout https://github.com/i-break-codes/logerr-remote + remoteLogging: true, // Checkout https://github.com/i-break-codes/logerr-remote remoteSettings: { url: 'REMOTE_URL', additionalParams: { @@ -84,13 +84,13 @@ Also checkout Logerr Remote to log these exceptions remotely. (Powered by NodeJS #### Default Configuration & Datatypes ```javascript -detailedErrors: true //Boolean true/false, optional -remoteLogging: false //Boolean true/false, optional -remoteSettings: { //Object {}, required if remoteLogging is set to true - url: null, //String '', required if remoteLogging is set to true - additionalParams: null, //Object {}, optional - successCallback: null, //function() {}, optional - errorCallback: null //function() {}, optional +detailedErrors: true // Boolean true/false, optional +remoteLogging: false // Boolean true/false, optional +remoteSettings: { // Object {}, required if remoteLogging is set to true + url: null, // String '', required if remoteLogging is set to true + additionalParams: null, // Object {}, optional + successCallback: null, // function() {}, optional + errorCallback: null // function() {}, optional } ``` diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..f838f95 --- /dev/null +++ b/TODO.md @@ -0,0 +1,3 @@ +### TODOs +| Filename | line # | TODO +|:------|:------:|:------ \ No newline at end of file diff --git a/bower.json b/bower.json index d7d575a..9f011eb 100644 --- a/bower.json +++ b/bower.json @@ -22,6 +22,9 @@ "node_modules", "bower_components", "test", - "tests" + "tests", + "package.json", + "TODO.md", + "gulpfile.js" ] } diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..381546f --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,39 @@ +const gulp = require('gulp'); +const plumber = require('gulp-plumber'); +const notify = require('gulp-notify'); +const eslint = require('gulp-eslint'); +const watch = require('gulp-watch'); +const todo = require('gulp-todo'); +const uglify = require('gulp-uglify'); +const rename = require('gulp-rename'); + +const lint = (file) => + gulp.src(file) + .pipe(plumber()) + .pipe(eslint()) + .pipe(eslint.format()) + .pipe(eslint.failAfterError()) + .on('error', notify.onError('Error: <%= error.message %>')); + +gulp.task('lint', () => lint('logerr.js')); +gulp.task('lint-gulp', () => lint('gulpfile.js')); + +gulp.task('uglify', () => + gulp.src('logerr.js') + .pipe(plumber()) + .pipe(uglify()) + .pipe(rename({ suffix: '.min' })) + .pipe(gulp.dest('./')) + .on('error', notify.onError('Error: <%= error.message %>')) +); + +gulp.task('todo', () => + gulp.src('logerr.js') + .pipe(todo()) + .pipe(gulp.dest('./')) +); + +gulp.task('default', ['lint', 'lint-gulp', 'uglify', 'todo'], () => { + watch('gulpfile.js', () => gulp.run(['lint-gulp'])); + watch('logerr.js', () => gulp.run(['lint', 'uglify', 'todo'])); +}); diff --git a/logerr.js b/logerr.js index f1fd520..35da9f8 100644 --- a/logerr.js +++ b/logerr.js @@ -5,99 +5,94 @@ * @author Vaibhav Mehta * @copyright Copyright (c) 2016 Vaibhav Mehta * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 1.2 Stable + * @version 1.2.1 Stable */ -var Logerr = function() { - 'use strict'; - +window.Logerr = (function Logerr() { var setConfig; - function init(userConfig) { - if(!userConfig) userConfig = {}; + function errorData(e) { + var filename = e.filename.lastIndexOf('/'); + var datetime = new Date().toString(); - // Default configuration - var config = { - detailedErrors: true, - remoteLogging: false, - remoteSettings: { - url: null, - additionalParams: null, - successCallback: null, - errorCallback: null - } + /** + * userAgent only for POST request purposes, not required in pretty print + */ + return { + type: e.type, + path: e.filename, + filename: e.filename.substring(++filename), + line: e.lineno, + column: e.colno, + error: e.message, + stackTrace: ((e.error) ? e.error.stack.toString().replace(/(\r\n|\n|\r)/gm, '') : ''), + datetime: datetime, + userAgent: navigator.userAgent || window.navigator.userAgent }; - - // Override with user config - setConfig = Object.assign(config, userConfig); - - //Remove current listener - window.removeEventListener('error', _listener); - - // Listen to errors - window.addEventListener('error', _listener); - } - - // NOTE: Private - function _listener(e) { - if(setConfig.detailedErrors) { - _detailedErrors(e); - } - - if(setConfig.remoteLogging) { - _remoteLogging(e, setConfig.remoteSettings); - } } - function _detailedErrors(e) { - var i = _errorData(e); - var helpPath = encodeURI("https://stackoverflow.com/search?q=" + i.error.split(' ').join('+')); + function detailedErrors(e) { + var i = errorData(e); + var helpPath = encodeURI('https://stackoverflow.com/search?q=' + i.error.split(' ').join('+')); var str = [ - "%cType: %c" + i.type, - "%cError: %c" + i.error, - "%cStackTrace: %c" + i.stackTrace, - "%cFile Name: %c" + i.filename, - "%cPath: %c" + i.path, - "%cLine: %c" + i.line, - "%cColumn: %c" + i.column, - "%cDate: %c" + i.datetime, - "%cDebug : %c" + i.path + ':' + i.line, - "%cGet Help: " + "%c" + helpPath - ].join("\n"); - - if(window.chrome) { - console.log(str, "font-weight: bold;", "color: #e74c3c;", "font-weight: bold;", "font-weight: normal; color: #e74c3c;","font-weight: bold;", "font-weight: normal; color: #e74c3c;", "font-weight: bold;", "font-weight: normal;", "font-weight: bold;", "font-weight: normal;", "font-weight: bold;", "font-weight: normal;", "font-weight: bold;", "font-weight: normal;", "font-weight: bold;", "font-weight: normal;", "font-weight: bold;", "font-weight: normal;", "font-weight: bold;", "font-weight: normal; color: #3498db;"); + '%cType: %c' + i.type, + '%cError: %c' + i.error, + '%cStackTrace: %c' + i.stackTrace, + '%cFile Name: %c' + i.filename, + '%cPath: %c' + i.path, + '%cLine: %c' + i.line, + '%cColumn: %c' + i.column, + '%cDate: %c' + i.datetime, + '%cDebug : %c' + i.path + ':' + i.line, + '%cGet Help: %c' + helpPath + ].join('\n'); + + if (window.chrome) { + /* eslint-disable max-len */ + console.log(str, 'font-weight: bold;', 'color: #e74c3c;', 'font-weight: bold;', 'font-weight: normal; color: #e74c3c;', 'font-weight: bold;', 'font-weight: normal; color: #e74c3c;', 'font-weight: bold;', 'font-weight: normal;', 'font-weight: bold;', 'font-weight: normal;', 'font-weight: bold;', 'font-weight: normal;', 'font-weight: bold;', 'font-weight: normal;', 'font-weight: bold;', 'font-weight: normal;', 'font-weight: bold;', 'font-weight: normal;', 'font-weight: bold;', 'font-weight: normal; color: #3498db;'); + /* eslint-enable max-len */ } else { console.log(str.replace(/%c/gi, '')); } } - function _remoteLogging(e, remoteSettings) { - if(!remoteSettings.url) { + function serializeData(params) { + function encodeKey(k) { + return encodeURIComponent(k) + '=' + encodeURIComponent(params[k]); + } + + return Object.keys(params).map(encodeKey).join('&'); + } + + function remoteLogging(e, remoteSettings) { + if (!remoteSettings.url) { throw new Error('Provide remote URL to log errors remotely'); - } else if(remoteSettings.additionalParams && typeof remoteSettings.additionalParams !== 'object') { + } else if ( + remoteSettings.additionalParams && + typeof remoteSettings.additionalParams !== 'object' + ) { throw new Error('Invalid data type, additionalParams should be a valid object'); } var http = new XMLHttpRequest(); var url = remoteSettings.url; - var data = _errorData(e); + var data = errorData(e); var setData = Object.assign(data, remoteSettings.additionalParams); - var params = _serializeData(setData); + var params = serializeData(setData); - http.open("POST", url, true); - http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + http.open('POST', url, true); + http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); http.send(params); - http.onreadystatechange = function() { - if(http.readyState == 4 && http.status == 200) { - if (http.readyState == XMLHttpRequest.DONE) { - if(remoteSettings.successCallback) { + http.onreadystatechange = function onreadystatechange() { + if (http.readyState === 4 && http.status === 200) { + if (http.readyState === XMLHttpRequest.DONE) { + if (remoteSettings.successCallback) { remoteSettings.successCallback(); } } else { - if(remoteSettings.errorCallback) { + if (remoteSettings.errorCallback) { remoteSettings.errorCallback(); } else { throw new Error('Remote error logging failed!'); @@ -107,57 +102,62 @@ var Logerr = function() { }; } - function _serializeData(params) { - return Object.keys(params).map(function(k) { - return encodeURIComponent(k) + "=" + encodeURIComponent(params[k]); - }).join('&'); - } - - function _errorData(e) { - var filename = e.filename.lastIndexOf('/'); - var datetime = new Date().toString(); - - /** - * userAgent only for POST request purposes, not required in pretty print - */ + function listener(e) { + if (setConfig.detailedErrors) { + detailedErrors(e); + } - return { - type: e.type, - path: e.filename, - filename: e.filename.substring(++filename), - line: e.lineno, - column: e.colno, - error: e.message, - stackTrace: ((e.error) ? e.error.stack.toString().replace(/(\r\n|\n|\r)/gm,"") : ""), - datetime: datetime, - userAgent: navigator.userAgent || window.navigator.userAgent - }; + if (setConfig.remoteLogging) { + remoteLogging(e, setConfig.remoteSettings); + } } - //Polyfill for Object.assign - if (typeof Object.assign != 'function') { - Object.assign = function(target) { + // Polyfill for Object.assign + if (typeof Object.assign !== 'function') { + Object.assign = function assign(target) { if (target === null) { throw new TypeError('Cannot convert undefined or null to object'); } - target = Object(target); + var newTarget = Object(target); for (var index = 1; index < arguments.length; index++) { var source = arguments[index]; if (source !== null) { for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key]; + newTarget[key] = source[key]; } } } } - return target; + return newTarget; }; } + function init(userConfig) { + // Default configuration + var config = { + detailedErrors: true, + remoteLogging: false, + remoteSettings: { + url: null, + additionalParams: null, + successCallback: null, + errorCallback: null + } + }; + + // Override with user config + setConfig = Object.assign(config, userConfig || {}); + + // Remove current listener + window.removeEventListener('error', listener); + + // Listen to errors + window.addEventListener('error', listener); + } + return { init: init }; - -}(); \ No newline at end of file +}()); diff --git a/logerr.min.js b/logerr.min.js index 7b12770..7615c73 100644 --- a/logerr.min.js +++ b/logerr.min.js @@ -1 +1 @@ -var Logerr=function(){"use strict";function b(b){b||(b={});var d={detailedErrors:!0,remoteLogging:!1,remoteSettings:{url:null,additionalParams:null,successCallback:null,errorCallback:null}};a=Object.assign(d,b),window.removeEventListener("error",c),window.addEventListener("error",c)}function c(b){a.detailedErrors&&d(b),a.remoteLogging&&e(b,a.remoteSettings)}function d(a){var b=g(a),c=encodeURI("https://stackoverflow.com/search?q="+b.error.split(" ").join("+")),d=["%cType: %c"+b.type,"%cError: %c"+b.error,"%cStackTrace: %c"+b.stackTrace,"%cFile Name: %c"+b.filename,"%cPath: %c"+b.path,"%cLine: %c"+b.line,"%cColumn: %c"+b.column,"%cDate: %c"+b.datetime,"%cDebug : %c"+b.path+":"+b.line,"%cGet Help: %c"+c].join("\n");window.chrome?console.log(d,"font-weight: bold;","color: #e74c3c;","font-weight: bold;","font-weight: normal; color: #e74c3c;","font-weight: bold;","font-weight: normal; color: #e74c3c;","font-weight: bold;","font-weight: normal;","font-weight: bold;","font-weight: normal;","font-weight: bold;","font-weight: normal;","font-weight: bold;","font-weight: normal;","font-weight: bold;","font-weight: normal;","font-weight: bold;","font-weight: normal;","font-weight: bold;","font-weight: normal; color: #3498db;"):console.log(d.replace(/%c/gi,""))}function e(a,b){if(!b.url)throw new Error("Provide remote URL to log errors remotely");if(b.additionalParams&&"object"!=typeof b.additionalParams)throw new Error("Invalid data type, additionalParams should be a valid object");var c=new XMLHttpRequest,d=b.url,e=g(a),h=Object.assign(e,b.additionalParams),i=f(h);c.open("POST",d,!0),c.setRequestHeader("Content-type","application/x-www-form-urlencoded"),c.send(i),c.onreadystatechange=function(){if(4==c.readyState&&200==c.status)if(c.readyState==XMLHttpRequest.DONE)b.successCallback&&b.successCallback();else{if(!b.errorCallback)throw new Error("Remote error logging failed!");b.errorCallback()}}}function f(a){return Object.keys(a).map(function(b){return encodeURIComponent(b)+"="+encodeURIComponent(a[b])}).join("&")}function g(a){var b=a.filename.lastIndexOf("/"),c=(new Date).toString();return{type:a.type,path:a.filename,filename:a.filename.substring(++b),line:a.lineno,column:a.colno,error:a.message,stackTrace:a.error?a.error.stack.toString().replace(/(\r\n|\n|\r)/gm,""):"",datetime:c,userAgent:navigator.userAgent||window.navigator.userAgent}}var a;return"function"!=typeof Object.assign&&(Object.assign=function(a){if(null===a)throw new TypeError("Cannot convert undefined or null to object");a=Object(a);for(var b=1;b