From e9e58393c1b12e81289bf87420f057f143f1dcd0 Mon Sep 17 00:00:00 2001 From: Rob Eisenberg Date: Tue, 9 Dec 2014 16:34:10 -0500 Subject: [PATCH] chore(*): set up the project structure and build This commit adds the initial source code, sets up the project structure, creates the gulp build file and configures karma. --- .editorconfig | 14 +++++ .gitignore | 5 ++ .npmignore | 3 ++ LICENSE | 5 +- README.md | 69 ++++++++++++++++++++++-- config.js | 5 ++ dist/amd/index.js | 116 +++++++++++++++++++++++++++++++++++++++++ dist/commonjs/index.js | 114 ++++++++++++++++++++++++++++++++++++++++ dist/es6/index.js | 107 +++++++++++++++++++++++++++++++++++++ doc/api.json | 1 + gulpfile.js | 100 +++++++++++++++++++++++++++++++++++ karma.conf.js | 70 +++++++++++++++++++++++++ lib/index.js | 107 +++++++++++++++++++++++++++++++++++++ package.json | 43 +++++++++++++++ test/logging.spec.js | 8 +++ 15 files changed, 761 insertions(+), 6 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .npmignore create mode 100644 config.js create mode 100644 dist/amd/index.js create mode 100644 dist/commonjs/index.js create mode 100644 dist/es6/index.js create mode 100644 doc/api.json create mode 100644 gulpfile.js create mode 100644 karma.conf.js create mode 100644 lib/index.js create mode 100644 package.json create mode 100644 test/logging.spec.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1033e2d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true + +# 2 space indentation +[**.*] +indent_style = space +indent_size = 2 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..784886a --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +node_modules +jspm_packages +bower_components +.idea +.DS_STORE \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..cafe9b6 --- /dev/null +++ b/.npmignore @@ -0,0 +1,3 @@ +jspm_packages +bower_components +.idea \ No newline at end of file diff --git a/LICENSE b/LICENSE index 35c2026..6714c1d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 aurelia +Copyright (c) 2014 The Durandal Project Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,5 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 10ca045..85fa8e9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,67 @@ -logging -======= +# aurelia-logging -A minimal but effective logging mechanism with support for log levels and pluggable log appenders. +This library is part of the [Aurelia](http://www.aurelia.io/) platform and contains a minimal but effective logging mechanism with support for log levels and pluggable log appenders. + +> To keep up to date on [Aurelia](http://www.aurelia.io/), please visit and subscribe to [the official blog](http://blog.durandal.io/). If you have questions, we invite you to join us on [our Gitter Channel](https://gitter.im/Aurelia/Discuss). + +## Dependencies + +This library has **NO** external dependencies. + +## Platform Support + +This library can be used in the **browser** as well as on the **server**. + +## Building The Code + +To build the code, follow these steps. + +1. Ensure that [NodeJS](http://nodejs.org/) is installed. This provides the platform on which the build tooling runs. +2. From the project folder, execute the following command: + + ```shell + npm install + ``` +3. Ensure that [Gulp](http://gulpjs.com/) is installed. If you need to install it, use the following command: + + ```shell + npm install -g gulp + ``` +4. To build the code, you can now run: + + ```shell + gulp build + ``` +5. You will find the compiled code in the `dist` folder, available in three module formats: AMD, CommonJS and ES6. + +6. See `gulpfile.js` for other tasks related to generating the docs and linting. + +## Running The Tests + +To run the unit tests, first ensure that you have followed the steps above in order to install all dependencies and successfully build the library. Once you have done that, proceed with these additional steps: + +1. Ensure that the [Karma](http://karma-runner.github.io/) CLI is installed. If you need to install it, use the following command: + + ```shell + npm install -g karma-cli + ``` +2. Ensure that [jspm](http://jspm.io/) is installed. If you need to install it, use the following commnand: + + ```shell + npm install -g jspm + ``` +3. Download the [SystemJS](https://github.com/systemjs/systemjs) module loader: + + ```shell + jspm dl-loader + ``` + +4. You can now run the tests with this command: + + ```shell + karma start + ``` + +## Contributing + +We'd love for you to contribute to our source code and to make this project even better than it is today! If this interests you, please begin by reading [our contributing guidelines](https://github.com/DurandalProject/about/blob/master/CONTRIBUTING.md). The contributing document will provide you with all the information you need to get started. Once you have read that, you will need to also [sign our CLA](http://goo.gl/forms/dI8QDDSyKR) before we can accepts a Pull Request from you. More information on the process is including in the [contributor's guide](https://github.com/DurandalProject/about/blob/master/CONTRIBUTING.md). \ No newline at end of file diff --git a/config.js b/config.js new file mode 100644 index 0000000..0bd2a6a --- /dev/null +++ b/config.js @@ -0,0 +1,5 @@ +System.config({ + "paths": { + "*": "*.js" + } +}); \ No newline at end of file diff --git a/dist/amd/index.js b/dist/amd/index.js new file mode 100644 index 0000000..f9448f1 --- /dev/null +++ b/dist/amd/index.js @@ -0,0 +1,116 @@ +define(["exports"], function (exports) { + "use strict"; + + exports.getLogger = getLogger; + exports.addAppender = addAppender; + exports.setLevel = setLevel; + var loggers = {}, logLevel = 0, appenders = [], slice = Array.prototype.slice, loggerConstructionKey = {}; + + function log(logger, level, args) { + var i = appenders.length, current; + + args = slice.call(args); + args.unshift(logger); + + while (i--) { + current = appenders[i]; + current[level].apply(current, args); + } + } + + function debug() { + if (logLevel < 4) { + return; + } + + log(this, "debug", arguments); + } + + function info() { + if (logLevel < 3) { + return; + } + + log(this, "info", arguments); + } + + function warn() { + if (logLevel < 2) { + return; + } + + log(this, "warn", arguments); + } + + function error() { + if (logLevel < 1) { + return; + } + + log(this, "error", arguments); + } + + function connectLogger(logger) { + logger.debug = debug; + logger.info = info; + logger.warn = warn; + logger.error = error; + } + + function createLogger(id) { + var logger = new Logger(id, loggerConstructionKey); + + if (appenders.length) { + connectLogger(logger); + } + + return logger; + } + + var levels = exports.levels = { + error: 1, + warn: 2, + info: 3, + debug: 4 + }; + + function getLogger(id) { + return loggers[id] || (loggers[id] = createLogger(id)); + } + + function addAppender(appender) { + appenders.push(appender); + + if (appenders.length === 1) { + for (var key in loggers) { + connectLogger(loggers[key]); + } + } + } + + function setLevel(level) { + logLevel = level; + } + + var Logger = (function () { + var Logger = function Logger(id, key) { + if (key !== loggerConstructionKey) { + throw new Error("You cannot instantiate \"Logger\". Use the \"getLogger\" API instead."); + } + + this.id = id; + }; + + Logger.prototype.debug = function () {}; + + Logger.prototype.info = function () {}; + + Logger.prototype.warn = function () {}; + + Logger.prototype.error = function () {}; + + return Logger; + })(); + + exports.Logger = Logger; +}); \ No newline at end of file diff --git a/dist/commonjs/index.js b/dist/commonjs/index.js new file mode 100644 index 0000000..0eea19e --- /dev/null +++ b/dist/commonjs/index.js @@ -0,0 +1,114 @@ +"use strict"; + +exports.getLogger = getLogger; +exports.addAppender = addAppender; +exports.setLevel = setLevel; +var loggers = {}, logLevel = 0, appenders = [], slice = Array.prototype.slice, loggerConstructionKey = {}; + +function log(logger, level, args) { + var i = appenders.length, current; + + args = slice.call(args); + args.unshift(logger); + + while (i--) { + current = appenders[i]; + current[level].apply(current, args); + } +} + +function debug() { + if (logLevel < 4) { + return; + } + + log(this, "debug", arguments); +} + +function info() { + if (logLevel < 3) { + return; + } + + log(this, "info", arguments); +} + +function warn() { + if (logLevel < 2) { + return; + } + + log(this, "warn", arguments); +} + +function error() { + if (logLevel < 1) { + return; + } + + log(this, "error", arguments); +} + +function connectLogger(logger) { + logger.debug = debug; + logger.info = info; + logger.warn = warn; + logger.error = error; +} + +function createLogger(id) { + var logger = new Logger(id, loggerConstructionKey); + + if (appenders.length) { + connectLogger(logger); + } + + return logger; +} + +var levels = exports.levels = { + error: 1, + warn: 2, + info: 3, + debug: 4 +}; + +function getLogger(id) { + return loggers[id] || (loggers[id] = createLogger(id)); +} + +function addAppender(appender) { + appenders.push(appender); + + if (appenders.length === 1) { + for (var key in loggers) { + connectLogger(loggers[key]); + } + } +} + +function setLevel(level) { + logLevel = level; +} + +var Logger = (function () { + var Logger = function Logger(id, key) { + if (key !== loggerConstructionKey) { + throw new Error("You cannot instantiate \"Logger\". Use the \"getLogger\" API instead."); + } + + this.id = id; + }; + + Logger.prototype.debug = function () {}; + + Logger.prototype.info = function () {}; + + Logger.prototype.warn = function () {}; + + Logger.prototype.error = function () {}; + + return Logger; +})(); + +exports.Logger = Logger; \ No newline at end of file diff --git a/dist/es6/index.js b/dist/es6/index.js new file mode 100644 index 0000000..e72493c --- /dev/null +++ b/dist/es6/index.js @@ -0,0 +1,107 @@ +var loggers = {}, + logLevel = 0, + appenders = [], + slice = Array.prototype.slice, + loggerConstructionKey = {}; + +function log(logger, level, args){ + var i = appenders.length, + current; + + args = slice.call(args); + args.unshift(logger); + + while(i--) { + current = appenders[i]; + current[level].apply(current, args); + } +} + +function debug(){ + if(logLevel < 4){ + return; + } + + log(this, 'debug', arguments); +} + +function info(){ + if(logLevel < 3){ + return; + } + + log(this, 'info', arguments); +} + +function warn(){ + if(logLevel < 2){ + return; + } + + log(this, 'warn', arguments); +} + +function error(){ + if(logLevel < 1){ + return; + } + + log(this, 'error', arguments); +} + +function connectLogger(logger){ + logger.debug = debug; + logger.info = info; + logger.warn = warn; + logger.error = error; +} + +function createLogger(id){ + var logger = new Logger(id, loggerConstructionKey); + + if(appenders.length) { + connectLogger(logger); + } + + return logger; +} + +export var levels = { + error:1, + warn:2, + info:3, + debug:4 +}; + +export function getLogger(id){ + return loggers[id] || (loggers[id] = createLogger(id)); +} + +export function addAppender(appender){ + appenders.push(appender); + + if(appenders.length === 1){ + for(var key in loggers){ + connectLogger(loggers[key]); + } + } +} + +export function setLevel(level){ + logLevel = level; +} + +export class Logger { + constructor(id, key){ + if(key !== loggerConstructionKey){ + throw new Error('You cannot instantiate "Logger". Use the "getLogger" API instead.'); + } + + this.id = id; + } + + debug(){} + info(){} + warn(){} + error(){} +} \ No newline at end of file diff --git a/doc/api.json b/doc/api.json new file mode 100644 index 0000000..b648957 --- /dev/null +++ b/doc/api.json @@ -0,0 +1 @@ +{"project":{},"files":{},"modules":{},"classes":{},"classitems":[],"warnings":[]} \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..c621e05 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,100 @@ +var gulp = require('gulp'); +var runSequence = require('run-sequence'); +var clean = require('gulp-clean'); +var to5 = require('gulp-6to5'); +var jshint = require('gulp-jshint'); +var stylish = require('jshint-stylish'); +var yuidoc = require("gulp-yuidoc"); +var changelog = require('conventional-changelog'); +var assign = Object.assign || require('object.assign'); +var pkg = require('./package.json'); +var fs = require('fs'); + +var VERSION = pkg.version; + +var path = { + source:'lib/**/*.js', + output:'dist/', + doc:'./doc' +}; + +var compilerOptions = { + filename: '', + filenameRelative: '', + blacklist: [], + whitelist: [], + modules: '', + sourceMap: true, + sourceMapName: '', + sourceFileName: '', + sourceRoot: '', + moduleRoot: '', + amdModuleIds: false, + runtime: false, + comments: false, + experimental: false +}; + +var jshintConfig = {esnext:true}; + +gulp.task('clean', function() { + return gulp.src([path.output], {read: false}) + .pipe(clean()); +}); + +gulp.task('build-es6', function () { + return gulp.src(path.source) + .pipe(gulp.dest(path.output + 'es6')); +}); + +gulp.task('build-commonjs', function () { + return gulp.src(path.source) + .pipe(to5(assign({}, compilerOptions, {modules:'common'}))) + .pipe(gulp.dest(path.output + 'commonjs')); +}); + +gulp.task('build-amd', function () { + return gulp.src(path.source) + .pipe(to5(assign({}, compilerOptions, {modules:'amd'}))) + .pipe(gulp.dest(path.output + 'amd')); +}); + +gulp.task('lint', function() { + return gulp.src(path.source) + .pipe(jshint(jshintConfig)) + .pipe(jshint.reporter(stylish)); +}); + +gulp.task('doc', function(){ + gulp.src(path.source) + .pipe(yuidoc.parser(null, 'api.json')) + .pipe(gulp.dest(path.doc)); +}); + +gulp.task('changelog', function(callback) { + changelog({ + repository: pkg.repository.url, + version: VERSION, + file: 'CHANGELOG.md' + }, function(err, log) { + fs.writeFileSync(path.doc + '/CHANGELOG.md', log); + }); +}); + +gulp.task('build', function(callback) { + runSequence( + 'clean', + ['build-es6', 'build-commonjs', 'build-amd'], + callback + ); +}); + +gulp.task('prepare-release', function(callback){ + runSequence( + 'build', + 'lint', + 'doc', + 'changelog', + callback + ); +}); \ No newline at end of file diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..dd69fdf --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,70 @@ +// Karma configuration +// Generated on Fri Dec 05 2014 16:49:29 GMT-0500 (EST) + +module.exports = function(config) { + config.set({ + + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: '', + + + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['jspm', 'jasmine'], + + jspm: { + // Edit this to your needs + loadFiles: ['lib/**/*.js', 'test/**/*.js'] + }, + + + // list of files / patterns to load in the browser + files: [], + + + // list of files to exclude + exclude: [ + ], + + + // preprocess matching files before serving them to the browser + // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + preprocessors: { + 'test/**/*.js': ['6to5'], + 'lib/**/*.js': ['6to5'] + }, + + + // test results reporter to use + // possible values: 'dots', 'progress' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ['progress'], + + + // web server port + port: 9876, + + + // enable / disable colors in the output (reporters and logs) + colors: true, + + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: true, + + + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + browsers: ['Chrome'], + + + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: false + }); +}; diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..e72493c --- /dev/null +++ b/lib/index.js @@ -0,0 +1,107 @@ +var loggers = {}, + logLevel = 0, + appenders = [], + slice = Array.prototype.slice, + loggerConstructionKey = {}; + +function log(logger, level, args){ + var i = appenders.length, + current; + + args = slice.call(args); + args.unshift(logger); + + while(i--) { + current = appenders[i]; + current[level].apply(current, args); + } +} + +function debug(){ + if(logLevel < 4){ + return; + } + + log(this, 'debug', arguments); +} + +function info(){ + if(logLevel < 3){ + return; + } + + log(this, 'info', arguments); +} + +function warn(){ + if(logLevel < 2){ + return; + } + + log(this, 'warn', arguments); +} + +function error(){ + if(logLevel < 1){ + return; + } + + log(this, 'error', arguments); +} + +function connectLogger(logger){ + logger.debug = debug; + logger.info = info; + logger.warn = warn; + logger.error = error; +} + +function createLogger(id){ + var logger = new Logger(id, loggerConstructionKey); + + if(appenders.length) { + connectLogger(logger); + } + + return logger; +} + +export var levels = { + error:1, + warn:2, + info:3, + debug:4 +}; + +export function getLogger(id){ + return loggers[id] || (loggers[id] = createLogger(id)); +} + +export function addAppender(appender){ + appenders.push(appender); + + if(appenders.length === 1){ + for(var key in loggers){ + connectLogger(loggers[key]); + } + } +} + +export function setLevel(level){ + logLevel = level; +} + +export class Logger { + constructor(id, key){ + if(key !== loggerConstructionKey){ + throw new Error('You cannot instantiate "Logger". Use the "getLogger" API instead.'); + } + + this.id = id; + } + + debug(){} + info(){} + warn(){} + error(){} +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..d8ef1f9 --- /dev/null +++ b/package.json @@ -0,0 +1,43 @@ +{ + "name": "aurelia-logging", + "version": "0.0.1", + "description": "A minimal but effective logging mechanism with support for log levels and pluggable log appenders.", + "keywords": [ + "aurelia", + "logging" + ], + "homepage": "http://aurelia.io", + "bugs": { + "url": "https://github.com/aurelia/logging/issues" + }, + "license": "MIT", + "author": "Rob Eisenberg (http://robeisenberg.com/)", + "main": "dist/commonjs/index.js", + "repository": { + "type": "git", + "url": "git://github.com/aurelia/logging" + }, + "jspm": { + "directories": { + "lib": "dist" + }, + "main": "amd/index" + }, + "devDependencies": { + "conventional-changelog": "0.0.11", + "gulp": "^3.8.10", + "gulp-6to5": "^1.0.2", + "gulp-clean": "^0.3.1", + "gulp-jshint": "^1.9.0", + "gulp-yuidoc": "^0.1.2", + "jasmine-core": "^2.1.3", + "jshint-stylish": "^1.0.0", + "karma": "^0.12.28", + "karma-6to5-preprocessor": "^0.1.3", + "karma-chrome-launcher": "^0.1.7", + "karma-jasmine": "^0.3.2", + "karma-jspm": "^1.0.1", + "object.assign": "^1.0.3", + "run-sequence": "^1.0.2" + } +} \ No newline at end of file diff --git a/test/logging.spec.js b/test/logging.spec.js new file mode 100644 index 0000000..00e0321 --- /dev/null +++ b/test/logging.spec.js @@ -0,0 +1,8 @@ +import * as LogManager from '../lib/index'; + +describe('log manager', () => { + it('should have some tests', () => { + var logger = LogManager.getLogger('test'); + expect(logger).not.toBe(null); + }); +}); \ No newline at end of file