Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

loglevel

Package Overview
Dependencies
Maintainers
1
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

loglevel - npm Package Compare versions

Comparing version 1.8.1 to 1.9.0

.github/workflows/ci.yml

2

bower.json
{
"name": "loglevel",
"version": "1.8.1",
"version": "1.9.0",
"main": "dist/loglevel.min.js",

@@ -5,0 +5,0 @@ "dependencies": {},

@@ -29,3 +29,3 @@ Filing tickets against loglevel

* You haven't broken the existing test suite in any obvious browsers (at least check latest IE/FF/Chrome - automatic saucelabs tests for this are coming soon too)
* You haven't broken the existing test suite in any obvious browsers (at least check latest IE/FF/Chrome)
* You've added relevant tests for the bug you're fixing/the new feature you're adding/etc, which pass in all the relevant browsers

@@ -32,0 +32,0 @@ * JSHint is happy with your new code

@@ -1,2 +0,2 @@

/*! loglevel - v1.8.1 - https://github.com/pimterry/loglevel - (c) 2022 Tim Perry - licensed MIT */
/*! loglevel - v1.9.0 - https://github.com/pimterry/loglevel - (c) 2024 Tim Perry - licensed MIT */
(function (root, definition) {

@@ -29,2 +29,5 @@ "use strict";

var _loggersByName = {};
var defaultLogger = null;
// Cross-browser bind equivalent that works at least back to IE6

@@ -82,4 +85,7 @@ function bindMethod(obj, methodName) {

function replaceLoggingMethods(level, loggerName) {
function replaceLoggingMethods() {
/*jshint validthis:true */
var level = this.getLevel();
// Replace the actual methods.
for (var i = 0; i < logMethods.length; i++) {

@@ -89,3 +95,3 @@ var methodName = logMethods[i];

noop :
this.methodFactory(methodName, level, loggerName);
this.methodFactory(methodName, level, this.name);
}

@@ -95,2 +101,7 @@

this.log = this.debug;
// Return any important warnings.
if (typeof console === undefinedType && level < this.levels.SILENT) {
return "No console available for logging";
}
}

@@ -100,6 +111,6 @@

// We build realMethod() replacements here that regenerate logging methods
function enableLoggingWhenConsoleArrives(methodName, level, loggerName) {
function enableLoggingWhenConsoleArrives(methodName) {
return function () {
if (typeof console !== undefinedType) {
replaceLoggingMethods.call(this, level, loggerName);
replaceLoggingMethods.call(this);
this[methodName].apply(this, arguments);

@@ -112,3 +123,3 @@ }

// otherwise we wait for a console to appear, and then try again.
function defaultMethodFactory(methodName, level, loggerName) {
function defaultMethodFactory(methodName, _level, _loggerName) {
/*jshint validthis:true */

@@ -119,6 +130,26 @@ return realMethod(methodName) ||

function Logger(name, defaultLevel, factory) {
function Logger(name, factory) {
// Private instance variables.
var self = this;
var currentLevel;
defaultLevel = defaultLevel == null ? "WARN" : defaultLevel;
/**
* The level inherited from a parent logger (or a global default). We
* cache this here rather than delegating to the parent so that it stays
* in sync with the actual logging methods that we have installed (the
* parent could change levels but we might not have rebuilt the loggers
* in this child yet).
* @type {number}
*/
var inheritedLevel;
/**
* The default level for this logger, if any. If set, this overrides
* `inheritedLevel`.
* @type {number|null}
*/
var defaultLevel;
/**
* A user-specific level for this logger. If set, this overrides
* `defaultLevel`.
* @type {number|null}
*/
var userLevel;

@@ -163,6 +194,8 @@ var storageKey = "loglevel";

var cookie = window.document.cookie;
var location = cookie.indexOf(
encodeURIComponent(storageKey) + "=");
var cookieName = encodeURIComponent(storageKey);
var location = cookie.indexOf(cookieName + "=");
if (location !== -1) {
storedLevel = /^([^;]+)/.exec(cookie.slice(location))[1];
storedLevel = /^([^;]+)/.exec(
cookie.slice(location + cookieName.length + 1)
)[1];
}

@@ -186,3 +219,2 @@ } catch (ignore) {}

window.localStorage.removeItem(storageKey);
return;
} catch (ignore) {}

@@ -197,2 +229,14 @@

function normalizeLevel(input) {
var level = input;
if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) {
level = self.levels[level.toUpperCase()];
}
if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) {
return level;
} else {
throw new TypeError("log.setLevel() called with invalid level: " + input);
}
}
/*

@@ -212,25 +256,23 @@ *

self.getLevel = function () {
return currentLevel;
if (userLevel != null) {
return userLevel;
} else if (defaultLevel != null) {
return defaultLevel;
} else {
return inheritedLevel;
}
};
self.setLevel = function (level, persist) {
if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) {
level = self.levels[level.toUpperCase()];
userLevel = normalizeLevel(level);
if (persist !== false) { // defaults to true
persistLevelIfPossible(userLevel);
}
if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) {
currentLevel = level;
if (persist !== false) { // defaults to true
persistLevelIfPossible(level);
}
replaceLoggingMethods.call(self, level, name);
if (typeof console === undefinedType && level < self.levels.SILENT) {
return "No console available for logging";
}
} else {
throw "log.setLevel() called with invalid level: " + level;
}
// NOTE: in v2, this should call rebuild(), which updates children.
return replaceLoggingMethods.call(this);
};
self.setDefaultLevel = function (level) {
defaultLevel = level;
defaultLevel = normalizeLevel(level);
if (!getPersistedLevel()) {

@@ -242,4 +284,5 @@ self.setLevel(level, false);

self.resetLevel = function () {
self.setLevel(defaultLevel, false);
userLevel = null;
clearPersistedLevel();
replaceLoggingMethods.call(this);
};

@@ -255,8 +298,24 @@

// Initialize with the right level
self.rebuild = function () {
if (defaultLogger !== self) {
inheritedLevel = normalizeLevel(defaultLogger.getLevel());
}
replaceLoggingMethods.call(this);
if (defaultLogger === self) {
for (var childName in _loggersByName) {
_loggersByName[childName].rebuild();
}
}
};
// Initialize all the internal levels.
inheritedLevel = normalizeLevel(
defaultLogger ? defaultLogger.getLevel() : "WARN"
);
var initialLevel = getPersistedLevel();
if (initialLevel == null) {
initialLevel = defaultLevel;
if (initialLevel != null) {
userLevel = normalizeLevel(initialLevel);
}
self.setLevel(initialLevel, false);
replaceLoggingMethods.call(this);
}

@@ -270,8 +329,7 @@

var defaultLogger = new Logger();
defaultLogger = new Logger();
var _loggersByName = {};
defaultLogger.getLogger = function getLogger(name) {
if ((typeof name !== "symbol" && typeof name !== "string") || name === "") {
throw new TypeError("You must supply a name when creating a logger.");
throw new TypeError("You must supply a name when creating a logger.");
}

@@ -281,4 +339,6 @@

if (!logger) {
logger = _loggersByName[name] = new Logger(
name, defaultLogger.getLevel(), defaultLogger.methodFactory);
logger = _loggersByName[name] = new Logger(
name,
defaultLogger.methodFactory
);
}

@@ -285,0 +345,0 @@ return logger;

@@ -1,2 +0,3 @@

/*! loglevel - v1.8.1 - https://github.com/pimterry/loglevel - (c) 2022 Tim Perry - licensed MIT */
!function(a,b){"use strict";"function"==typeof define&&define.amd?define(b):"object"==typeof module&&module.exports?module.exports=b():a.log=b()}(this,function(){"use strict";function a(a,b){var c=a[b];if("function"==typeof c.bind)return c.bind(a);try{return Function.prototype.bind.call(c,a)}catch(b){return function(){return Function.prototype.apply.apply(c,[a,arguments])}}}function b(){console.log&&(console.log.apply?console.log.apply(console,arguments):Function.prototype.apply.apply(console.log,[console,arguments])),console.trace&&console.trace()}function c(c){return"debug"===c&&(c="log"),typeof console!==i&&("trace"===c&&j?b:void 0!==console[c]?a(console,c):void 0!==console.log?a(console,"log"):h)}function d(a,b){for(var c=0;c<k.length;c++){var d=k[c];this[d]=c<a?h:this.methodFactory(d,a,b)}this.log=this.debug}function e(a,b,c){return function(){typeof console!==i&&(d.call(this,b,c),this[a].apply(this,arguments))}}function f(a,b,d){return c(a)||e.apply(this,arguments)}function g(a,b,c){function e(a){var b=(k[a]||"silent").toUpperCase();if(typeof window!==i&&m){try{return void(window.localStorage[m]=b)}catch(a){}try{window.document.cookie=encodeURIComponent(m)+"="+b+";"}catch(a){}}}function g(){var a;if(typeof window!==i&&m){try{a=window.localStorage[m]}catch(a){}if(typeof a===i)try{var b=window.document.cookie,c=b.indexOf(encodeURIComponent(m)+"=");-1!==c&&(a=/^([^;]+)/.exec(b.slice(c))[1])}catch(a){}return void 0===l.levels[a]&&(a=void 0),a}}function h(){if(typeof window!==i&&m){try{return void window.localStorage.removeItem(m)}catch(a){}try{window.document.cookie=encodeURIComponent(m)+"=; expires=Thu, 01 Jan 1970 00:00:00 UTC"}catch(a){}}}var j,l=this;b=null==b?"WARN":b;var m="loglevel";"string"==typeof a?m+=":"+a:"symbol"==typeof a&&(m=void 0),l.name=a,l.levels={TRACE:0,DEBUG:1,INFO:2,WARN:3,ERROR:4,SILENT:5},l.methodFactory=c||f,l.getLevel=function(){return j},l.setLevel=function(b,c){if("string"==typeof b&&void 0!==l.levels[b.toUpperCase()]&&(b=l.levels[b.toUpperCase()]),!("number"==typeof b&&b>=0&&b<=l.levels.SILENT))throw"log.setLevel() called with invalid level: "+b;if(j=b,!1!==c&&e(b),d.call(l,b,a),typeof console===i&&b<l.levels.SILENT)return"No console available for logging"},l.setDefaultLevel=function(a){b=a,g()||l.setLevel(a,!1)},l.resetLevel=function(){l.setLevel(b,!1),h()},l.enableAll=function(a){l.setLevel(l.levels.TRACE,a)},l.disableAll=function(a){l.setLevel(l.levels.SILENT,a)};var n=g();null==n&&(n=b),l.setLevel(n,!1)}var h=function(){},i="undefined",j=typeof window!==i&&typeof window.navigator!==i&&/Trident\/|MSIE /.test(window.navigator.userAgent),k=["trace","debug","info","warn","error"],l=new g,m={};l.getLogger=function(a){if("symbol"!=typeof a&&"string"!=typeof a||""===a)throw new TypeError("You must supply a name when creating a logger.");var b=m[a];return b||(b=m[a]=new g(a,l.getLevel(),l.methodFactory)),b};var n=typeof window!==i?window.log:void 0;return l.noConflict=function(){return typeof window!==i&&window.log===l&&(window.log=n),l},l.getLoggers=function(){return m},l.default=l,l});
/*! loglevel - v1.9.0 - https://github.com/pimterry/loglevel - (c) 2024 Tim Perry - licensed MIT */
!function(e,o){"use strict";"function"==typeof define&&define.amd?define(o):"object"==typeof module&&module.exports?module.exports=o():e.log=o()}(this,function(){"use strict";var l=function(){},s="undefined",i=typeof window!==s&&typeof window.navigator!==s&&/Trident\/|MSIE /.test(window.navigator.userAgent),f=["trace","debug","info","warn","error"],p={},d=null;function r(o,e){var t=o[e];if("function"==typeof t.bind)return t.bind(o);try{return Function.prototype.bind.call(t,o)}catch(e){return function(){return Function.prototype.apply.apply(t,[o,arguments])}}}function c(){console.log&&(console.log.apply?console.log.apply(console,arguments):Function.prototype.apply.apply(console.log,[console,arguments])),console.trace&&console.trace()}function v(){for(var e=this.getLevel(),o=0;o<f.length;o++){var t=f[o];this[t]=o<e?l:this.methodFactory(t,e,this.name)}if(this.log=this.debug,typeof console===s&&e<this.levels.SILENT)return"No console available for logging"}function y(e,o,t){return"debug"===(n=e)&&(n="log"),typeof console!==s&&("trace"===n&&i?c:void 0!==console[n]?r(console,n):void 0!==console.log?r(console,"log"):l)||function(e){return function(){typeof console!==s&&(v.call(this),this[e].apply(this,arguments))}}.apply(this,arguments);var n}function t(e,o){var t,n,l,i=this,r="loglevel";function c(){var e;if(typeof window!==s&&r){try{e=window.localStorage[r]}catch(e){}if(typeof e===s)try{var o=window.document.cookie,t=encodeURIComponent(r),n=o.indexOf(t+"=");-1!==n&&(e=/^([^;]+)/.exec(o.slice(n+t.length+1))[1])}catch(e){}return void 0===i.levels[e]&&(e=void 0),e}}function a(e){var o=e;if("string"==typeof o&&void 0!==i.levels[o.toUpperCase()]&&(o=i.levels[o.toUpperCase()]),"number"==typeof o&&0<=o&&o<=i.levels.SILENT)return o;throw new TypeError("log.setLevel() called with invalid level: "+e)}"string"==typeof e?r+=":"+e:"symbol"==typeof e&&(r=void 0),i.name=e,i.levels={TRACE:0,DEBUG:1,INFO:2,WARN:3,ERROR:4,SILENT:5},i.methodFactory=o||y,i.getLevel=function(){return null!=l?l:null!=n?n:t},i.setLevel=function(e,o){return l=a(e),!1!==o&&function(e){var o=(f[e]||"silent").toUpperCase();if(typeof window!==s&&r){try{return window.localStorage[r]=o}catch(e){}try{window.document.cookie=encodeURIComponent(r)+"="+o+";"}catch(e){}}}(l),v.call(this)},i.setDefaultLevel=function(e){n=a(e),c()||i.setLevel(e,!1)},i.resetLevel=function(){l=null,function(){if(typeof window!==s&&r){try{window.localStorage.removeItem(r)}catch(e){}try{window.document.cookie=encodeURIComponent(r)+"=; expires=Thu, 01 Jan 1970 00:00:00 UTC"}catch(e){}}}(),v.call(this)},i.enableAll=function(e){i.setLevel(i.levels.TRACE,e)},i.disableAll=function(e){i.setLevel(i.levels.SILENT,e)},i.rebuild=function(){if(d!==i&&(t=a(d.getLevel())),v.call(this),d===i)for(var e in p)p[e].rebuild()},t=a(d?d.getLevel():"WARN");var u=c();null!=u&&(l=a(u)),v.call(this)}(d=new t).getLogger=function(e){if("symbol"!=typeof e&&"string"!=typeof e||""===e)throw new TypeError("You must supply a name when creating a logger.");var o=p[e];return o||(o=p[e]=new t(e,d.methodFactory)),o};var e=typeof window!==s?window.log:void 0;return d.noConflict=function(){return typeof window!==s&&window.log===d&&(window.log=e),d},d.getLoggers=function(){return p},d.default=d});
'use strict';
var Jasmine = require('jasmine');
module.exports = function (grunt) {
var jasmineRequireJsOptions = {
specs: 'test/*-test.js',
helpers: 'test/*-helper.js',
};

@@ -37,6 +43,5 @@ // Project configuration.

options: {
specs: 'test/*-test.js',
vendor: 'test/vendor/*.js',
helpers: 'test/*-helper.js',
template: require('grunt-template-jasmine-requirejs')
specs: jasmineRequireJsOptions.specs,
helpers: jasmineRequireJsOptions.helpers,
template: require('./vendor/grunt-template-jasmine-requirejs')
}

@@ -48,3 +53,2 @@ },

specs: 'test/global-integration.js',
vendor: 'test/vendor/*.js'
}

@@ -56,54 +60,10 @@ },

specs: 'test/global-integration-with-new-context.js',
vendor: 'test/vendor/*.js'
}
},
withCoverage: {
src: 'lib/**/*.js',
options: {
specs: 'test/*-test.js',
vendor: 'test/vendor/*.js',
helpers: 'test/*-helper.js',
template: require('grunt-template-jasmine-istanbul'),
templateOptions: {
coverage: 'coverage/coverage.json',
report: [
{
type: 'html',
options: {
dir: 'coverage'
}
},
{
type: 'lcov',
options: {
dir: 'coverage'
}
}
],
template: require('grunt-template-jasmine-requirejs'),
templateOptions: {
requireConfig: {
paths: {
"lib": '.grunt/grunt-contrib-jasmine/lib/'
}
}
}
}
}
}
},
"jasmine_node": {
test: {
options: {
match: "node-integration.",
matchall: true,
projectRoot: "./test",
useHelpers: false
}
jasmine_node: {
options: {
specs: ['test/node-integration.js']
}
},
coveralls: {
src: 'coverage/lcov.info'
},
open: {

@@ -120,35 +80,2 @@ jasmine: {

},
'saucelabs-jasmine': {
// Requires valid SAUCE_USERNAME and SAUCE_ACCESS_KEY in env to run.
all: {
options: {
urls: ['http://localhost:8000/_SpecRunner.html'],
browsers: [
{"browserName": "firefox", "platform": "Windows 2003", "version": "3.6"},
{"browserName": "firefox", "platform": "Windows 2003", "version": "4"},
{"browserName": "firefox", "platform": "Windows 2003", "version": "25"},
{"browserName": "safari", "platform": "Mac 10.6", "version": "5"},
{"browserName": "safari", "platform": "Mac 10.8", "version": "6"},
{"browserName": "googlechrome", "platform": "Windows 7"},
{"browserName": "opera", "platform": "Windows 2003", "version": "12"},
// Disabled because old IE breaks the Jasmine runner; these have to be manually tested
// {"browserName": "iehta", "platform": "Windows XP", "version": "6"},
// {"browserName": "iehta", "platform": "Windows XP", "version": "7"},
// {"browserName": "iehta", "platform": "Windows XP", "version": "8"},
{"browserName": "iehta", "platform": "Windows 7", "version": "9"},
{"browserName": "iehta", "platform": "Windows 7", "version": "10"},
{"browserName": "opera", "platform": "Windows 7", "version": "12"},
{"browserName": "android", "platform": "Linux", "version": "4.0"},
{"browserName": "iphone", "platform": "OS X 10.8", "version": "6"}
],
concurrency: 3,
detailedError: true,
testTimeout:10000,
testInterval:1000,
testReadyTimeout:2000,
testname: 'loglevel jasmine test',
tags: [process.env.TRAVIS_REPO_SLUG || "local", process.env.TRAVIS_COMMIT || "manual"]
}
}
},
jshint: {

@@ -188,5 +115,2 @@ options: {

},
qunit: {
all: ['test/*-qunit.html']
},
preprocess: {

@@ -207,19 +131,34 @@ "test-context-using-apply": {

grunt.loadNpmTasks('grunt-contrib-jasmine');
grunt.loadNpmTasks('grunt-coveralls');
grunt.loadNpmTasks('grunt-jasmine-node');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-open');
grunt.loadNpmTasks('grunt-saucelabs');
grunt.loadNpmTasks('grunt-preprocess');
grunt.loadNpmTasks('grunt-contrib-clean');
// Run Jasmine with Node.js tests (as opposed to browser tests).
//
// NOTE: This is designed for Jasmine 2.4, which matches the version used
// in `grunt-contrib-jasmine`. If that package is updated, this should also
// be updated to match.
grunt.registerTask('jasmine_node', 'Run Jasmine in Node.js', function() {
var done = this.async();
var jasmine = new Jasmine({ projectBaseDir: __dirname });
jasmine.onComplete(function(success) {
done(success);
});
jasmine.execute(this.options().specs);
});
// Build a distributable release
grunt.registerTask('dist', ['test', 'concat', 'uglify']);
grunt.registerTask('dist', ['test', 'dist-build']);
grunt.registerTask('dist-build', ['concat', 'uglify']);
// Check everything is good
grunt.registerTask('test', ['jshint', 'jasmine:requirejs', 'jasmine:global', 'preprocess', 'jasmine:context', 'clean:test', 'jasmine_node', 'jasmine:withCoverage', 'qunit']);
grunt.registerTask('test', ['jshint', 'test-browser', 'test-node']);
grunt.registerTask('test-browser', ['jasmine:global', 'preprocess', 'jasmine:context', 'clean:test', 'jasmine:requirejs']);
grunt.registerTask('test-node', ['jasmine_node']);

@@ -229,9 +168,4 @@ // Test with a live server and an actual browser

// Test with lots of browsers on saucelabs. Requires valid SAUCE_USERNAME and SAUCE_ACCESS_KEY in env to run.
grunt.registerTask('saucelabs', ['jasmine:requirejs:src:build', 'connect:test', 'saucelabs-jasmine']);
// Default task.
grunt.registerTask('default', 'test');
grunt.registerTask('ci', ['test', 'coveralls']);
};

@@ -193,3 +193,12 @@ // Originally from Definitely Typed, see:

disableAll(persist?: boolean): void;
/**
* Rebuild the logging methods on this logger and its child loggers.
*
* This is mostly intended for plugin developers, but can be useful if you update a logger's `methodFactory` or
* if you want to apply the root logger’s level to any *pre-existing* child loggers (this updates the level on
* any child logger that hasn't used `setLevel()` or `setDefaultLevel()`).
*/
rebuild(): void;
}
}

@@ -34,2 +34,5 @@ /*

var _loggersByName = {};
var defaultLogger = null;
// Cross-browser bind equivalent that works at least back to IE6

@@ -87,4 +90,7 @@ function bindMethod(obj, methodName) {

function replaceLoggingMethods(level, loggerName) {
function replaceLoggingMethods() {
/*jshint validthis:true */
var level = this.getLevel();
// Replace the actual methods.
for (var i = 0; i < logMethods.length; i++) {

@@ -94,3 +100,3 @@ var methodName = logMethods[i];

noop :
this.methodFactory(methodName, level, loggerName);
this.methodFactory(methodName, level, this.name);
}

@@ -100,2 +106,7 @@

this.log = this.debug;
// Return any important warnings.
if (typeof console === undefinedType && level < this.levels.SILENT) {
return "No console available for logging";
}
}

@@ -105,6 +116,6 @@

// We build realMethod() replacements here that regenerate logging methods
function enableLoggingWhenConsoleArrives(methodName, level, loggerName) {
function enableLoggingWhenConsoleArrives(methodName) {
return function () {
if (typeof console !== undefinedType) {
replaceLoggingMethods.call(this, level, loggerName);
replaceLoggingMethods.call(this);
this[methodName].apply(this, arguments);

@@ -117,3 +128,3 @@ }

// otherwise we wait for a console to appear, and then try again.
function defaultMethodFactory(methodName, level, loggerName) {
function defaultMethodFactory(methodName, _level, _loggerName) {
/*jshint validthis:true */

@@ -124,6 +135,26 @@ return realMethod(methodName) ||

function Logger(name, defaultLevel, factory) {
function Logger(name, factory) {
// Private instance variables.
var self = this;
var currentLevel;
defaultLevel = defaultLevel == null ? "WARN" : defaultLevel;
/**
* The level inherited from a parent logger (or a global default). We
* cache this here rather than delegating to the parent so that it stays
* in sync with the actual logging methods that we have installed (the
* parent could change levels but we might not have rebuilt the loggers
* in this child yet).
* @type {number}
*/
var inheritedLevel;
/**
* The default level for this logger, if any. If set, this overrides
* `inheritedLevel`.
* @type {number|null}
*/
var defaultLevel;
/**
* A user-specific level for this logger. If set, this overrides
* `defaultLevel`.
* @type {number|null}
*/
var userLevel;

@@ -168,6 +199,8 @@ var storageKey = "loglevel";

var cookie = window.document.cookie;
var location = cookie.indexOf(
encodeURIComponent(storageKey) + "=");
var cookieName = encodeURIComponent(storageKey);
var location = cookie.indexOf(cookieName + "=");
if (location !== -1) {
storedLevel = /^([^;]+)/.exec(cookie.slice(location))[1];
storedLevel = /^([^;]+)/.exec(
cookie.slice(location + cookieName.length + 1)
)[1];
}

@@ -191,3 +224,2 @@ } catch (ignore) {}

window.localStorage.removeItem(storageKey);
return;
} catch (ignore) {}

@@ -202,2 +234,14 @@

function normalizeLevel(input) {
var level = input;
if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) {
level = self.levels[level.toUpperCase()];
}
if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) {
return level;
} else {
throw new TypeError("log.setLevel() called with invalid level: " + input);
}
}
/*

@@ -217,25 +261,23 @@ *

self.getLevel = function () {
return currentLevel;
if (userLevel != null) {
return userLevel;
} else if (defaultLevel != null) {
return defaultLevel;
} else {
return inheritedLevel;
}
};
self.setLevel = function (level, persist) {
if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) {
level = self.levels[level.toUpperCase()];
userLevel = normalizeLevel(level);
if (persist !== false) { // defaults to true
persistLevelIfPossible(userLevel);
}
if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) {
currentLevel = level;
if (persist !== false) { // defaults to true
persistLevelIfPossible(level);
}
replaceLoggingMethods.call(self, level, name);
if (typeof console === undefinedType && level < self.levels.SILENT) {
return "No console available for logging";
}
} else {
throw "log.setLevel() called with invalid level: " + level;
}
// NOTE: in v2, this should call rebuild(), which updates children.
return replaceLoggingMethods.call(this);
};
self.setDefaultLevel = function (level) {
defaultLevel = level;
defaultLevel = normalizeLevel(level);
if (!getPersistedLevel()) {

@@ -247,4 +289,5 @@ self.setLevel(level, false);

self.resetLevel = function () {
self.setLevel(defaultLevel, false);
userLevel = null;
clearPersistedLevel();
replaceLoggingMethods.call(this);
};

@@ -260,8 +303,24 @@

// Initialize with the right level
self.rebuild = function () {
if (defaultLogger !== self) {
inheritedLevel = normalizeLevel(defaultLogger.getLevel());
}
replaceLoggingMethods.call(this);
if (defaultLogger === self) {
for (var childName in _loggersByName) {
_loggersByName[childName].rebuild();
}
}
};
// Initialize all the internal levels.
inheritedLevel = normalizeLevel(
defaultLogger ? defaultLogger.getLevel() : "WARN"
);
var initialLevel = getPersistedLevel();
if (initialLevel == null) {
initialLevel = defaultLevel;
if (initialLevel != null) {
userLevel = normalizeLevel(initialLevel);
}
self.setLevel(initialLevel, false);
replaceLoggingMethods.call(this);
}

@@ -275,8 +334,7 @@

var defaultLogger = new Logger();
defaultLogger = new Logger();
var _loggersByName = {};
defaultLogger.getLogger = function getLogger(name) {
if ((typeof name !== "symbol" && typeof name !== "string") || name === "") {
throw new TypeError("You must supply a name when creating a logger.");
throw new TypeError("You must supply a name when creating a logger.");
}

@@ -286,4 +344,6 @@

if (!logger) {
logger = _loggersByName[name] = new Logger(
name, defaultLogger.getLevel(), defaultLogger.methodFactory);
logger = _loggersByName[name] = new Logger(
name,
defaultLogger.methodFactory
);
}

@@ -290,0 +350,0 @@ return logger;

{
"name": "loglevel",
"description": "Minimal lightweight logging for JavaScript, adding reliable log level methods to any available console.log methods",
"version": "1.8.1",
"version": "1.9.0",
"homepage": "https://github.com/pimterry/loglevel",

@@ -29,5 +29,9 @@ "author": {

"scripts": {
"test": "grunt test && tsc --noEmit ./test/type-test.ts",
"ci": "grunt ci",
"lint": "grunt jshint",
"test": "grunt test && npm run test-types",
"test-browser": "grunt test-browser",
"test-node": "grunt test-node",
"test-types": "tsc --noEmit ./test/type-test.ts",
"dist": "grunt dist",
"dist-build": "grunt dist-build",
"watch": "grunt watch"

@@ -39,20 +43,14 @@ },

"@types/node": "^12.0.4",
"grunt": "~0.4.5",
"grunt-cli": "~0.1.13",
"grunt-contrib-clean": "^0.6.0",
"grunt": "~1.0.4",
"grunt-cli": "~1.2.0",
"grunt-contrib-clean": "^1.1.0",
"grunt-contrib-concat": "~0.5.0",
"grunt-contrib-connect": "~0.8.0",
"grunt-contrib-jasmine": "~0.5.2",
"grunt-contrib-connect": "^1.0.2",
"grunt-contrib-jasmine": "^4.0.0",
"grunt-contrib-jshint": "^1.1.0",
"grunt-contrib-qunit": "~0.5.2",
"grunt-contrib-uglify": "~0.5.1",
"grunt-contrib-watch": "~0.6.1",
"grunt-coveralls": "^1.0.0",
"grunt-jasmine-node": "~0.2.1",
"grunt-contrib-uglify": "^3.4.0",
"grunt-contrib-watch": "^1.1.0",
"grunt-open": "~0.2.3",
"grunt-preprocess": "^4.0.0",
"grunt-saucelabs": "^8.2.0",
"grunt-template-jasmine-istanbul": "~0.2.5",
"grunt-template-jasmine-requirejs": "~0.1.6",
"qunitjs": "1.14.0",
"grunt-preprocess": "^5.1.0",
"jasmine": "^2.4.1",
"typescript": "^3.5.1"

@@ -59,0 +57,0 @@ },

# loglevel [![NPM version][npm-image]][npm-url] [![NPM downloads](https://img.shields.io/npm/dw/loglevel.svg)](https://www.npmjs.com/package/loglevel) [![Build status](https://travis-ci.org/pimterry/loglevel.png)](https://travis-ci.org/pimterry/loglevel) [![Coveralls percentage](https://img.shields.io/coveralls/pimterry/loglevel.svg)](https://coveralls.io/r/pimterry/loglevel?branch=master)
# loglevel [![NPM version][npm-image]][npm-url] [![NPM downloads](https://img.shields.io/npm/dw/loglevel.svg)](https://www.npmjs.com/package/loglevel) [![Build Status](https://github.com/pimterry/loglevel/actions/workflows/ci.yml/badge.svg)](https://github.com/pimterry/loglevel/actions/workflows/ci.yml)

@@ -9,6 +9,8 @@ [npm-image]: https://img.shields.io/npm/v/loglevel.svg?style=flat

Minimal lightweight simple logging for JavaScript. loglevel replaces console.log() and friends with level-based logging and filtering, with none of console's downsides.
Minimal lightweight simple logging for JavaScript (browsers, node.js or elsewhere). loglevel extends console.log() & friends with level-based logging and filtering, with none of console's downsides.
This is a barebones reliable everyday logging library. It does not do fancy things, it does not let you reconfigure appenders or add complex log filtering rules or boil tea (more's the pity), but it does have the all core functionality that you actually use:
Test it out live in your browser console at https://pimterry.github.io/loglevel/demo/index.html
Loglevel is a barebones reliable everyday logging library. It does not do fancy things, it does not let you reconfigure appenders or add complex log filtering rules or boil tea (more's the pity), but it does have the all core functionality that you actually use:
## Features

@@ -70,3 +72,3 @@

### Directly in your web page:
### Directly in your web page

@@ -80,3 +82,3 @@ ```html

### As an ES6 module:
### As an ES6 module

@@ -99,5 +101,5 @@ loglevel is written as a UMD module, with a single object exported. Unfortunately ES6 module loaders & transpilers don't all handle this the same way. Some will treat the object as the default export, while others use it as the root exported object. In addition, loglevel includes `default` property on the root object, designed to help handle this differences. Nonetheless, there's two possible syntaxes that might work for you:

There's no major difference, unless you're using TypeScript & building a loglevel plugin (in that case, see https://github.com/pimterry/loglevel/issues/149). In general though, just use whichever suits your environment, and everything should work out fine.
There's no major difference, unless you're using TypeScript & building a loglevel plugin (in that case, see <https://github.com/pimterry/loglevel/issues/149>). In general though, just use whichever suits your environment, and everything should work out fine.
### With noConflict():
### With noConflict()

@@ -117,3 +119,3 @@ If you're using another JavaScript library that exposes a 'log' global, you can run into conflicts with loglevel. Similarly to jQuery, you can solve this by putting loglevel into no-conflict mode immediately after it is loaded onto the page. This resets to 'log' global to its value before loglevel was loaded (typically `undefined`), and returns the loglevel object, which you can then bind to another name yourself.

### TypeScript:
### TypeScript

@@ -127,2 +129,3 @@ loglevel includes its own type definitions, assuming you're using a modern module environment (e.g. Node.JS, webpack, etc), you should be able to use the ES6 syntax above, and everything will work immediately. If not, file a bug!

* In that file, add:
```typescript

@@ -136,114 +139,148 @@ import * as log from 'loglevel';

### Methods
The loglevel API is extremely minimal. All methods are available on the root loglevel object, which it's suggested you name 'log' (this is the default if you import it in globally, and is what's set up in the above examples). The API consists of:
* 5 actual logging methods, ordered and available as:
* `log.trace(msg)`
* `log.debug(msg)`
* `log.info(msg)`
* `log.warn(msg)`
* `log.error(msg)`
#### Logging Methods
`log.log(msg)` is also available, as an alias for `log.debug(msg)`, to improve compatibility with `console`, and make migration easier.
5 actual logging methods, ordered and available as:
Exact output formatting of these will depend on the console available in the current context of your application. For example, many environments will include a full stack trace with all trace() calls, and icons or similar to highlight other calls.
* `log.trace(msg)`
* `log.debug(msg)`
* `log.info(msg)`
* `log.warn(msg)`
* `log.error(msg)`
These methods should never fail in any environment, even if no console object is currently available, and should always fall back to an available log method even if the specific method called (e.g. warn) isn't available.
`log.log(msg)` is also available, as an alias for `log.debug(msg)`, to improve compatibility with `console`, and make migration easier.
Be aware that all this means that these method won't necessarily always produce exactly the output you expect in every environment; loglevel only guarantees that these methods will never explode on you, and that it will call the most relevant method it can find, with your argument. For example, `log.trace(msg)` in Firefox before version 64 prints the stacktrace by itself, and doesn't include your message (see [#84](https://github.com/pimterry/loglevel/issues/84)).
Exact output formatting of these will depend on the console available in the current context of your application. For example, many environments will include a full stack trace with all trace() calls, and icons or similar to highlight other calls.
* A `log.setLevel(level, [persist])` method.
These methods should never fail in any environment, even if no console object is currently available, and should always fall back to an available log method even if the specific method called (e.g. warn) isn't available.
This disables all logging below the given level, so that after a log.setLevel("warn") call log.warn("something") or log.error("something") will output messages, but log.info("something") will not.
Be aware that all this means that these method won't necessarily always produce exactly the output you expect in every environment; loglevel only guarantees that these methods will never explode on you, and that it will call the most relevant method it can find, with your argument. For example, `log.trace(msg)` in Firefox before version 64 prints the stacktrace by itself, and doesn't include your message (see [#84](https://github.com/pimterry/loglevel/issues/84)).
This can take either a log level name or 'silent' (which disables everything) in one of a few forms:
* As a log level from the internal levels list, e.g. log.levels.SILENT ← _for type safety_
* As a string, like 'error' (case-insensitive) ← _for a reasonable practical balance_
* As a numeric index from 0 (trace) to 5 (silent) ← _deliciously terse, and more easily programmable (...although, why?)_
#### `log.setLevel(level, [persist])`
Where possible the log level will be persisted. LocalStorage will be used if available, falling back to cookies if not. If neither is available in the current environment (i.e. in Node), or if you pass `false` as the optional 'persist' second argument, persistence will be skipped.
This disables all logging below the given level, so that after a `log.setLevel("warn")` call `log.warn("something")` or `log.error("something")` will output messages, but `log.info("something")` will not.
If log.setLevel() is called when a console object is not available (in IE 8 or 9 before the developer tools have been opened, for example) logging will remain silent until the console becomes available, and then begin logging at the requested level.
This can take either a log level name or `'silent'` (which disables everything) in one of a few forms:
* A `log.setDefaultLevel(level)` method.
* As a log level from the internal levels list, e.g. `log.levels.SILENT` ← _for type safety_
* As a string, like `'error'` (case-insensitive) ← _for a reasonable practical balance_
* As a numeric index from `0` (trace) to `5` (silent) ← _deliciously terse, and more easily programmable (...although, why?)_
This sets the current log level only if one has not been persisted and can’t be loaded. This is useful when initializing scripts; if a developer or user has previously called `setLevel()`, this won’t alter their settings. For example, your application might set the log level to `error` in a production environment, but when debugging an issue, you might call `setLevel("trace")` on the console to see all the logs. If that `error` setting was set using `setDefaultLevel()`, it will still stay as `trace` on subsequent page loads and refreshes instead of resetting to `error`.
Where possible, the log level will be persisted. LocalStorage will be used if available, falling back to cookies if not. If neither is available in the current environment (i.e. in Node), or if you pass `false` as the optional 'persist' second argument, persistence will be skipped.
The `level` argument takes is the same values that you might pass to `setLevel()`. Levels set using `setDefaultLevel()` never persist to subsequent page loads.
If `log.setLevel()` is called when a console object is not available (in IE 8 or 9 before the developer tools have been opened, for example) logging will remain silent until the console becomes available, and then begin logging at the requested level.
* A `log.resetLevel()` method.
#### `log.setDefaultLevel(level)`
This resets the current log level to the default level (or `warn` if no explicit default was set) and clears the persisted level if one was previously persisted.
This sets the current log level only if one has not been persisted and can’t be loaded. This is useful when initializing modules or scripts; if a developer or user has previously called `setLevel()`, this won’t alter their settings. For example, your application might set the log level to `error` in a production environment, but when debugging an issue, you might call `setLevel("trace")` on the console to see all the logs. If that `error` setting was set using `setDefaultLevel()`, it will still stay as `trace` on subsequent page loads and refreshes instead of resetting to `error`.
* `log.enableAll()` and `log.disableAll()` methods.
The `level` argument takes is the same values that you might pass to `setLevel()`. Levels set using `setDefaultLevel()` never persist to subsequent page loads.
These enable or disable all log messages, and are equivalent to log.setLevel("trace") and log.setLevel("silent") respectively.
#### `log.resetLevel()`
* A `log.getLevel()` method.
This resets the current log level to the logger's default level (if no explicit default was set, then it resets it to the root logger's level, or to `WARN`) and clears the persisted level if one was previously persisted.
Returns the current logging level, as a number from 0 (trace) to 5 (silent)
#### `log.enableAll()` and `log.disableAll()`
It's very unlikely you'll need to use this for normal application logging; it's provided partly to help plugin development, and partly to let you optimize logging code as below, where debug data is only generated if the level is set such that it'll actually be logged. This probably doesn't affect you, unless you've run profiling on your code and you have hard numbers telling you that your log data generation is a real performance problem.
These enable or disable all log messages, and are equivalent to log.setLevel("trace") and log.setLevel("silent") respectively.
```javascript
if (log.getLevel() <= log.levels.DEBUG) {
var logData = runExpensiveDataGeneration();
log.debug(logData);
}
```
#### `log.getLevel()`
This notably isn't the right solution to avoid the cost of string concatenation in your logging. Firstly, it's very unlikely that string concatenation in your logging is really an important performance problem. Even if you do genuinely have hard metrics showing that it is though, the better solution that wrapping your log statements in this is to use multiple arguments, as below. The underlying console API will automatically concatenate these for you if logging is enabled, and if it isn't then all log methods are no-ops, and no concatenation will be done at all.
Returns the current logging level, as a number from 0 (trace) to 5 (silent)
```javascript
// Prints 'My concatenated log message'
log.debug("My ", "concatenated ", "log message");
```
It's very unlikely you'll need to use this for normal application logging; it's provided partly to help plugin development, and partly to let you optimize logging code as below, where debug data is only generated if the level is set such that it'll actually be logged. This probably doesn't affect you, unless you've run profiling on your code and you have hard numbers telling you that your log data generation is a real performance problem.
* A `log.getLogger(loggerName)` method.
```javascript
if (log.getLevel() <= log.levels.DEBUG) {
var logData = runExpensiveDataGeneration();
log.debug(logData);
}
```
This gets you a new logger object that works exactly like the root `log` object, but can have its level and logging methods set independently. All loggers must have a name (which is a non-empty string, or a [Symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)). Calling `getLogger()` multiple times with the same name will return an identical logger object.
This notably isn't the right solution to avoid the cost of string concatenation in your logging. Firstly, it's very unlikely that string concatenation in your logging is really an important performance problem. Even if you do genuinely have hard metrics showing that it is though, the better solution that wrapping your log statements in this is to use multiple arguments, as below. The underlying console API will automatically concatenate these for you if logging is enabled, and if it isn't then all log methods are no-ops, and no concatenation will be done at all.
In large applications, it can be incredibly useful to turn logging on and off for particular modules as you are working with them. Using the `getLogger()` method lets you create a separate logger for each part of your application with its own logging level.
```javascript
// Prints 'My concatenated log message'
log.debug("My ", "concatenated ", "log message");
```
Likewise, for small, independent modules, using a named logger instead of the default root logger allows developers using your module to selectively turn on deep, trace-level logging when trying to debug problems, while logging only errors or silencing logging altogether under normal circumstances.
#### `log.getLogger(loggerName)`
Example usage *(using CommonJS modules, but you could do the same with any module system):*
This gets you a new logger object that works exactly like the root `log` object, but can have its level and logging methods set independently. All loggers must have a name (which is a non-empty string, or a [Symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)). Calling `getLogger()` multiple times with the same name will return an identical logger object.
```javascript
// In module-one.js:
var log = require("loglevel").getLogger("module-one");
function doSomethingAmazing() {
log.debug("Amazing message from module one.");
}
In large applications, it can be incredibly useful to turn logging on and off for particular modules as you are working with them. Using the `getLogger()` method lets you create a separate logger for each part of your application with its own logging level.
// In module-two.js:
var log = require("loglevel").getLogger("module-two");
function doSomethingSpecial() {
log.debug("Special message from module two.");
}
Likewise, for small, independent modules, using a named logger instead of the default root logger allows developers using your module to selectively turn on deep, trace-level logging when trying to debug problems, while logging only errors or silencing logging altogether under normal circumstances.
// In your main application module:
var log = require("loglevel");
var moduleOne = require("module-one");
var moduleTwo = require("module-two");
log.getLogger("module-two").setLevel("TRACE");
Example usage _(using CommonJS modules, but you could do the same with any module system):_
moduleOne.doSomethingAmazing();
moduleTwo.doSomethingSpecial();
// logs "Special message from module two."
// (but nothing from module one.)
```
```javascript
// In module-one.js:
var log = require("loglevel").getLogger("module-one");
function doSomethingAmazing() {
log.debug("Amazing message from module one.");
}
Loggers returned by `getLogger()` support all the same properties and methods as the default root logger, excepting `noConflict()` and the `getLogger()` method itself.
// In module-two.js:
var log = require("loglevel").getLogger("module-two");
function doSomethingSpecial() {
log.debug("Special message from module two.");
}
Like the root logger, other loggers can have their logging level saved. If a logger’s level has not been saved, it will inherit the root logger’s level when it is first created. If the root logger’s level changes later, the new level will not affect other loggers that have already been created. Loggers with Symbol names (rather than string names) will be always considered as unique instances, and will never have their logging level saved or restored.
// In your main application module:
var log = require("loglevel");
var moduleOne = require("module-one");
var moduleTwo = require("module-two");
log.getLogger("module-two").setLevel("TRACE");
Likewise, loggers will inherit the root logger’s `methodFactory`. After creation, each logger can have its `methodFactory` independently set. See the *plugins* section below for more about `methodFactory`.
moduleOne.doSomethingAmazing();
moduleTwo.doSomethingSpecial();
// logs "Special message from module two."
// (but nothing from module one.)
```
* A `log.getLoggers()` method.
Loggers returned by `getLogger()` support all the same properties and methods as the default root logger, excepting `noConflict()` and the `getLogger()` method itself.
This will return you the dictionary of all loggers created with `getLogger`, keyed off of their names.
Like the root logger, other loggers can have their logging level saved. If a logger’s level has not been saved, it will inherit the root logger’s level when it is first created. If the root logger’s level changes later, the new level will not affect other loggers that have already been created. Loggers with Symbol names (rather than string names) will be always considered as unique instances, and will never have their logging level saved or restored.
Likewise, loggers will inherit the root logger’s `methodFactory`. After creation, each logger can have its `methodFactory` independently set. See the _plugins_ section below for more about `methodFactory`.
#### `log.getLoggers()`
This will return you the dictionary of all loggers created with `getLogger`, keyed off of their names.
#### `log.rebuild()`
Ensure the various logging methods (`log.info()`, `log.warn()`, etc.) behave as expected given the currently set logging level and `methodFactory`. It will also rebuild all child loggers of the logger this was called on.
This is mostly useful for plugin development. When you call `log.setLevel()` or `log.setDefaultLevel()`, the logger is rebuilt automatically. However, if you change the logger’s `methodFactory`, you should use this to rebuild all the logging methods with your new factory.
It is also useful if you change the level of the root logger and want it to affect child loggers that you’ve already created (and have not called `someChildLogger.setLevel()` or `someChildLogger.setDefaultLevel()` on). For example:
```js
var childLogger1 = log.getLogger("child1");
childLogger1.getLevel(); // WARN (inherited from the root logger)
var childLogger2 = log.getLogger("child2");
childLogger2.setDefaultLevel("TRACE");
childLogger2.getLevel(); // TRACE
log.setLevel("ERROR");
// At this point, the child loggers have not changed:
childLogger1.getLevel(); // WARN
childLogger2.getLevel(); // TRACE
// To update them:
log.rebuild();
childLogger1.getLevel(); // ERROR (still inheriting from root logger)
childLogger2.getLevel(); // TRACE (no longer inheriting because `.setDefaultLevel() was called`)
```
## Plugins
### Existing plugins:
### Existing plugins

@@ -254,7 +291,7 @@ [loglevel-plugin-prefix](https://github.com/kutuluk/loglevel-plugin-prefix) - plugin for loglevel message prefixing.

ServerSend - https://github.com/artemyarulin/loglevel-serverSend - Forward your log messages to a remote server.
ServerSend - <https://github.com/artemyarulin/loglevel-serverSend> - Forward your log messages to a remote server.
DEBUG - https://github.com/vectrlabs/loglevel-debug - Control logging from a DEBUG environmental variable (similar to the classic [Debug](https://github.com/visionmedia/debug) module)
DEBUG - <https://github.com/vectrlabs/loglevel-debug> - Control logging from a DEBUG environmental variable (similar to the classic [Debug](https://github.com/visionmedia/debug) module)
### Writing plugins:
### Writing plugins

@@ -265,3 +302,3 @@ Loglevel provides a simple reliable minimal base for console logging that works everywhere. This means it doesn't include lots of fancy functionality that might be useful in some cases, such as log formatting and redirection (e.g. also sending log messages to a server over AJAX)

There's clearly enough enthusiasm for this even at that cost though that loglevel now includes a plugin API. To use it, redefine `log.methodFactory(methodName, logLevel, loggerName)` with a function of your own. This will be called for each enabled method each time the level is set (including initially), and should return a function to be used for the given log method `methodName`, at the given *configured* (not actual) level `logLevel`, for a logger with the given name `loggerName`. If you'd like to retain all the reliability and features of loglevel, it's recommended that this wraps the initially provided value of `log.methodFactory`.
There's clearly enough enthusiasm for this even at that cost though that loglevel now includes a plugin API. To use it, redefine `log.methodFactory(methodName, logLevel, loggerName)` with a function of your own. This will be called for each enabled method each time the level is set (including initially), and should return a function to be used for the given log method `methodName`, at the given _configured_ (not actual) level `logLevel`, for a logger with the given name `loggerName`. If you'd like to retain all the reliability and features of loglevel, it's recommended that this wraps the initially provided value of `log.methodFactory`.

@@ -279,3 +316,3 @@ For example, a plugin to prefix all log messages with "Newsflash: " would look like:

};
log.setLevel(log.getLevel()); // Be sure to call setLevel method in order to apply plugin
log.rebuild(); // Be sure to call the rebuild method in order to apply plugin.
```

@@ -288,2 +325,3 @@

## Developing & Contributing
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality.

@@ -307,2 +345,3 @@

## Release History
v0.1.0 - First working release with apparent compatibility with everything tested

@@ -362,6 +401,8 @@

v1.8.0 - Add resetLevel() method to clear persisted levels & reset to defaults
v1.8.0 - Add `resetLevel()` method to clear persisted levels & reset to defaults
v1.8.1 - Fix incorrect type definitions for MethodFactory
v1.9.0 - Added `rebuild()` method, overhaul dev & test setup, and fix some bugs (notably around cookies) en route
## `loglevel` for enterprise

@@ -374,3 +415,4 @@

## License
Copyright (c) 2013 Tim Perry
Licensed under the MIT license.

@@ -7,3 +7,3 @@ "use strict";

log[methodName]("Log message for call to " + methodName);
expect(console.log.calls.length).toEqual(1);
expect(console.log.calls.count()).toEqual(1);
});

@@ -16,3 +16,3 @@ }

define(['../lib/loglevel'], function(log) {
define(['../lib/loglevel', 'test/test-helpers'], function(log, testHelpers) {
var originalConsole = window.console;

@@ -45,2 +45,3 @@

log.trace("hello");
expect().nothing();
});

@@ -87,2 +88,3 @@

log.setLevel(log.levels.SILENT);
expect().nothing();
});

@@ -92,2 +94,3 @@

log.setLevel(log.levels.ERROR);
expect().nothing();
});

@@ -94,0 +97,0 @@

@@ -15,3 +15,3 @@ "use strict";

window.console = {"log" : jasmine.createSpy("console.log")};
this.addMatchers({
jasmine.addMatchers({
"toBeAtLevel" : testHelpers.toBeAtLevel,

@@ -18,0 +18,0 @@ "toBeTheStoredLevel" : testHelpers.toBeTheLevelStoredByCookie

@@ -13,3 +13,3 @@ "use strict";

window.console = {"log" : jasmine.createSpy("console.log")};
this.addMatchers({
jasmine.addMatchers({
"toBeAtLevel" : testHelpers.toBeAtLevel,

@@ -27,2 +27,6 @@ "toBeTheStoredLevel" : testHelpers.toBeTheLevelStoredByLocalStorage

describe("If no level is saved", function() {
beforeEach(function () {
testHelpers.clearStoredLevels();
});
it("new level is always set", function(log) {

@@ -38,3 +42,3 @@ log.setDefaultLevel("trace");

});
describe("If a level is saved", function () {

@@ -44,3 +48,3 @@ beforeEach(function () {

});
it("saved level is not modified", function (log) {

@@ -47,0 +51,0 @@ log.setDefaultLevel("debug");

@@ -20,2 +20,6 @@ "use strict";

describe("If no level is saved", function() {
beforeEach(function() {
testHelpers.clearStoredLevels();
});
it("current level is the default level", function(log) {

@@ -22,0 +26,0 @@ log.setDefaultLevel("trace");

@@ -19,2 +19,3 @@ /* global MyCustomLogger, log */

MyCustomLogger.setLevel(MyCustomLogger.levels.ERROR);
expect().nothing();
});

@@ -21,0 +22,0 @@

@@ -15,2 +15,3 @@ /* global log */

log.setLevel(log.levels.ERROR);
expect().nothing();
});

@@ -26,2 +27,20 @@

});
});
describe("noConflict()", function () {
var globalLog;
beforeEach(function () {
globalLog = window.log;
});
afterEach(function () {
window.log = globalLog;
});
it("removes global reference to `log`", function () {
var local = log.noConflict();
expect(window.log).toBeUndefined();
expect(local).toEqual(globalLog);
});
});
});

