// Scribe.js (NodeJS) // Mathew Kurian // Module dependences // --------------------------------- var util = require('util'); var mkdirp = require('mkdirp'); var path = require('path'); var moment = require('moment'); var fs = require('fs'); var stack = require('callsite'); var colors = require('colors'); var self = module.exports; self.express = {}; // Configuration // --------------------------------- var $ = { app: "scribe.js", logPath: "./../logs", mainUser: "root", maxTagLength: 50, indentation: 2, divider: ':::', defaultUserDir: '_user', testOutput: function(result, pipes, actual, expected, opts) { var pipe = result ? 'log' : 'error'; var ne = expected.indexOf("\n") > -1; var na = actual.indexOf("\n") > -1; pipes[pipe]((" " + opts + " ").bold.inverse + (result ? " PASSED ".green : " FAILED ".red).bold.inverse); pipes[pipe](" EXPECTED " [result ? "green" : "red"].bold.inverse + " " + (!ne ? expected : "")); if (ne) { pipes[pipe](expected); } pipes[pipe](" ACTUAL " [result ? "green" : "red"].bold.inverse + " " + (!na ? actual : "")); if (na) { pipes[pipe](actual); } } }; // Active settings // --------------------------------- var activeDefaultTag; var activeUserDir; var activeDateDir; var activeDayIso; var activeDir; var loggers = {}; var theme = {}; var fsOptions = { encoding: 'utf8' }; var __reserved = ["f", "t", "tag", "file", "should", "be", "test", "assert"]; // Cache pipe out // --------------------------------- var __stdpipe = (function() { return console.log; })(); // Utility functions // --------------------------------- var pretty = function(a) { if (!a) { return a + ""; } if (typeof a === 'object') { return JSON.stringify(a, null, 4); } return a.toString(); }; var compress = function(a) { if (!a) { return a + ""; } if (typeof a === 'object') { return JSON.stringify(a); } return a.toString(); }; var tag = function(a) { return "[" + a + "]"; }; var createDir = function() { mkdirp.sync(path.normalize($.logPath), 0777 & (~process.umask())); mkdirp.sync(path.normalize(path.join($.logPath, activeDateDir)), 0777 & (~process.umask())); mkdirp.sync(activeDir = path.normalize(path.join($.logPath, activeDateDir, activeUserDir)), 0777 & (~process.umask())); }; var getUser = function() { try { activeUserDir = process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'].toLowerCase(); activeUserDir = activeUserDir.slice(activeUserDir.lastIndexOf((process.platform === 'win32') ? '\\' : '/') + 1); } catch (e) { activeUserDir = $.defaultUserDir; } finally { return activeUserDir; } }; var validate = function() { var _activeDayIso = moment().day(); if (activeDayIso !== _activeDayIso) { activeDayIso = _activeDayIso; activeDateDir = moment().format('MMM_D_YY').toLowerCase(); return true; } return false; }; function Extender(tag, opts) { var self = this; self.tag = tag; self.opts = opts; self.do = self.invoke = self.should = function(actual) { var _actual = compress(actual); self.expect = self.be = function(expected) { var _expected = compress(expected); $.testOutput(_actual === _expected, self, pretty(actual), pretty(expected), self.opts); return self; }; return self; }; } var spaces = function(sp) { var s = ''; for (var z = 0; z < sp; z++) { s += ' '; } return s; }; var stackTag = function(_stack) { try { return tag(path.basename(_stack.getFileName()) + ":" + _stack.getLineNumber()); } catch (e) { return tag(activeDefaultTag); } }; // Exports // --------------------------------- self.addLogger = function(name, file, console, color) { if (arguments.length < 4) { return false; } if (__reserved.indexOf(name) > -1) { throw Error("Reserved pipe - " + name); } theme[name] = color; loggers[name] = { "file": file, "console": console }; colors.setTheme(theme); addPipe(name); return true; }; exports.removeLogger = function(name) { if (loggers[name]) { delete loggers[name]; delete console[name]; return true; } return false; }; self.set = function(a, b) { $[a] = b; }; self.configure = function(callback) { var _logPath = $.logPath; var _activeUserDir = activeUserDir; if (callback) { callback(); } activeDefaultTag = tag($.app.toLowerCase()); activeUserDir = getUser(); if ($.logPath !== _logPath) { if (_logPath) { fs.unlink(_logPath, function() {}); } } else if (_activeUserDir !== activeUserDir) { if (_activeUserDir) { fs.unlink(_activeUserDir, function() {}); } } validate(); createDir(); }; self.express.logger = function(validate) { return function(req, res, next) { if (!validate || validate(req, res)) { console.info('[%s]%s %s %s %s', "express.js", req.ip.red, req.method.green, req.url.grey, (/mobile/i.test(req.headers['user-agent']) ? 'MOBILE' : 'DESKTOP').yellow); } next(); }; }; self.express.webpipe = function() { self.addLogger('user', true, true, 'magenta'); return function(req, res) { console.t('scribe.js').user(req.ip.red + " " + req.body.data); res.send('received'); }; }; // Web Control Panel // --------------------------------- var datetemplate = fs.readFileSync(path.join(__dirname, "/log.html"), { encoding: "utf8" }); var flatColors = ["#16a085", "#27ae60", "#2980b9", "#8e44ad", "#f39c12", "#d35400", "#c0392b", "#7f8c8d"]; self.express.controlPanel = function() { return function(req, res) { var date = req.param('date'); if (!date) { var datePath = path.normalize(path.join($.logPath)); fs.readdir(datePath, function(err, files) { if (err) { console.error(err); return res.send(err); } var loggerDates = ""; for (var i = 0; i < files.length; i++) { try { var file = files[i]; var fileSplit = file.split("_"); loggerDates += '