@@ -17,2 +17,3 @@ "use strict";

log.error("error");
expect().nothing();
});

@@ -23,6 +24,3 @@ });

it("can all be called", function() {
if (typeof console !== "undefined") {
log.setLevel(log.levels.TRACE);
}
log.setLevel(log.levels.TRACE);
log.trace("trace");

@@ -34,2 +32,3 @@ log.debug("debug");

log.error("error");
expect().nothing();
});

@@ -40,3 +39,3 @@ });

beforeEach(function() {
this.addMatchers({
jasmine.addMatchers({
"toBeTheStoredLevel" : testHelpers.toBeTheStoredLevel

@@ -52,2 +51,3 @@ });

log.setLevel(log.levels.ERROR);
expect().nothing();
});

@@ -54,0 +54,0 @@

@@ -67,3 +67,3 @@ "use strict";

log.setLevel();
}).toThrow("log.setLevel() called with invalid level: undefined");
}).toThrowError(TypeError, "log.setLevel() called with invalid level: undefined");
});

@@ -74,3 +74,3 @@

log.setLevel(null);
}).toThrow("log.setLevel() called with invalid level: null");
}).toThrowError(TypeError, "log.setLevel() called with invalid level: null");
});

@@ -81,3 +81,3 @@

log.setLevel(undefined);
}).toThrow("log.setLevel() called with invalid level: undefined");
}).toThrowError(TypeError, "log.setLevel() called with invalid level: undefined");
});

@@ -88,3 +88,3 @@

log.setLevel(-1);
}).toThrow("log.setLevel() called with invalid level: -1");
}).toThrowError(TypeError, "log.setLevel() called with invalid level: -1");
});

@@ -95,3 +95,3 @@

log.setLevel("InvalidLevelName");
}).toThrow("log.setLevel() called with invalid level: InvalidLevelName");
}).toThrowError(TypeError, "log.setLevel() called with invalid level: InvalidLevelName");
});

@@ -98,0 +98,0 @@ });

@@ -13,3 +13,3 @@ "use strict";

window.console = {"log" : jasmine.createSpy("console.log")};
this.addMatchers({
jasmine.addMatchers({
"toBeAtLevel" : testHelpers.toBeAtLevel,

@@ -52,3 +52,3 @@ "toBeTheStoredLevel" : testHelpers.toBeTheLevelStoredByLocalStorage,

});
describe("If trace level is saved", function () {

@@ -58,3 +58,3 @@ beforeEach(function () {

});
it("trace is the default log level", function (log) {

@@ -74,3 +74,3 @@ expect(log).toBeAtLevel("trace");

});
describe("If info level is saved", function() {

@@ -187,3 +187,3 @@ beforeEach(function() {

it("the level stored in cookies is ignored if a local storage level is set", function () {
it("the level stored in cookies is ignored if a local storage level is set", function (log, done) {
testHelpers.setCookieStoredLevel("info");

@@ -194,6 +194,7 @@ testHelpers.setLocalStorageStoredLevel("debug");

expect(log).toBeAtLevel("debug");
done();
});
});
it("the level stored in cookies is used if no local storage level is set", function () {
it("the level stored in cookies is used if no local storage level is set", function (log, done) {
testHelpers.setCookieStoredLevel("info");

@@ -204,2 +205,3 @@ window.localStorage.clear();

expect(log).toBeAtLevel("info");
done();
});

@@ -206,0 +208,0 @@ });

@@ -12,12 +12,12 @@ "use strict";

log.setLevel("trace");
expect(log.methodFactory.calls.length).toEqual(5);
expect(log.methodFactory.argsForCall[0]).toEqual(["trace", 0, undefined]);
expect(log.methodFactory.argsForCall[1]).toEqual(["debug", 0, undefined]);
expect(log.methodFactory.argsForCall[2]).toEqual(["info", 0, undefined]);
expect(log.methodFactory.argsForCall[3]).toEqual(["warn", 0, undefined]);
expect(log.methodFactory.argsForCall[4]).toEqual(["error", 0, undefined]);
expect(log.methodFactory.calls.count()).toEqual(5);
expect(log.methodFactory.calls.argsFor(0)).toEqual(["trace", 0, undefined]);
expect(log.methodFactory.calls.argsFor(1)).toEqual(["debug", 0, undefined]);
expect(log.methodFactory.calls.argsFor(2)).toEqual(["info", 0, undefined]);
expect(log.methodFactory.calls.argsFor(3)).toEqual(["warn", 0, undefined]);
expect(log.methodFactory.calls.argsFor(4)).toEqual(["error", 0, undefined]);
log.setLevel("error");
expect(log.methodFactory.calls.length).toEqual(6);
expect(log.methodFactory.argsForCall[5]).toEqual(["error", 4, undefined]);
expect(log.methodFactory.calls.count()).toEqual(6);
expect(log.methodFactory.calls.argsFor(5)).toEqual(["error", 4, undefined]);
});

@@ -39,3 +39,3 @@

logger.setLevel("error");
expect(logger.methodFactory.argsForCall[0]).toEqual(["error", 4, "newLogger"]);
expect(logger.methodFactory.calls.argsFor(0)).toEqual(["error", 4, "newLogger"]);
});

@@ -42,0 +42,0 @@

@@ -60,6 +60,21 @@ "use strict";

expect(function() { log.getLogger(undefined); }).toThrow();
if (window.Symbol) {
expect(function() { log.getLogger(Symbol()); }).toThrow();
}
});
// NOTE: this test is the same as the similarly-named test in
// `node-integration.js` (which only runs in Node.js). If making
// changes here, be sure to adjust that test as well.
it(typeof Symbol !== "undefined", "supports using symbols as names", function(log) {
var s1 = Symbol("a-symbol");
var s2 = Symbol("a-symbol");
var logger1 = log.getLogger(s1);
var defaultLevel = logger1.getLevel();
logger1.setLevel(log.levels.TRACE);
var logger2 = log.getLogger(s2);
// Should be unequal: same name, but different symbol instances
expect(logger1).not.toEqual(logger2);
expect(logger2.getLevel()).toEqual(defaultLevel);
});
});

@@ -70,3 +85,3 @@

window.console = {"log" : jasmine.createSpy("console.log")};
this.addMatchers({
jasmine.addMatchers({
"toBeAtLevel" : testHelpers.toBeAtLevel

@@ -140,3 +155,124 @@ });

});
describe("logger.resetLevel()", function() {
beforeEach(function() {
window.console = {"log" : jasmine.createSpy("console.log")};
jasmine.addMatchers({
"toBeAtLevel" : testHelpers.toBeAtLevel
});
testHelpers.clearStoredLevels();
});
afterEach(function() {
window.console = originalConsole;
});
it("resets to the inherited level if no local level was set", function(log) {
testHelpers.setStoredLevel("ERROR", "newLogger");
log.setLevel("TRACE");
var newLogger = log.getLogger("newLogger");
expect(newLogger).toBeAtLevel("ERROR");
newLogger.resetLevel();
expect(newLogger).toBeAtLevel("TRACE");
// resetLevel() should not have broken inheritance.
log.setLevel("DEBUG");
log.rebuild();
expect(newLogger).toBeAtLevel("DEBUG");
});
it("resets to the inherited level if no default level was set", function(log) {
log.setLevel("TRACE");
var newLogger = log.getLogger("newLogger");
expect(newLogger).toBeAtLevel("TRACE");
newLogger.setLevel("ERROR");
expect(newLogger).toBeAtLevel("ERROR");
newLogger.resetLevel();
expect(newLogger).toBeAtLevel("TRACE");
// resetLevel() should not have broken inheritance.
log.setLevel("DEBUG");
log.rebuild();
expect(newLogger).toBeAtLevel("DEBUG");
});
it("resets to the default level if one was set", function(log) {
testHelpers.setStoredLevel("ERROR", "newLogger");
log.setLevel("TRACE");
var newLogger = log.getLogger("newLogger");
newLogger.setDefaultLevel("INFO");
expect(newLogger).toBeAtLevel("ERROR");
newLogger.resetLevel();
expect(newLogger).toBeAtLevel("INFO");
// resetLevel() should not have caused inheritance to start.
log.setLevel("DEBUG");
log.rebuild();
expect(newLogger).toBeAtLevel("INFO");
});
});
describe("logger.rebuild()", function() {
beforeEach(function() {
window.console = {"log" : jasmine.createSpy("console.log")};
jasmine.addMatchers({
"toBeAtLevel" : testHelpers.toBeAtLevel
});
testHelpers.clearStoredLevels();
});
afterEach(function() {
window.console = originalConsole;
});
it("rebuilds existing child loggers", function(log) {
log.setLevel("TRACE");
var newLogger = log.getLogger("newLogger");
expect(newLogger).toBeAtLevel("TRACE");
log.setLevel("ERROR");
expect(newLogger).toBeAtLevel("TRACE");
log.rebuild();
expect(newLogger).toBeAtLevel("ERROR");
});
it("should not change a child's persisted level", function(log) {
testHelpers.setStoredLevel("ERROR", "newLogger");
log.setLevel("TRACE");
var newLogger = log.getLogger("newLogger");
expect(newLogger).toBeAtLevel("ERROR");
log.rebuild();
expect(newLogger).toBeAtLevel("ERROR");
});
it("should not change a child's level set with `setLevel()`", function(log) {
log.setLevel("TRACE");
var newLogger = log.getLogger("newLogger");
expect(newLogger).toBeAtLevel("TRACE");
newLogger.setLevel("DEBUG", false);
log.rebuild();
expect(newLogger).toBeAtLevel("DEBUG");
});
it("should not change a child's level set with `setDefaultLevel()`", function(log) {
log.setLevel("TRACE");
var newLogger = log.getLogger("newLogger");
expect(newLogger).toBeAtLevel("TRACE");
newLogger.setDefaultLevel("DEBUG");
log.rebuild();
expect(newLogger).toBeAtLevel("DEBUG");
});
});
});
});

@@ -28,2 +28,5 @@ "use strict";

// NOTE: this test is the same as the similarly-named test in
// `multiple-logger-test.js` (which only runs in browsers). If making
// changes here, be sure to adjust that test as well.
it("supports using symbols as names", function() {

@@ -30,0 +33,0 @@ var log = require('../lib/loglevel');

@@ -26,20 +26,28 @@ "use strict";

// Jasmine matcher to check the log level of a log object
self.toBeAtLevel = function toBeAtLevel(level) {
var log = this.actual;
var expectedWorkingCalls = log.levels.SILENT - log.levels[level.toUpperCase()];
var realLogMethod = window.console.log;
var priorCalls = realLogMethod.calls.length;
// Jasmine matcher to check the log level of a log object. Usage:
// expect(log).toBeAtLevel("DEBUG");
self.toBeAtLevel = function toBeAtLevel() {
return {
compare: function (log, level) {
var expectedWorkingCalls = log.levels.SILENT - log.levels[level.toUpperCase()];
var realLogMethod = window.console.log;
var priorCalls = realLogMethod.calls.count();
for (var ii = 0; ii < logMethods.length; ii++) {
var methodName = logMethods[ii];
log[methodName](methodName);
}
for (var ii = 0; ii < logMethods.length; ii++) {
var methodName = logMethods[ii];
log[methodName](methodName);
}
expect(realLogMethod.calls.length - priorCalls).toEqual(expectedWorkingCalls);
return true;
var actualCalls = realLogMethod.calls.count() - priorCalls;
var actualLevel = logMethods[log.levels.SILENT - actualCalls];
return {
pass: actualCalls === expectedWorkingCalls,
message: "Expected level to be '" + level + "' but found '" + actualLevel + "'"
};
}
};
};
self.isCookieStorageAvailable = function isCookieStorageAvailable() {
if (window && window.document && window.document.cookie) {
if (window && window.document && window.document.cookie != null) {
// We need to check not just that the cookie objects are available, but that they work, because

@@ -70,4 +78,6 @@ // if we run from file:// URLs they appear present but are non-functional

self.toBeTheLevelStoredByCookie = function toBeTheLevelStoredByCookie(name) {
var level = this.actual === undefined ? undefined : this.actual.toUpperCase();
// Check whether a cookie is storing the given level for the given logger
// name. If level is `undefined`, this will check that it is *not* stored.
function isLevelInCookie(level, name) {
level = level === undefined ? undefined : level.toUpperCase();
var storageKey = encodeURIComponent(getStorageKey(name));

@@ -82,6 +92,22 @@

}
}
// Jasmine matcher to check whether the given log level is in a cookie.
// Usage: `expect("DEBUG").toBeTheLevelStoredByCookie("name-of-logger")`
self.toBeTheLevelStoredByCookie = function toBeTheLevelStoredByCookie() {
return {
compare: function (actual, name) {
return {
pass: isLevelInCookie(actual, name),
message: "Level '" + actual + "' for the " + (name || "default") + " logger is not stored in a cookie"
};
}
};
};
self.toBeTheLevelStoredByLocalStorage = function toBeTheLevelStoredByLocalStorage(name) {
var level = this.actual === undefined ? undefined : this.actual.toUpperCase();
// Check whether local storage is storing the given level for the given
// logger name. If level is `undefined`, this will check that it is *not*
// stored.
function isLevelInLocalStorage(level, name) {
level = level === undefined ? undefined : level.toUpperCase();

@@ -93,8 +119,28 @@ if (window.localStorage[getStorageKey(name)] === level) {

return false;
}
// Jasmine matcher to check whether the given log level is in local storage.
// Usage: `expect("DEBUG").toBeTheLevelStoredByLocalStorage("name-of-logger")`
self.toBeTheLevelStoredByLocalStorage = function toBeTheLevelStoredByLocalStorage() {
return {
compare: function (actual, name) {
return {
pass: isLevelInLocalStorage(actual, name),
message: "Level '" + actual + "' for the " + (name || "default") + " logger is not stored in local storage"
};
}
};
};
// Jasmine matcher to check whether a given string was saved by loglevel
self.toBeTheStoredLevel = function toBeTheStoredLevel(name) {
return self.toBeTheLevelStoredByLocalStorage.call(this, name) ||
self.toBeTheLevelStoredByCookie.call(this, name);
// Jasmine matcher to check whether a given level has been persisted.
self.toBeTheStoredLevel = function toBeTheStoredLevel() {
return {
compare: function (actual, name) {
return {
pass: isLevelInLocalStorage(actual, name) ||
isLevelInCookie(actual, name),
message: "Level '" + actual + "' is not persisted for the " + (name || "default") + " logger"
};
}
};
};

@@ -126,3 +172,3 @@

if (self.isCookieStorageAvailable()) {
var storedKeys = window.document.cookie.match(/(?:^|;\s)(loglevel(\:\w+)?)(?=\=)/g);
var storedKeys = window.document.cookie.match(/(?:^|;\s)(loglevel(%3a\w+)?)(?=\=)/ig);
if (storedKeys) {

@@ -137,36 +183,57 @@ for (var i = 0; i < storedKeys.length; i++) {

self.describeIf = function describeIf(condition, name, test) {
if (condition) {
jasmine.getEnv().describe(name, test);
}
var env = jasmine.getEnv();
var implementation = condition ? env.describe : env.xdescribe;
return implementation(name, test);
};
self.itIf = function itIf(condition, name, test) {
if (condition) {
jasmine.getEnv().it(name, test);
}
var env = jasmine.getEnv();
var implementation = condition ? env.it : env.xit;
return implementation(name, test);
};
// Forcibly reloads loglevel, and asynchronously hands the resulting log back to the given callback
// via Jasmine async magic
self.withFreshLog = function withFreshLog(toRun) {
// Forcibly reloads loglevel and asynchronously hands the resulting log to
// a callback.
self.withFreshLog = function withFreshLog(toRun, onError) {
require.undef("lib/loglevel");
var freshLog;
waitsFor(function() {
require(['lib/loglevel'], function(log) {
freshLog = log;
});
return typeof freshLog !== "undefined";
require(['lib/loglevel'], function(log) {
toRun(log);
});
runs(function() {
toRun(freshLog);
});
};
// Wraps Jasmine's it(name, test) call to reload the loglevel dependency for the given test
self.itWithFreshLog = function itWithFreshLog(name, test) {
jasmine.getEnv().it(name, function() {
self.withFreshLog(test);
// Wraps Jasmine's `it(name, test)` call to reload the loglevel module
// for the given test. An optional boolean first argument causes this to
// behave like `itIf()` instead of `it()`.
//
// Normal usage:
// itWithFreshLog("test name", function(log) {
// // test code
// });
//
// Conditional usage:
// itWithFreshLog(shouldRunTest(), "test name", function(log) {
// // test code
// });
self.itWithFreshLog = function itWithFreshLog(condition, name, test) {
if (!test) {
test = name;
name = condition;
condition = true;
}
self.itIf(condition, name, function(done) {
function runTest (log) {
if (test.length > 1) {
return test(log, done);
} else {
try {
test(log);
done();
} catch (error) {
done.fail(error);
}
}
}
self.withFreshLog(runTest);
});

@@ -173,0 +240,0 @@ };

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc