first commit

This commit is contained in:
2024-01-19 11:09:11 +01:00
commit b18af7a943
29473 changed files with 4500547 additions and 0 deletions

157
node_modules/log4js/lib/LoggingEvent.js generated vendored Normal file
View File

@@ -0,0 +1,157 @@
/* eslint max-classes-per-file: ["error", 2] */
/* eslint no-underscore-dangle: ["error", { "allow": ["_getLocationKeys"] }] */
const flatted = require('flatted');
const levels = require('./levels');
class SerDe {
constructor() {
const deserialise = {
__LOG4JS_undefined__: undefined,
__LOG4JS_NaN__: Number('abc'),
__LOG4JS_Infinity__: 1 / 0,
'__LOG4JS_-Infinity__': -1 / 0,
};
this.deMap = deserialise;
this.serMap = {};
Object.keys(this.deMap).forEach((key) => {
const value = this.deMap[key];
this.serMap[value] = key;
});
}
canSerialise(key) {
if (typeof key === 'string') return false;
return key in this.serMap;
}
serialise(key) {
if (this.canSerialise(key)) return this.serMap[key];
return key;
}
canDeserialise(key) {
return key in this.deMap;
}
deserialise(key) {
if (this.canDeserialise(key)) return this.deMap[key];
return key;
}
}
const serde = new SerDe();
/**
* @name LoggingEvent
* @namespace Log4js
*/
class LoggingEvent {
/**
* Models a logging event.
* @constructor
* @param {string} categoryName name of category
* @param {Log4js.Level} level level of message
* @param {Array} data objects to log
* @param {Error} [error]
* @author Seth Chisamore
*/
constructor(categoryName, level, data, context, location, error) {
this.startTime = new Date();
this.categoryName = categoryName;
this.data = data;
this.level = level;
this.context = Object.assign({}, context); // eslint-disable-line prefer-object-spread
this.pid = process.pid;
this.error = error;
if (typeof location !== 'undefined') {
if (!location || typeof location !== 'object' || Array.isArray(location))
throw new TypeError(
'Invalid location type passed to LoggingEvent constructor'
);
this.constructor._getLocationKeys().forEach((key) => {
if (typeof location[key] !== 'undefined') this[key] = location[key];
});
}
}
/** @private */
static _getLocationKeys() {
return [
'fileName',
'lineNumber',
'columnNumber',
'callStack',
'className',
'functionName',
'functionAlias',
'callerName',
];
}
serialise() {
return flatted.stringify(this, (key, value) => {
// JSON.stringify(new Error('test')) returns {}, which is not really useful for us.
// The following allows us to serialize errors (semi) correctly.
if (value instanceof Error) {
// eslint-disable-next-line prefer-object-spread
value = Object.assign(
{ message: value.message, stack: value.stack },
value
);
}
// JSON.stringify({a: Number('abc'), b: 1/0, c: -1/0}) returns {a: null, b: null, c: null}.
// The following allows us to serialize to NaN, Infinity and -Infinity correctly.
// JSON.stringify([undefined]) returns [null].
// The following allows us to serialize to undefined correctly.
return serde.serialise(value);
});
}
static deserialise(serialised) {
let event;
try {
const rehydratedEvent = flatted.parse(serialised, (key, value) => {
if (value && value.message && value.stack) {
const fakeError = new Error(value);
Object.keys(value).forEach((k) => {
fakeError[k] = value[k];
});
value = fakeError;
}
return serde.deserialise(value);
});
this._getLocationKeys().forEach((key) => {
if (typeof rehydratedEvent[key] !== 'undefined') {
if (!rehydratedEvent.location) rehydratedEvent.location = {};
rehydratedEvent.location[key] = rehydratedEvent[key];
}
});
event = new LoggingEvent(
rehydratedEvent.categoryName,
levels.getLevel(rehydratedEvent.level.levelStr),
rehydratedEvent.data,
rehydratedEvent.context,
rehydratedEvent.location,
rehydratedEvent.error
);
event.startTime = new Date(rehydratedEvent.startTime);
event.pid = rehydratedEvent.pid;
if (rehydratedEvent.cluster) {
event.cluster = rehydratedEvent.cluster;
}
} catch (e) {
event = new LoggingEvent('log4js', levels.ERROR, [
'Unable to parse log:',
serialised,
'because: ',
e,
]);
}
return event;
}
}
module.exports = LoggingEvent;

46
node_modules/log4js/lib/appenders/adapters.js generated vendored Normal file
View File

@@ -0,0 +1,46 @@
function maxFileSizeUnitTransform(maxLogSize) {
if (typeof maxLogSize === 'number' && Number.isInteger(maxLogSize)) {
return maxLogSize;
}
const units = {
K: 1024,
M: 1024 * 1024,
G: 1024 * 1024 * 1024,
};
const validUnit = Object.keys(units);
const unit = maxLogSize.slice(-1).toLocaleUpperCase();
const value = maxLogSize.slice(0, -1).trim();
if (validUnit.indexOf(unit) < 0 || !Number.isInteger(Number(value))) {
throw Error(`maxLogSize: "${maxLogSize}" is invalid`);
} else {
return value * units[unit];
}
}
function adapter(configAdapter, config) {
const newConfig = Object.assign({}, config); // eslint-disable-line prefer-object-spread
Object.keys(configAdapter).forEach((key) => {
if (newConfig[key]) {
newConfig[key] = configAdapter[key](config[key]);
}
});
return newConfig;
}
function fileAppenderAdapter(config) {
const configAdapter = {
maxLogSize: maxFileSizeUnitTransform,
};
return adapter(configAdapter, config);
}
const adapters = {
dateFile: fileAppenderAdapter,
file: fileAppenderAdapter,
fileSync: fileAppenderAdapter,
};
module.exports.modifyConfig = (config) =>
adapters[config.type] ? adapters[config.type](config) : config;

19
node_modules/log4js/lib/appenders/categoryFilter.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
const debug = require('debug')('log4js:categoryFilter');
function categoryFilter(excludes, appender) {
if (typeof excludes === 'string') excludes = [excludes];
return (logEvent) => {
debug(`Checking ${logEvent.categoryName} against ${excludes}`);
if (excludes.indexOf(logEvent.categoryName) === -1) {
debug('Not excluded, sending to appender');
appender(logEvent);
}
};
}
function configure(config, layouts, findAppender) {
const appender = findAppender(config.appender);
return categoryFilter(config.exclude, appender);
}
module.exports.configure = configure;

18
node_modules/log4js/lib/appenders/console.js generated vendored Normal file
View File

@@ -0,0 +1,18 @@
// eslint-disable-next-line no-console
const consoleLog = console.log.bind(console);
function consoleAppender(layout, timezoneOffset) {
return (loggingEvent) => {
consoleLog(layout(loggingEvent, timezoneOffset));
};
}
function configure(config, layouts) {
let layout = layouts.colouredLayout;
if (config.layout) {
layout = layouts.layout(config.layout.type, config.layout);
}
return consoleAppender(layout, config.timezoneOffset);
}
module.exports.configure = configure;

76
node_modules/log4js/lib/appenders/dateFile.js generated vendored Normal file
View File

@@ -0,0 +1,76 @@
const streams = require('streamroller');
const os = require('os');
const eol = os.EOL;
function openTheStream(filename, pattern, options) {
const stream = new streams.DateRollingFileStream(filename, pattern, options);
stream.on('error', (err) => {
// eslint-disable-next-line no-console
console.error(
'log4js.dateFileAppender - Writing to file %s, error happened ',
filename,
err
);
});
stream.on('drain', () => {
process.emit('log4js:pause', false);
});
return stream;
}
/**
* File appender that rolls files according to a date pattern.
* @param filename base filename.
* @param pattern the format that will be added to the end of filename when rolling,
* also used to check when to roll files - defaults to '.yyyy-MM-dd'
* @param layout layout function for log messages - defaults to basicLayout
* @param options - options to be passed to the underlying stream
* @param timezoneOffset - optional timezone offset in minutes (default system local)
*/
function appender(filename, pattern, layout, options, timezoneOffset) {
// the options for file appender use maxLogSize, but the docs say any file appender
// options should work for dateFile as well.
options.maxSize = options.maxLogSize;
const writer = openTheStream(filename, pattern, options);
const app = function (logEvent) {
if (!writer.writable) {
return;
}
if (!writer.write(layout(logEvent, timezoneOffset) + eol, 'utf8')) {
process.emit('log4js:pause', true);
}
};
app.shutdown = function (complete) {
writer.end('', 'utf-8', complete);
};
return app;
}
function configure(config, layouts) {
let layout = layouts.basicLayout;
if (config.layout) {
layout = layouts.layout(config.layout.type, config.layout);
}
if (!config.alwaysIncludePattern) {
config.alwaysIncludePattern = false;
}
// security default (instead of relying on streamroller default)
config.mode = config.mode || 0o600;
return appender(
config.filename,
config.pattern,
layout,
config,
config.timezoneOffset
);
}
module.exports.configure = configure;

154
node_modules/log4js/lib/appenders/file.js generated vendored Normal file
View File

@@ -0,0 +1,154 @@
const debug = require('debug')('log4js:file');
const path = require('path');
const streams = require('streamroller');
const os = require('os');
const eol = os.EOL;
let mainSighupListenerStarted = false;
const sighupListeners = new Set();
function mainSighupHandler() {
sighupListeners.forEach((app) => {
app.sighupHandler();
});
}
/**
* File Appender writing the logs to a text file. Supports rolling of logs by size.
*
* @param file the file log messages will be written to
* @param layout a function that takes a logEvent and returns a string
* (defaults to basicLayout).
* @param logSize - the maximum size (in bytes) for a log file,
* if not provided then logs won't be rotated.
* @param numBackups - the number of log files to keep after logSize
* has been reached (default 5)
* @param options - options to be passed to the underlying stream
* @param timezoneOffset - optional timezone offset in minutes (default system local)
*/
function fileAppender(
file,
layout,
logSize,
numBackups,
options,
timezoneOffset
) {
if (typeof file !== 'string' || file.length === 0) {
throw new Error(`Invalid filename: ${file}`);
} else if (file.endsWith(path.sep)) {
throw new Error(`Filename is a directory: ${file}`);
} else if (file.indexOf(`~${path.sep}`) === 0) {
// handle ~ expansion: https://github.com/nodejs/node/issues/684
// exclude ~ and ~filename as these can be valid files
file = file.replace('~', os.homedir());
}
file = path.normalize(file);
numBackups = !numBackups && numBackups !== 0 ? 5 : numBackups;
debug(
'Creating file appender (',
file,
', ',
logSize,
', ',
numBackups,
', ',
options,
', ',
timezoneOffset,
')'
);
function openTheStream(filePath, fileSize, numFiles, opt) {
const stream = new streams.RollingFileStream(
filePath,
fileSize,
numFiles,
opt
);
stream.on('error', (err) => {
// eslint-disable-next-line no-console
console.error(
'log4js.fileAppender - Writing to file %s, error happened ',
filePath,
err
);
});
stream.on('drain', () => {
process.emit('log4js:pause', false);
});
return stream;
}
let writer = openTheStream(file, logSize, numBackups, options);
const app = function (loggingEvent) {
if (!writer.writable) {
return;
}
if (options.removeColor === true) {
// eslint-disable-next-line no-control-regex
const regex = /\x1b[[0-9;]*m/g;
loggingEvent.data = loggingEvent.data.map((d) => {
if (typeof d === 'string') return d.replace(regex, '');
return d;
});
}
if (!writer.write(layout(loggingEvent, timezoneOffset) + eol, 'utf8')) {
process.emit('log4js:pause', true);
}
};
app.reopen = function () {
writer.end(() => {
writer = openTheStream(file, logSize, numBackups, options);
});
};
app.sighupHandler = function () {
debug('SIGHUP handler called.');
app.reopen();
};
app.shutdown = function (complete) {
sighupListeners.delete(app);
if (sighupListeners.size === 0 && mainSighupListenerStarted) {
process.removeListener('SIGHUP', mainSighupHandler);
mainSighupListenerStarted = false;
}
writer.end('', 'utf-8', complete);
};
// On SIGHUP, close and reopen all files. This allows this appender to work with
// logrotate. Note that if you are using logrotate, you should not set
// `logSize`.
sighupListeners.add(app);
if (!mainSighupListenerStarted) {
process.on('SIGHUP', mainSighupHandler);
mainSighupListenerStarted = true;
}
return app;
}
function configure(config, layouts) {
let layout = layouts.basicLayout;
if (config.layout) {
layout = layouts.layout(config.layout.type, config.layout);
}
// security default (instead of relying on streamroller default)
config.mode = config.mode || 0o600;
return fileAppender(
config.filename,
layout,
config.maxLogSize,
config.backups,
config,
config.timezoneOffset
);
}
module.exports.configure = configure;

258
node_modules/log4js/lib/appenders/fileSync.js generated vendored Executable file
View File

@@ -0,0 +1,258 @@
const debug = require('debug')('log4js:fileSync');
const path = require('path');
const fs = require('fs');
const os = require('os');
const eol = os.EOL;
function touchFile(file, options) {
// attempt to create the directory
const mkdir = (dir) => {
try {
return fs.mkdirSync(dir, { recursive: true });
} catch (e) {
// backward-compatible fs.mkdirSync for nodejs pre-10.12.0 (without recursive option)
// recursive creation of parent first
if (e.code === 'ENOENT') {
mkdir(path.dirname(dir));
return mkdir(dir);
}
// throw error for all except EEXIST and EROFS (read-only filesystem)
if (e.code !== 'EEXIST' && e.code !== 'EROFS') {
throw e;
}
// EEXIST: throw if file and not directory
// EROFS : throw if directory not found
else {
try {
if (fs.statSync(dir).isDirectory()) {
return dir;
}
throw e;
} catch (err) {
throw e;
}
}
}
};
mkdir(path.dirname(file));
// try to throw EISDIR, EROFS, EACCES
fs.appendFileSync(file, '', { mode: options.mode, flag: options.flags });
}
class RollingFileSync {
constructor(filename, maxLogSize, backups, options) {
debug('In RollingFileStream');
if (maxLogSize < 0) {
throw new Error(`maxLogSize (${maxLogSize}) should be > 0`);
}
this.filename = filename;
this.size = maxLogSize;
this.backups = backups;
this.options = options;
this.currentSize = 0;
function currentFileSize(file) {
let fileSize = 0;
try {
fileSize = fs.statSync(file).size;
} catch (e) {
// file does not exist
touchFile(file, options);
}
return fileSize;
}
this.currentSize = currentFileSize(this.filename);
}
shouldRoll() {
debug(
'should roll with current size %d, and max size %d',
this.currentSize,
this.size
);
return this.currentSize >= this.size;
}
roll(filename) {
const that = this;
const nameMatcher = new RegExp(`^${path.basename(filename)}`);
function justTheseFiles(item) {
return nameMatcher.test(item);
}
function index(filename_) {
return (
parseInt(filename_.slice(`${path.basename(filename)}.`.length), 10) || 0
);
}
function byIndex(a, b) {
return index(a) - index(b);
}
function increaseFileIndex(fileToRename) {
const idx = index(fileToRename);
debug(`Index of ${fileToRename} is ${idx}`);
if (that.backups === 0) {
fs.truncateSync(filename, 0);
} else if (idx < that.backups) {
// on windows, you can get a EEXIST error if you rename a file to an existing file
// so, we'll try to delete the file we're renaming to first
try {
fs.unlinkSync(`${filename}.${idx + 1}`);
} catch (e) {
// ignore err: if we could not delete, it's most likely that it doesn't exist
}
debug(`Renaming ${fileToRename} -> ${filename}.${idx + 1}`);
fs.renameSync(
path.join(path.dirname(filename), fileToRename),
`${filename}.${idx + 1}`
);
}
}
function renameTheFiles() {
// roll the backups (rename file.n to file.n+1, where n <= numBackups)
debug('Renaming the old files');
const files = fs.readdirSync(path.dirname(filename));
files
.filter(justTheseFiles)
.sort(byIndex)
.reverse()
.forEach(increaseFileIndex);
}
debug('Rolling, rolling, rolling');
renameTheFiles();
}
// eslint-disable-next-line no-unused-vars
write(chunk, encoding) {
const that = this;
function writeTheChunk() {
debug('writing the chunk to the file');
that.currentSize += chunk.length;
fs.appendFileSync(that.filename, chunk);
}
debug('in write');
if (this.shouldRoll()) {
this.currentSize = 0;
this.roll(this.filename);
}
writeTheChunk();
}
}
/**
* File Appender writing the logs to a text file. Supports rolling of logs by size.
*
* @param file the file log messages will be written to
* @param layout a function that takes a logevent and returns a string
* (defaults to basicLayout).
* @param logSize - the maximum size (in bytes) for a log file,
* if not provided then logs won't be rotated.
* @param numBackups - the number of log files to keep after logSize
* has been reached (default 5)
* @param options - options to be passed to the underlying stream
* @param timezoneOffset - optional timezone offset in minutes (default system local)
*/
function fileAppender(
file,
layout,
logSize,
numBackups,
options,
timezoneOffset
) {
if (typeof file !== 'string' || file.length === 0) {
throw new Error(`Invalid filename: ${file}`);
} else if (file.endsWith(path.sep)) {
throw new Error(`Filename is a directory: ${file}`);
} else if (file.indexOf(`~${path.sep}`) === 0) {
// handle ~ expansion: https://github.com/nodejs/node/issues/684
// exclude ~ and ~filename as these can be valid files
file = file.replace('~', os.homedir());
}
file = path.normalize(file);
numBackups = !numBackups && numBackups !== 0 ? 5 : numBackups;
debug(
'Creating fileSync appender (',
file,
', ',
logSize,
', ',
numBackups,
', ',
options,
', ',
timezoneOffset,
')'
);
function openTheStream(filePath, fileSize, numFiles) {
let stream;
if (fileSize) {
stream = new RollingFileSync(filePath, fileSize, numFiles, options);
} else {
stream = ((f) => {
// touch the file to apply flags (like w to truncate the file)
touchFile(f, options);
return {
write(data) {
fs.appendFileSync(f, data);
},
};
})(filePath);
}
return stream;
}
const logFile = openTheStream(file, logSize, numBackups);
return (loggingEvent) => {
logFile.write(layout(loggingEvent, timezoneOffset) + eol);
};
}
function configure(config, layouts) {
let layout = layouts.basicLayout;
if (config.layout) {
layout = layouts.layout(config.layout.type, config.layout);
}
const options = {
flags: config.flags || 'a',
encoding: config.encoding || 'utf8',
mode: config.mode || 0o600,
};
return fileAppender(
config.filename,
layout,
config.maxLogSize,
config.backups,
options,
config.timezoneOffset
);
}
module.exports.configure = configure;

0
node_modules/log4js/lib/appenders/ignoreBrowser.js generated vendored Normal file
View File

182
node_modules/log4js/lib/appenders/index.js generated vendored Normal file
View File

@@ -0,0 +1,182 @@
const path = require('path');
const debug = require('debug')('log4js:appenders');
const configuration = require('../configuration');
const clustering = require('../clustering');
const levels = require('../levels');
const layouts = require('../layouts');
const adapters = require('./adapters');
// pre-load the core appenders so that webpack can find them
const coreAppenders = new Map();
coreAppenders.set('console', require('./console'));
coreAppenders.set('stdout', require('./stdout'));
coreAppenders.set('stderr', require('./stderr'));
coreAppenders.set('logLevelFilter', require('./logLevelFilter'));
coreAppenders.set('categoryFilter', require('./categoryFilter'));
coreAppenders.set('noLogFilter', require('./noLogFilter'));
coreAppenders.set('file', require('./file'));
coreAppenders.set('dateFile', require('./dateFile'));
coreAppenders.set('fileSync', require('./fileSync'));
coreAppenders.set('tcp', require('./tcp'));
const appenders = new Map();
const tryLoading = (modulePath, config) => {
let resolvedPath;
try {
const modulePathCJS = `${modulePath}.cjs`;
resolvedPath = require.resolve(modulePathCJS);
debug('Loading module from ', modulePathCJS);
} catch (e) {
resolvedPath = modulePath;
debug('Loading module from ', modulePath);
}
try {
// eslint-disable-next-line global-require, import/no-dynamic-require
return require(resolvedPath);
} catch (e) {
// if the module was found, and we still got an error, then raise it
configuration.throwExceptionIf(
config,
e.code !== 'MODULE_NOT_FOUND',
`appender "${modulePath}" could not be loaded (error was: ${e})`
);
return undefined;
}
};
const loadAppenderModule = (type, config) =>
coreAppenders.get(type) ||
tryLoading(`./${type}`, config) ||
tryLoading(type, config) ||
(require.main &&
require.main.filename &&
tryLoading(path.join(path.dirname(require.main.filename), type), config)) ||
tryLoading(path.join(process.cwd(), type), config);
const appendersLoading = new Set();
const getAppender = (name, config) => {
if (appenders.has(name)) return appenders.get(name);
if (!config.appenders[name]) return false;
if (appendersLoading.has(name))
throw new Error(`Dependency loop detected for appender ${name}.`);
appendersLoading.add(name);
debug(`Creating appender ${name}`);
// eslint-disable-next-line no-use-before-define
const appender = createAppender(name, config);
appendersLoading.delete(name);
appenders.set(name, appender);
return appender;
};
const createAppender = (name, config) => {
const appenderConfig = config.appenders[name];
const appenderModule = appenderConfig.type.configure
? appenderConfig.type
: loadAppenderModule(appenderConfig.type, config);
configuration.throwExceptionIf(
config,
configuration.not(appenderModule),
`appender "${name}" is not valid (type "${appenderConfig.type}" could not be found)`
);
if (appenderModule.appender) {
process.emitWarning(
`Appender ${appenderConfig.type} exports an appender function.`,
'DeprecationWarning',
'log4js-node-DEP0001'
);
debug(
'[log4js-node-DEP0001]',
`DEPRECATION: Appender ${appenderConfig.type} exports an appender function.`
);
}
if (appenderModule.shutdown) {
process.emitWarning(
`Appender ${appenderConfig.type} exports a shutdown function.`,
'DeprecationWarning',
'log4js-node-DEP0002'
);
debug(
'[log4js-node-DEP0002]',
`DEPRECATION: Appender ${appenderConfig.type} exports a shutdown function.`
);
}
debug(`${name}: clustering.isMaster ? ${clustering.isMaster()}`);
debug(
// eslint-disable-next-line global-require
`${name}: appenderModule is ${require('util').inspect(appenderModule)}`
);
return clustering.onlyOnMaster(
() => {
debug(
`calling appenderModule.configure for ${name} / ${appenderConfig.type}`
);
return appenderModule.configure(
adapters.modifyConfig(appenderConfig),
layouts,
(appender) => getAppender(appender, config),
levels
);
},
/* istanbul ignore next: fn never gets called by non-master yet needed to pass config validation */ () => {}
);
};
const setup = (config) => {
appenders.clear();
appendersLoading.clear();
if (!config) {
return;
}
const usedAppenders = [];
Object.values(config.categories).forEach((category) => {
usedAppenders.push(...category.appenders);
});
Object.keys(config.appenders).forEach((name) => {
// dodgy hard-coding of special case for tcp-server and multiprocess which may not have
// any categories associated with it, but needs to be started up anyway
if (
usedAppenders.includes(name) ||
config.appenders[name].type === 'tcp-server' ||
config.appenders[name].type === 'multiprocess'
) {
getAppender(name, config);
}
});
};
const init = () => {
setup();
};
init();
configuration.addListener((config) => {
configuration.throwExceptionIf(
config,
configuration.not(configuration.anObject(config.appenders)),
'must have a property "appenders" of type object.'
);
const appenderNames = Object.keys(config.appenders);
configuration.throwExceptionIf(
config,
configuration.not(appenderNames.length),
'must define at least one appender.'
);
appenderNames.forEach((name) => {
configuration.throwExceptionIf(
config,
configuration.not(config.appenders[name].type),
`appender "${name}" is not valid (must be an object with property "type")`
);
});
});
configuration.addListener(setup);
module.exports = appenders;
module.exports.init = init;

20
node_modules/log4js/lib/appenders/logLevelFilter.js generated vendored Normal file
View File

@@ -0,0 +1,20 @@
function logLevelFilter(minLevelString, maxLevelString, appender, levels) {
const minLevel = levels.getLevel(minLevelString);
const maxLevel = levels.getLevel(maxLevelString, levels.FATAL);
return (logEvent) => {
const eventLevel = logEvent.level;
if (
minLevel.isLessThanOrEqualTo(eventLevel) &&
maxLevel.isGreaterThanOrEqualTo(eventLevel)
) {
appender(logEvent);
}
};
}
function configure(config, layouts, findAppender, levels) {
const appender = findAppender(config.appender);
return logLevelFilter(config.level, config.maxLevel, appender, levels);
}
module.exports.configure = configure;

91
node_modules/log4js/lib/appenders/multiFile.js generated vendored Normal file
View File

@@ -0,0 +1,91 @@
const debug = require('debug')('log4js:multiFile');
const path = require('path');
const fileAppender = require('./file');
const findFileKey = (property, event) =>
event[property] || event.context[property];
module.exports.configure = (config, layouts) => {
debug('Creating a multi-file appender');
const files = new Map();
const timers = new Map();
function checkForTimeout(fileKey) {
const timer = timers.get(fileKey);
const app = files.get(fileKey);
/* istanbul ignore else: failsafe */
if (timer && app) {
if (Date.now() - timer.lastUsed > timer.timeout) {
debug('%s not used for > %d ms => close', fileKey, timer.timeout);
clearInterval(timer.interval);
timers.delete(fileKey);
files.delete(fileKey);
app.shutdown((err) => {
if (err) {
debug('ignore error on file shutdown: %s', err.message);
}
});
}
} else {
// will never get here as files and timers are coupled to be added and deleted at same place
debug('timer or app does not exist');
}
}
const appender = (logEvent) => {
const fileKey = findFileKey(config.property, logEvent);
debug('fileKey for property ', config.property, ' is ', fileKey);
if (fileKey) {
let file = files.get(fileKey);
debug('existing file appender is ', file);
if (!file) {
debug('creating new file appender');
config.filename = path.join(config.base, fileKey + config.extension);
file = fileAppender.configure(config, layouts);
files.set(fileKey, file);
if (config.timeout) {
debug('creating new timer');
timers.set(fileKey, {
timeout: config.timeout,
lastUsed: Date.now(),
interval: setInterval(
checkForTimeout.bind(null, fileKey),
config.timeout
),
});
}
} else if (config.timeout) {
debug('%s extending activity', fileKey);
timers.get(fileKey).lastUsed = Date.now();
}
file(logEvent);
} else {
debug('No fileKey for logEvent, quietly ignoring this log event');
}
};
appender.shutdown = (cb) => {
let shutdownFunctions = files.size;
if (shutdownFunctions <= 0) {
cb();
}
let error;
timers.forEach((timer, fileKey) => {
debug('clearing timer for ', fileKey);
clearInterval(timer.interval);
});
files.forEach((app, fileKey) => {
debug('calling shutdown for ', fileKey);
app.shutdown((err) => {
error = error || err;
shutdownFunctions -= 1;
if (shutdownFunctions <= 0) {
cb(error);
}
});
});
};
return appender;
};

191
node_modules/log4js/lib/appenders/multiprocess.js generated vendored Normal file
View File

@@ -0,0 +1,191 @@
const debug = require('debug')('log4js:multiprocess');
const net = require('net');
const LoggingEvent = require('../LoggingEvent');
const END_MSG = '__LOG4JS__';
/**
* Creates a server, listening on config.loggerPort, config.loggerHost.
* Output goes to config.actualAppender (config.appender is used to
* set up that appender).
*/
function logServer(config, actualAppender, levels) {
/**
* Takes a utf-8 string, returns an object with
* the correct log properties.
*/
function deserializeLoggingEvent(clientSocket, msg) {
debug('(master) deserialising log event');
const loggingEvent = LoggingEvent.deserialise(msg);
loggingEvent.remoteAddress = clientSocket.remoteAddress;
loggingEvent.remotePort = clientSocket.remotePort;
return loggingEvent;
}
const server = net.createServer((clientSocket) => {
debug('(master) connection received');
clientSocket.setEncoding('utf8');
let logMessage = '';
function logTheMessage(msg) {
debug('(master) deserialising log event and sending to actual appender');
actualAppender(deserializeLoggingEvent(clientSocket, msg));
}
function chunkReceived(chunk) {
debug('(master) chunk of data received');
let event;
logMessage += chunk || '';
if (logMessage.indexOf(END_MSG) > -1) {
event = logMessage.slice(0, logMessage.indexOf(END_MSG));
logTheMessage(event);
logMessage = logMessage.slice(event.length + END_MSG.length) || '';
// check for more, maybe it was a big chunk
chunkReceived();
}
}
function handleError(error) {
const loggingEvent = {
startTime: new Date(),
categoryName: 'log4js',
level: levels.ERROR,
data: ['A worker log process hung up unexpectedly', error],
remoteAddress: clientSocket.remoteAddress,
remotePort: clientSocket.remotePort,
};
actualAppender(loggingEvent);
}
clientSocket.on('data', chunkReceived);
clientSocket.on('end', chunkReceived);
clientSocket.on('error', handleError);
});
server.listen(
config.loggerPort || 5000,
config.loggerHost || 'localhost',
(e) => {
debug('(master) master server listening, error was ', e);
// allow the process to exit, if this is the only socket active
server.unref();
}
);
function app(event) {
debug('(master) log event sent directly to actual appender (local event)');
return actualAppender(event);
}
app.shutdown = function (cb) {
debug('(master) master shutdown called, closing server');
server.close(cb);
};
return app;
}
function workerAppender(config) {
let canWrite = false;
const buffer = [];
let socket;
let shutdownAttempts = 3;
function write(loggingEvent) {
debug('(worker) Writing log event to socket');
socket.write(loggingEvent.serialise(), 'utf8');
socket.write(END_MSG, 'utf8');
}
function emptyBuffer() {
let evt;
debug('(worker) emptying worker buffer');
while ((evt = buffer.shift())) {
write(evt);
}
}
function createSocket() {
debug(
`(worker) worker appender creating socket to ${
config.loggerHost || 'localhost'
}:${config.loggerPort || 5000}`
);
socket = net.createConnection(
config.loggerPort || 5000,
config.loggerHost || 'localhost'
);
socket.on('connect', () => {
debug('(worker) worker socket connected');
emptyBuffer();
canWrite = true;
});
socket.on('timeout', socket.end.bind(socket));
socket.on('error', (e) => {
debug('connection error', e);
canWrite = false;
emptyBuffer();
});
socket.on('close', createSocket);
}
createSocket();
function log(loggingEvent) {
if (canWrite) {
write(loggingEvent);
} else {
debug(
'(worker) worker buffering log event because it cannot write at the moment'
);
buffer.push(loggingEvent);
}
}
log.shutdown = function (cb) {
debug('(worker) worker shutdown called');
if (buffer.length && shutdownAttempts) {
debug('(worker) worker buffer has items, waiting 100ms to empty');
shutdownAttempts -= 1;
setTimeout(() => {
log.shutdown(cb);
}, 100);
} else {
socket.removeAllListeners('close');
socket.end(cb);
}
};
return log;
}
function createAppender(config, appender, levels) {
if (config.mode === 'master') {
debug('Creating master appender');
return logServer(config, appender, levels);
}
debug('Creating worker appender');
return workerAppender(config);
}
function configure(config, layouts, findAppender, levels) {
let appender;
debug(`configure with mode = ${config.mode}`);
if (config.mode === 'master') {
if (!config.appender) {
debug(`no appender found in config ${config}`);
throw new Error('multiprocess master must have an "appender" defined');
}
debug(`actual appender is ${config.appender}`);
appender = findAppender(config.appender);
if (!appender) {
debug(`actual appender "${config.appender}" not found`);
throw new Error(
`multiprocess master appender "${config.appender}" not defined`
);
}
}
return createAppender(config, appender, levels);
}
module.exports.configure = configure;

43
node_modules/log4js/lib/appenders/noLogFilter.js generated vendored Normal file
View File

@@ -0,0 +1,43 @@
const debug = require('debug')('log4js:noLogFilter');
/**
* The function removes empty or null regexp from the array
* @param {string[]} regexp
* @returns {string[]} a filtered string array with not empty or null regexp
*/
function removeNullOrEmptyRegexp(regexp) {
const filtered = regexp.filter((el) => el != null && el !== '');
return filtered;
}
/**
* Returns a function that will exclude the events in case they match
* with the regular expressions provided
* @param {(string|string[])} filters contains the regexp that will be used for the evaluation
* @param {*} appender
* @returns {function}
*/
function noLogFilter(filters, appender) {
return (logEvent) => {
debug(`Checking data: ${logEvent.data} against filters: ${filters}`);
if (typeof filters === 'string') {
filters = [filters];
}
filters = removeNullOrEmptyRegexp(filters);
const regex = new RegExp(filters.join('|'), 'i');
if (
filters.length === 0 ||
logEvent.data.findIndex((value) => regex.test(value)) < 0
) {
debug('Not excluded, sending to appender');
appender(logEvent);
}
};
}
function configure(config, layouts, findAppender) {
const appender = findAppender(config.appender);
return noLogFilter(config.exclude, appender);
}
module.exports.configure = configure;

29
node_modules/log4js/lib/appenders/recording.js generated vendored Normal file
View File

@@ -0,0 +1,29 @@
const debug = require('debug')('log4js:recording');
const recordedEvents = [];
function configure() {
return function (logEvent) {
debug(
`received logEvent, number of events now ${recordedEvents.length + 1}`
);
debug('log event was ', logEvent);
recordedEvents.push(logEvent);
};
}
function replay() {
return recordedEvents.slice();
}
function reset() {
recordedEvents.length = 0;
}
module.exports = {
configure,
replay,
playback: replay,
reset,
erase: reset,
};

15
node_modules/log4js/lib/appenders/stderr.js generated vendored Normal file
View File

@@ -0,0 +1,15 @@
function stderrAppender(layout, timezoneOffset) {
return (loggingEvent) => {
process.stderr.write(`${layout(loggingEvent, timezoneOffset)}\n`);
};
}
function configure(config, layouts) {
let layout = layouts.colouredLayout;
if (config.layout) {
layout = layouts.layout(config.layout.type, config.layout);
}
return stderrAppender(layout, config.timezoneOffset);
}
module.exports.configure = configure;

15
node_modules/log4js/lib/appenders/stdout.js generated vendored Normal file
View File

@@ -0,0 +1,15 @@
function stdoutAppender(layout, timezoneOffset) {
return (loggingEvent) => {
process.stdout.write(`${layout(loggingEvent, timezoneOffset)}\n`);
};
}
function configure(config, layouts) {
let layout = layouts.colouredLayout;
if (config.layout) {
layout = layouts.layout(config.layout.type, config.layout);
}
return stdoutAppender(layout, config.timezoneOffset);
}
exports.configure = configure;

49
node_modules/log4js/lib/appenders/tcp-server.js generated vendored Normal file
View File

@@ -0,0 +1,49 @@
const debug = require('debug')('log4js:tcp-server');
const net = require('net');
const clustering = require('../clustering');
const LoggingEvent = require('../LoggingEvent');
const DELIMITER = '__LOG4JS__';
exports.configure = (config) => {
debug('configure called with ', config);
const server = net.createServer((socket) => {
let dataSoFar = '';
const send = (data) => {
if (data) {
dataSoFar += data;
if (dataSoFar.indexOf(DELIMITER)) {
const events = dataSoFar.split(DELIMITER);
if (!dataSoFar.endsWith(DELIMITER)) {
dataSoFar = events.pop();
} else {
dataSoFar = '';
}
events
.filter((e) => e.length)
.forEach((e) => {
clustering.send(LoggingEvent.deserialise(e));
});
} else {
dataSoFar = '';
}
}
};
socket.setEncoding('utf8');
socket.on('data', send);
socket.on('end', send);
});
server.listen(config.port || 5000, config.host || 'localhost', () => {
debug(`listening on ${config.host || 'localhost'}:${config.port || 5000}`);
server.unref();
});
return {
shutdown: (cb) => {
debug('shutdown called.');
server.close(cb);
},
};
};

92
node_modules/log4js/lib/appenders/tcp.js generated vendored Normal file
View File

@@ -0,0 +1,92 @@
const debug = require('debug')('log4js:tcp');
const net = require('net');
function appender(config, layout) {
let canWrite = false;
const buffer = [];
let socket;
let shutdownAttempts = 3;
let endMsg = '__LOG4JS__';
function write(loggingEvent) {
debug('Writing log event to socket');
canWrite = socket.write(`${layout(loggingEvent)}${endMsg}`, 'utf8');
}
function emptyBuffer() {
let evt;
debug('emptying buffer');
while ((evt = buffer.shift())) {
write(evt);
}
}
function createSocket() {
debug(
`appender creating socket to ${config.host || 'localhost'}:${
config.port || 5000
}`
);
endMsg = `${config.endMsg || '__LOG4JS__'}`;
socket = net.createConnection(
config.port || 5000,
config.host || 'localhost'
);
socket.on('connect', () => {
debug('socket connected');
emptyBuffer();
canWrite = true;
});
socket.on('drain', () => {
debug('drain event received, emptying buffer');
canWrite = true;
emptyBuffer();
});
socket.on('timeout', socket.end.bind(socket));
socket.on('error', (e) => {
debug('connection error', e);
canWrite = false;
emptyBuffer();
});
socket.on('close', createSocket);
}
createSocket();
function log(loggingEvent) {
if (canWrite) {
write(loggingEvent);
} else {
debug('buffering log event because it cannot write at the moment');
buffer.push(loggingEvent);
}
}
log.shutdown = function (cb) {
debug('shutdown called');
if (buffer.length && shutdownAttempts) {
debug('buffer has items, waiting 100ms to empty');
shutdownAttempts -= 1;
setTimeout(() => {
log.shutdown(cb);
}, 100);
} else {
socket.removeAllListeners('close');
socket.end(cb);
}
};
return log;
}
function configure(config, layouts) {
debug(`configure with config = ${config}`);
let layout = function (loggingEvent) {
return loggingEvent.serialise();
};
if (config.layout) {
layout = layouts.layout(config.layout.type, config.layout);
}
return appender(config, layout);
}
module.exports.configure = configure;

219
node_modules/log4js/lib/categories.js generated vendored Normal file
View File

@@ -0,0 +1,219 @@
const debug = require('debug')('log4js:categories');
const configuration = require('./configuration');
const levels = require('./levels');
const appenders = require('./appenders');
const categories = new Map();
/**
* Add inherited config to this category. That includes extra appenders from parent,
* and level, if none is set on this category.
* This is recursive, so each parent also gets loaded with inherited appenders.
* Inheritance is blocked if a category has inherit=false
* @param {*} config
* @param {*} category the child category
* @param {string} categoryName dotted path to category
* @return {void}
*/
function inheritFromParent(config, category, categoryName) {
if (category.inherit === false) return;
const lastDotIndex = categoryName.lastIndexOf('.');
if (lastDotIndex < 0) return; // category is not a child
const parentCategoryName = categoryName.slice(0, lastDotIndex);
let parentCategory = config.categories[parentCategoryName];
if (!parentCategory) {
// parent is missing, so implicitly create it, so that it can inherit from its parents
parentCategory = { inherit: true, appenders: [] };
}
// make sure parent has had its inheritance taken care of before pulling its properties to this child
inheritFromParent(config, parentCategory, parentCategoryName);
// if the parent is not in the config (because we just created it above),
// and it inherited a valid configuration, add it to config.categories
if (
!config.categories[parentCategoryName] &&
parentCategory.appenders &&
parentCategory.appenders.length &&
parentCategory.level
) {
config.categories[parentCategoryName] = parentCategory;
}
category.appenders = category.appenders || [];
category.level = category.level || parentCategory.level;
// merge in appenders from parent (parent is already holding its inherited appenders)
parentCategory.appenders.forEach((ap) => {
if (!category.appenders.includes(ap)) {
category.appenders.push(ap);
}
});
category.parent = parentCategory;
}
/**
* Walk all categories in the config, and pull down any configuration from parent to child.
* This includes inherited appenders, and level, where level is not set.
* Inheritance is skipped where a category has inherit=false.
* @param {*} config
*/
function addCategoryInheritance(config) {
if (!config.categories) return;
const categoryNames = Object.keys(config.categories);
categoryNames.forEach((name) => {
const category = config.categories[name];
// add inherited appenders and level to this category
inheritFromParent(config, category, name);
});
}
configuration.addPreProcessingListener((config) =>
addCategoryInheritance(config)
);
configuration.addListener((config) => {
configuration.throwExceptionIf(
config,
configuration.not(configuration.anObject(config.categories)),
'must have a property "categories" of type object.'
);
const categoryNames = Object.keys(config.categories);
configuration.throwExceptionIf(
config,
configuration.not(categoryNames.length),
'must define at least one category.'
);
categoryNames.forEach((name) => {
const category = config.categories[name];
configuration.throwExceptionIf(
config,
[
configuration.not(category.appenders),
configuration.not(category.level),
],
`category "${name}" is not valid (must be an object with properties "appenders" and "level")`
);
configuration.throwExceptionIf(
config,
configuration.not(Array.isArray(category.appenders)),
`category "${name}" is not valid (appenders must be an array of appender names)`
);
configuration.throwExceptionIf(
config,
configuration.not(category.appenders.length),
`category "${name}" is not valid (appenders must contain at least one appender name)`
);
if (Object.prototype.hasOwnProperty.call(category, 'enableCallStack')) {
configuration.throwExceptionIf(
config,
typeof category.enableCallStack !== 'boolean',
`category "${name}" is not valid (enableCallStack must be boolean type)`
);
}
category.appenders.forEach((appender) => {
configuration.throwExceptionIf(
config,
configuration.not(appenders.get(appender)),
`category "${name}" is not valid (appender "${appender}" is not defined)`
);
});
configuration.throwExceptionIf(
config,
configuration.not(levels.getLevel(category.level)),
`category "${name}" is not valid (level "${category.level}" not recognised;` +
` valid levels are ${levels.levels.join(', ')})`
);
});
configuration.throwExceptionIf(
config,
configuration.not(config.categories.default),
'must define a "default" category.'
);
});
const setup = (config) => {
categories.clear();
if (!config) {
return;
}
const categoryNames = Object.keys(config.categories);
categoryNames.forEach((name) => {
const category = config.categories[name];
const categoryAppenders = [];
category.appenders.forEach((appender) => {
categoryAppenders.push(appenders.get(appender));
debug(`Creating category ${name}`);
categories.set(name, {
appenders: categoryAppenders,
level: levels.getLevel(category.level),
enableCallStack: category.enableCallStack || false,
});
});
});
};
const init = () => {
setup();
};
init();
configuration.addListener(setup);
const configForCategory = (category) => {
debug(`configForCategory: searching for config for ${category}`);
if (categories.has(category)) {
debug(`configForCategory: ${category} exists in config, returning it`);
return categories.get(category);
}
let sourceCategoryConfig;
if (category.indexOf('.') > 0) {
debug(`configForCategory: ${category} has hierarchy, cloning from parents`);
sourceCategoryConfig = {
...configForCategory(category.slice(0, category.lastIndexOf('.'))),
};
} else {
if (!categories.has('default')) {
setup({ categories: { default: { appenders: ['out'], level: 'OFF' } } });
}
debug('configForCategory: cloning default category');
sourceCategoryConfig = { ...categories.get('default') };
}
categories.set(category, sourceCategoryConfig);
return sourceCategoryConfig;
};
const appendersForCategory = (category) =>
configForCategory(category).appenders;
const getLevelForCategory = (category) => configForCategory(category).level;
const setLevelForCategory = (category, level) => {
configForCategory(category).level = level;
};
const getEnableCallStackForCategory = (category) =>
configForCategory(category).enableCallStack === true;
const setEnableCallStackForCategory = (category, useCallStack) => {
configForCategory(category).enableCallStack = useCallStack;
};
module.exports = categories;
module.exports = Object.assign(module.exports, {
appendersForCategory,
getLevelForCategory,
setLevelForCategory,
getEnableCallStackForCategory,
setEnableCallStackForCategory,
init,
});

105
node_modules/log4js/lib/clustering.js generated vendored Normal file
View File

@@ -0,0 +1,105 @@
const debug = require('debug')('log4js:clustering');
const LoggingEvent = require('./LoggingEvent');
const configuration = require('./configuration');
let disabled = false;
let cluster = null;
try {
// eslint-disable-next-line global-require
cluster = require('cluster');
} catch (e) {
debug('cluster module not present');
disabled = true;
}
const listeners = [];
let pm2 = false;
let pm2InstanceVar = 'NODE_APP_INSTANCE';
const isPM2Master = () => pm2 && process.env[pm2InstanceVar] === '0';
const isMaster = () =>
disabled || (cluster && cluster.isMaster) || isPM2Master();
const sendToListeners = (logEvent) => {
listeners.forEach((l) => l(logEvent));
};
// in a multi-process node environment, worker loggers will use
// process.send
const receiver = (worker, message) => {
// prior to node v6, the worker parameter was not passed (args were message, handle)
debug('cluster message received from worker ', worker, ': ', message);
if (worker.topic && worker.data) {
message = worker;
worker = undefined;
}
if (message && message.topic && message.topic === 'log4js:message') {
debug('received message: ', message.data);
const logEvent = LoggingEvent.deserialise(message.data);
sendToListeners(logEvent);
}
};
if (!disabled) {
configuration.addListener((config) => {
// clear out the listeners, because configure has been called.
listeners.length = 0;
({
pm2,
disableClustering: disabled,
pm2InstanceVar = 'NODE_APP_INSTANCE',
} = config);
debug(`clustering disabled ? ${disabled}`);
debug(`cluster.isMaster ? ${cluster && cluster.isMaster}`);
debug(`pm2 enabled ? ${pm2}`);
debug(`pm2InstanceVar = ${pm2InstanceVar}`);
debug(`process.env[${pm2InstanceVar}] = ${process.env[pm2InstanceVar]}`);
// just in case configure is called after shutdown
if (pm2) {
process.removeListener('message', receiver);
}
if (cluster && cluster.removeListener) {
cluster.removeListener('message', receiver);
}
if (disabled || config.disableClustering) {
debug('Not listening for cluster messages, because clustering disabled.');
} else if (isPM2Master()) {
// PM2 cluster support
// PM2 runs everything as workers - install pm2-intercom for this to work.
// we only want one of the app instances to write logs
debug('listening for PM2 broadcast messages');
process.on('message', receiver);
} else if (cluster && cluster.isMaster) {
debug('listening for cluster messages');
cluster.on('message', receiver);
} else {
debug('not listening for messages, because we are not a master process');
}
});
}
module.exports = {
onlyOnMaster: (fn, notMaster) => (isMaster() ? fn() : notMaster),
isMaster,
send: (msg) => {
if (isMaster()) {
sendToListeners(msg);
} else {
if (!pm2) {
msg.cluster = {
workerId: cluster.worker.id,
worker: process.pid,
};
}
process.send({ topic: 'log4js:message', data: msg.serialise() });
}
},
onMessage: (listener) => {
listeners.push(listener);
},
};

19
node_modules/log4js/lib/clusteringBrowser.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
/* istanbul ignore file */
// This is used in browsers only and is designed to allow the rest of
// log4js to continue as if `clustering.js` is in use.
const isMaster = () => true;
const listeners = [];
const sendToListeners = (logEvent) => {
listeners.forEach((l) => l(logEvent));
};
module.exports = {
onlyOnMaster: (fn, notMaster) => (isMaster() ? fn() : notMaster),
isMaster,
send: sendToListeners,
onMessage: (listener) => {
listeners.push(listener);
},
};

64
node_modules/log4js/lib/configuration.js generated vendored Normal file
View File

@@ -0,0 +1,64 @@
const util = require('util');
const debug = require('debug')('log4js:configuration');
const preProcessingListeners = [];
const listeners = [];
const not = (thing) => !thing;
const anObject = (thing) =>
thing && typeof thing === 'object' && !Array.isArray(thing);
const validIdentifier = (thing) => /^[A-Za-z][A-Za-z0-9_]*$/g.test(thing);
const anInteger = (thing) =>
thing && typeof thing === 'number' && Number.isInteger(thing);
const addListener = (fn) => {
listeners.push(fn);
debug(`Added listener, now ${listeners.length} listeners`);
};
const addPreProcessingListener = (fn) => {
preProcessingListeners.push(fn);
debug(
`Added pre-processing listener, now ${preProcessingListeners.length} listeners`
);
};
const throwExceptionIf = (config, checks, message) => {
const tests = Array.isArray(checks) ? checks : [checks];
tests.forEach((test) => {
if (test) {
throw new Error(
`Problem with log4js configuration: (${util.inspect(config, {
depth: 5,
})}) - ${message}`
);
}
});
};
const configure = (candidate) => {
debug('New configuration to be validated: ', candidate);
throwExceptionIf(candidate, not(anObject(candidate)), 'must be an object.');
debug(`Calling pre-processing listeners (${preProcessingListeners.length})`);
preProcessingListeners.forEach((listener) => listener(candidate));
debug('Configuration pre-processing finished.');
debug(`Calling configuration listeners (${listeners.length})`);
listeners.forEach((listener) => listener(candidate));
debug('Configuration finished.');
};
module.exports = {
configure,
addListener,
addPreProcessingListener,
throwExceptionIf,
anObject,
anInteger,
validIdentifier,
not,
};

323
node_modules/log4js/lib/connect-logger.js generated vendored Executable file
View File

@@ -0,0 +1,323 @@
/* eslint no-underscore-dangle: ["error", { "allow": ["__statusCode", "_remoteAddress", "__headers", "_logging"] }] */
const levels = require('./levels');
const DEFAULT_FORMAT =
':remote-addr - -' +
' ":method :url HTTP/:http-version"' +
' :status :content-length ":referrer"' +
' ":user-agent"';
/**
* Return request url path,
* adding this function prevents the Cyclomatic Complexity,
* for the assemble_tokens function at low, to pass the tests.
*
* @param {IncomingMessage} req
* @return {string}
* @api private
*/
function getUrl(req) {
return req.originalUrl || req.url;
}
/**
* Adds custom {token, replacement} objects to defaults,
* overwriting the defaults if any tokens clash
*
* @param {IncomingMessage} req
* @param {ServerResponse} res
* @param {Array} customTokens
* [{ token: string-or-regexp, replacement: string-or-replace-function }]
* @return {Array}
*/
function assembleTokens(req, res, customTokens) {
const arrayUniqueTokens = (array) => {
const a = array.concat();
for (let i = 0; i < a.length; ++i) {
for (let j = i + 1; j < a.length; ++j) {
// not === because token can be regexp object
// eslint-disable-next-line eqeqeq
if (a[i].token == a[j].token) {
a.splice(j--, 1); // eslint-disable-line no-plusplus
}
}
}
return a;
};
const defaultTokens = [];
defaultTokens.push({ token: ':url', replacement: getUrl(req) });
defaultTokens.push({ token: ':protocol', replacement: req.protocol });
defaultTokens.push({ token: ':hostname', replacement: req.hostname });
defaultTokens.push({ token: ':method', replacement: req.method });
defaultTokens.push({
token: ':status',
replacement: res.__statusCode || res.statusCode,
});
defaultTokens.push({
token: ':response-time',
replacement: res.responseTime,
});
defaultTokens.push({ token: ':date', replacement: new Date().toUTCString() });
defaultTokens.push({
token: ':referrer',
replacement: req.headers.referer || req.headers.referrer || '',
});
defaultTokens.push({
token: ':http-version',
replacement: `${req.httpVersionMajor}.${req.httpVersionMinor}`,
});
defaultTokens.push({
token: ':remote-addr',
replacement:
req.headers['x-forwarded-for'] ||
req.ip ||
req._remoteAddress ||
(req.socket &&
(req.socket.remoteAddress ||
(req.socket.socket && req.socket.socket.remoteAddress))),
});
defaultTokens.push({
token: ':user-agent',
replacement: req.headers['user-agent'],
});
defaultTokens.push({
token: ':content-length',
replacement:
res.getHeader('content-length') ||
(res.__headers && res.__headers['Content-Length']) ||
'-',
});
defaultTokens.push({
token: /:req\[([^\]]+)]/g,
replacement(_, field) {
return req.headers[field.toLowerCase()];
},
});
defaultTokens.push({
token: /:res\[([^\]]+)]/g,
replacement(_, field) {
return (
res.getHeader(field.toLowerCase()) ||
(res.__headers && res.__headers[field])
);
},
});
return arrayUniqueTokens(customTokens.concat(defaultTokens));
}
/**
* Return formatted log line.
*
* @param {string} str
* @param {Array} tokens
* @return {string}
* @api private
*/
function format(str, tokens) {
for (let i = 0; i < tokens.length; i++) {
str = str.replace(tokens[i].token, tokens[i].replacement);
}
return str;
}
/**
* Return RegExp Object about nolog
*
* @param {(string|Array)} nolog
* @return {RegExp}
* @api private
*
* syntax
* 1. String
* 1.1 "\\.gif"
* NOT LOGGING http://example.com/hoge.gif and http://example.com/hoge.gif?fuga
* LOGGING http://example.com/hoge.agif
* 1.2 in "\\.gif|\\.jpg$"
* NOT LOGGING http://example.com/hoge.gif and
* http://example.com/hoge.gif?fuga and http://example.com/hoge.jpg?fuga
* LOGGING http://example.com/hoge.agif,
* http://example.com/hoge.ajpg and http://example.com/hoge.jpg?hoge
* 1.3 in "\\.(gif|jpe?g|png)$"
* NOT LOGGING http://example.com/hoge.gif and http://example.com/hoge.jpeg
* LOGGING http://example.com/hoge.gif?uid=2 and http://example.com/hoge.jpg?pid=3
* 2. RegExp
* 2.1 in /\.(gif|jpe?g|png)$/
* SAME AS 1.3
* 3. Array
* 3.1 ["\\.jpg$", "\\.png", "\\.gif"]
* SAME AS "\\.jpg|\\.png|\\.gif"
*/
function createNoLogCondition(nolog) {
let regexp = null;
if (nolog instanceof RegExp) {
regexp = nolog;
}
if (typeof nolog === 'string') {
regexp = new RegExp(nolog);
}
if (Array.isArray(nolog)) {
// convert to strings
const regexpsAsStrings = nolog.map((reg) =>
reg.source ? reg.source : reg
);
regexp = new RegExp(regexpsAsStrings.join('|'));
}
return regexp;
}
/**
* Allows users to define rules around status codes to assign them to a specific
* logging level.
* There are two types of rules:
* - RANGE: matches a code within a certain range
* E.g. { 'from': 200, 'to': 299, 'level': 'info' }
* - CONTAINS: matches a code to a set of expected codes
* E.g. { 'codes': [200, 203], 'level': 'debug' }
* Note*: Rules are respected only in order of prescendence.
*
* @param {Number} statusCode
* @param {Level} currentLevel
* @param {Object} ruleSet
* @return {Level}
* @api private
*/
function matchRules(statusCode, currentLevel, ruleSet) {
let level = currentLevel;
if (ruleSet) {
const matchedRule = ruleSet.find((rule) => {
let ruleMatched = false;
if (rule.from && rule.to) {
ruleMatched = statusCode >= rule.from && statusCode <= rule.to;
} else {
ruleMatched = rule.codes.indexOf(statusCode) !== -1;
}
return ruleMatched;
});
if (matchedRule) {
level = levels.getLevel(matchedRule.level, level);
}
}
return level;
}
/**
* Log requests with the given `options` or a `format` string.
*
* Options:
*
* - `format` Format string, see below for tokens
* - `level` A log4js levels instance. Supports also 'auto'
* - `nolog` A string or RegExp to exclude target logs or function(req, res): boolean
* - `statusRules` A array of rules for setting specific logging levels base on status codes
* - `context` Whether to add a response of express to the context
*
* Tokens:
*
* - `:req[header]` ex: `:req[Accept]`
* - `:res[header]` ex: `:res[Content-Length]`
* - `:http-version`
* - `:response-time`
* - `:remote-addr`
* - `:date`
* - `:method`
* - `:url`
* - `:referrer`
* - `:user-agent`
* - `:status`
*
* @return {Function}
* @param logger4js
* @param options
* @api public
*/
module.exports = function getLogger(logger4js, options) {
if (typeof options === 'string' || typeof options === 'function') {
options = { format: options };
} else {
options = options || {};
}
const thisLogger = logger4js;
let level = levels.getLevel(options.level, levels.INFO);
const fmt = options.format || DEFAULT_FORMAT;
return (req, res, next) => {
// mount safety
if (typeof req._logging !== 'undefined') return next();
// nologs
if (typeof options.nolog !== 'function') {
const nolog = createNoLogCondition(options.nolog);
if (nolog && nolog.test(req.originalUrl)) return next();
}
if (thisLogger.isLevelEnabled(level) || options.level === 'auto') {
const start = new Date();
const { writeHead } = res;
// flag as logging
req._logging = true;
// proxy for statusCode.
res.writeHead = (code, headers) => {
res.writeHead = writeHead;
res.writeHead(code, headers);
res.__statusCode = code;
res.__headers = headers || {};
};
// hook on end request to emit the log entry of the HTTP request.
let finished = false;
const handler = () => {
if (finished) {
return;
}
finished = true;
// nologs
if (typeof options.nolog === 'function') {
if (options.nolog(req, res) === true) {
req._logging = false;
return;
}
}
res.responseTime = new Date() - start;
// status code response level handling
if (res.statusCode && options.level === 'auto') {
level = levels.INFO;
if (res.statusCode >= 300) level = levels.WARN;
if (res.statusCode >= 400) level = levels.ERROR;
}
level = matchRules(res.statusCode, level, options.statusRules);
const combinedTokens = assembleTokens(req, res, options.tokens || []);
if (options.context) thisLogger.addContext('res', res);
if (typeof fmt === 'function') {
const line = fmt(req, res, (str) => format(str, combinedTokens));
if (line) thisLogger.log(level, line);
} else {
thisLogger.log(level, format(fmt, combinedTokens));
}
if (options.context) thisLogger.removeContext('res');
};
res.on('end', handler);
res.on('finish', handler);
res.on('error', handler);
res.on('close', handler);
}
// ensure next gets always called
return next();
};
};

486
node_modules/log4js/lib/layouts.js generated vendored Normal file
View File

@@ -0,0 +1,486 @@
const dateFormat = require('date-format');
const os = require('os');
const util = require('util');
const path = require('path');
const url = require('url');
const debug = require('debug')('log4js:layouts');
const styles = {
// styles
bold: [1, 22],
italic: [3, 23],
underline: [4, 24],
inverse: [7, 27],
// grayscale
white: [37, 39],
grey: [90, 39],
black: [90, 39],
// colors
blue: [34, 39],
cyan: [36, 39],
green: [32, 39],
magenta: [35, 39],
red: [91, 39],
yellow: [33, 39],
};
function colorizeStart(style) {
return style ? `\x1B[${styles[style][0]}m` : '';
}
function colorizeEnd(style) {
return style ? `\x1B[${styles[style][1]}m` : '';
}
/**
* Taken from masylum's fork (https://github.com/masylum/log4js-node)
*/
function colorize(str, style) {
return colorizeStart(style) + str + colorizeEnd(style);
}
function timestampLevelAndCategory(loggingEvent, colour) {
return colorize(
util.format(
'[%s] [%s] %s - ',
dateFormat.asString(loggingEvent.startTime),
loggingEvent.level.toString(),
loggingEvent.categoryName
),
colour
);
}
/**
* BasicLayout is a simple layout for storing the logs. The logs are stored
* in following format:
* <pre>
* [startTime] [logLevel] categoryName - message\n
* </pre>
*
* @author Stephan Strittmatter
*/
function basicLayout(loggingEvent) {
return (
timestampLevelAndCategory(loggingEvent) + util.format(...loggingEvent.data)
);
}
/**
* colouredLayout - taken from masylum's fork.
* same as basicLayout, but with colours.
*/
function colouredLayout(loggingEvent) {
return (
timestampLevelAndCategory(loggingEvent, loggingEvent.level.colour) +
util.format(...loggingEvent.data)
);
}
function messagePassThroughLayout(loggingEvent) {
return util.format(...loggingEvent.data);
}
function dummyLayout(loggingEvent) {
return loggingEvent.data[0];
}
/**
* PatternLayout
* Format for specifiers is %[padding].[truncation][field]{[format]}
* e.g. %5.10p - left pad the log level by 5 characters, up to a max of 10
* both padding and truncation can be negative.
* Negative truncation = trunc from end of string
* Positive truncation = trunc from start of string
* Negative padding = pad right
* Positive padding = pad left
*
* Fields can be any of:
* - %r time in toLocaleTimeString format
* - %p log level
* - %c log category
* - %h hostname
* - %m log data
* - %m{l} where l is an integer, log data.slice(l)
* - %m{l,u} where l and u are integers, log data.slice(l, u)
* - %d date in constious formats
* - %% %
* - %n newline
* - %z pid
* - %f filename
* - %l line number
* - %o column postion
* - %s call stack
* - %C class name [#1316](https://github.com/log4js-node/log4js-node/pull/1316)
* - %M method or function name [#1316](https://github.com/log4js-node/log4js-node/pull/1316)
* - %A method or function alias [#1316](https://github.com/log4js-node/log4js-node/pull/1316)
* - %F fully qualified caller name [#1316](https://github.com/log4js-node/log4js-node/pull/1316)
* - %x{<tokenname>} add dynamic tokens to your log. Tokens are specified in the tokens parameter
* - %X{<tokenname>} add dynamic tokens to your log. Tokens are specified in logger context
* You can use %[ and %] to define a colored block.
*
* Tokens are specified as simple key:value objects.
* The key represents the token name whereas the value can be a string or function
* which is called to extract the value to put in the log message. If token is not
* found, it doesn't replace the field.
*
* A sample token would be: { 'pid' : function() { return process.pid; } }
*
* Takes a pattern string, array of tokens and returns a layout function.
* @return {Function}
* @param pattern
* @param tokens
* @param timezoneOffset
*
* @authors ['Stephan Strittmatter', 'Jan Schmidle']
*/
function patternLayout(pattern, tokens) {
const TTCC_CONVERSION_PATTERN = '%r %p %c - %m%n';
const regex =
/%(-?[0-9]+)?(\.?-?[0-9]+)?([[\]cdhmnprzxXyflosCMAF%])(\{([^}]+)\})?|([^%]+)/;
pattern = pattern || TTCC_CONVERSION_PATTERN;
function categoryName(loggingEvent, specifier) {
let loggerName = loggingEvent.categoryName;
if (specifier) {
const precision = parseInt(specifier, 10);
const loggerNameBits = loggerName.split('.');
if (precision < loggerNameBits.length) {
loggerName = loggerNameBits
.slice(loggerNameBits.length - precision)
.join('.');
}
}
return loggerName;
}
function formatAsDate(loggingEvent, specifier) {
let format = dateFormat.ISO8601_FORMAT;
if (specifier) {
format = specifier;
// Pick up special cases
switch (format) {
case 'ISO8601':
case 'ISO8601_FORMAT':
format = dateFormat.ISO8601_FORMAT;
break;
case 'ISO8601_WITH_TZ_OFFSET':
case 'ISO8601_WITH_TZ_OFFSET_FORMAT':
format = dateFormat.ISO8601_WITH_TZ_OFFSET_FORMAT;
break;
case 'ABSOLUTE':
process.emitWarning(
'Pattern %d{ABSOLUTE} is deprecated in favor of %d{ABSOLUTETIME}. ' +
'Please use %d{ABSOLUTETIME} instead.',
'DeprecationWarning',
'log4js-node-DEP0003'
);
debug(
'[log4js-node-DEP0003]',
'DEPRECATION: Pattern %d{ABSOLUTE} is deprecated and replaced by %d{ABSOLUTETIME}.'
);
// falls through
case 'ABSOLUTETIME':
case 'ABSOLUTETIME_FORMAT':
format = dateFormat.ABSOLUTETIME_FORMAT;
break;
case 'DATE':
process.emitWarning(
'Pattern %d{DATE} is deprecated due to the confusion it causes when used. ' +
'Please use %d{DATETIME} instead.',
'DeprecationWarning',
'log4js-node-DEP0004'
);
debug(
'[log4js-node-DEP0004]',
'DEPRECATION: Pattern %d{DATE} is deprecated and replaced by %d{DATETIME}.'
);
// falls through
case 'DATETIME':
case 'DATETIME_FORMAT':
format = dateFormat.DATETIME_FORMAT;
break;
// no default
}
}
// Format the date
return dateFormat.asString(format, loggingEvent.startTime);
}
function hostname() {
return os.hostname().toString();
}
function formatMessage(loggingEvent, specifier) {
let dataSlice = loggingEvent.data;
if (specifier) {
const [lowerBound, upperBound] = specifier.split(',');
dataSlice = dataSlice.slice(lowerBound, upperBound);
}
return util.format(...dataSlice);
}
function endOfLine() {
return os.EOL;
}
function logLevel(loggingEvent) {
return loggingEvent.level.toString();
}
function startTime(loggingEvent) {
return dateFormat.asString('hh:mm:ss', loggingEvent.startTime);
}
function startColour(loggingEvent) {
return colorizeStart(loggingEvent.level.colour);
}
function endColour(loggingEvent) {
return colorizeEnd(loggingEvent.level.colour);
}
function percent() {
return '%';
}
function pid(loggingEvent) {
return loggingEvent && loggingEvent.pid
? loggingEvent.pid.toString()
: process.pid.toString();
}
function clusterInfo() {
// this used to try to return the master and worker pids,
// but it would never have worked because master pid is not available to workers
// leaving this here to maintain compatibility for patterns
return pid();
}
function userDefined(loggingEvent, specifier) {
if (typeof tokens[specifier] !== 'undefined') {
return typeof tokens[specifier] === 'function'
? tokens[specifier](loggingEvent)
: tokens[specifier];
}
return null;
}
function contextDefined(loggingEvent, specifier) {
const resolver = loggingEvent.context[specifier];
if (typeof resolver !== 'undefined') {
return typeof resolver === 'function' ? resolver(loggingEvent) : resolver;
}
return null;
}
function fileName(loggingEvent, specifier) {
let filename = loggingEvent.fileName || '';
// support for ESM as it uses url instead of path for file
/* istanbul ignore next: unsure how to simulate ESM for test coverage */
const convertFileURLToPath = function (filepath) {
const urlPrefix = 'file://';
if (filepath.startsWith(urlPrefix)) {
// https://nodejs.org/api/url.html#urlfileurltopathurl
if (typeof url.fileURLToPath === 'function') {
filepath = url.fileURLToPath(filepath);
}
// backward-compatible for nodejs pre-10.12.0 (without url.fileURLToPath method)
else {
// posix: file:///hello/world/foo.txt -> /hello/world/foo.txt -> /hello/world/foo.txt
// win32: file:///C:/path/foo.txt -> /C:/path/foo.txt -> \C:\path\foo.txt -> C:\path\foo.txt
// win32: file://nas/foo.txt -> //nas/foo.txt -> nas\foo.txt -> \\nas\foo.txt
filepath = path.normalize(
filepath.replace(new RegExp(`^${urlPrefix}`), '')
);
if (process.platform === 'win32') {
if (filepath.startsWith('\\')) {
filepath = filepath.slice(1);
} else {
filepath = path.sep + path.sep + filepath;
}
}
}
}
return filepath;
};
filename = convertFileURLToPath(filename);
if (specifier) {
const fileDepth = parseInt(specifier, 10);
const fileList = filename.split(path.sep);
if (fileList.length > fileDepth) {
filename = fileList.slice(-fileDepth).join(path.sep);
}
}
return filename;
}
function lineNumber(loggingEvent) {
return loggingEvent.lineNumber ? `${loggingEvent.lineNumber}` : '';
}
function columnNumber(loggingEvent) {
return loggingEvent.columnNumber ? `${loggingEvent.columnNumber}` : '';
}
function callStack(loggingEvent) {
return loggingEvent.callStack || '';
}
function className(loggingEvent) {
return loggingEvent.className || '';
}
function functionName(loggingEvent) {
return loggingEvent.functionName || '';
}
function functionAlias(loggingEvent) {
return loggingEvent.functionAlias || '';
}
function callerName(loggingEvent) {
return loggingEvent.callerName || '';
}
const replacers = {
c: categoryName,
d: formatAsDate,
h: hostname,
m: formatMessage,
n: endOfLine,
p: logLevel,
r: startTime,
'[': startColour,
']': endColour,
y: clusterInfo,
z: pid,
'%': percent,
x: userDefined,
X: contextDefined,
f: fileName,
l: lineNumber,
o: columnNumber,
s: callStack,
C: className,
M: functionName,
A: functionAlias,
F: callerName,
};
function replaceToken(conversionCharacter, loggingEvent, specifier) {
return replacers[conversionCharacter](loggingEvent, specifier);
}
function truncate(truncation, toTruncate) {
let len;
if (truncation) {
len = parseInt(truncation.slice(1), 10);
// negative truncate length means truncate from end of string
return len > 0 ? toTruncate.slice(0, len) : toTruncate.slice(len);
}
return toTruncate;
}
function pad(padding, toPad) {
let len;
if (padding) {
if (padding.charAt(0) === '-') {
len = parseInt(padding.slice(1), 10);
// Right pad with spaces
while (toPad.length < len) {
toPad += ' ';
}
} else {
len = parseInt(padding, 10);
// Left pad with spaces
while (toPad.length < len) {
toPad = ` ${toPad}`;
}
}
}
return toPad;
}
function truncateAndPad(toTruncAndPad, truncation, padding) {
let replacement = toTruncAndPad;
replacement = truncate(truncation, replacement);
replacement = pad(padding, replacement);
return replacement;
}
return function (loggingEvent) {
let formattedString = '';
let result;
let searchString = pattern;
while ((result = regex.exec(searchString)) !== null) {
// const matchedString = result[0];
const padding = result[1];
const truncation = result[2];
const conversionCharacter = result[3];
const specifier = result[5];
const text = result[6];
// Check if the pattern matched was just normal text
if (text) {
formattedString += text.toString();
} else {
// Create a raw replacement string based on the conversion
// character and specifier
const replacement = replaceToken(
conversionCharacter,
loggingEvent,
specifier
);
formattedString += truncateAndPad(replacement, truncation, padding);
}
searchString = searchString.slice(result.index + result[0].length);
}
return formattedString;
};
}
const layoutMakers = {
messagePassThrough() {
return messagePassThroughLayout;
},
basic() {
return basicLayout;
},
colored() {
return colouredLayout;
},
coloured() {
return colouredLayout;
},
pattern(config) {
return patternLayout(config && config.pattern, config && config.tokens);
},
dummy() {
return dummyLayout;
},
};
module.exports = {
basicLayout,
messagePassThroughLayout,
patternLayout,
colouredLayout,
coloredLayout: colouredLayout,
dummyLayout,
addLayout(name, serializerGenerator) {
layoutMakers[name] = serializerGenerator;
},
layout(name, config) {
return layoutMakers[name] && layoutMakers[name](config);
},
};

155
node_modules/log4js/lib/levels.js generated vendored Normal file
View File

@@ -0,0 +1,155 @@
const configuration = require('./configuration');
const validColours = [
'white',
'grey',
'black',
'blue',
'cyan',
'green',
'magenta',
'red',
'yellow',
];
class Level {
constructor(level, levelStr, colour) {
this.level = level;
this.levelStr = levelStr;
this.colour = colour;
}
toString() {
return this.levelStr;
}
/**
* converts given String to corresponding Level
* @param {(Level|string)} sArg -- String value of Level OR Log4js.Level
* @param {Level} [defaultLevel] -- default Level, if no String representation
* @return {Level}
*/
static getLevel(sArg, defaultLevel) {
if (!sArg) {
return defaultLevel;
}
if (sArg instanceof Level) {
return sArg;
}
// a json-serialised level won't be an instance of Level (see issue #768)
if (sArg instanceof Object && sArg.levelStr) {
sArg = sArg.levelStr;
}
return Level[sArg.toString().toUpperCase()] || defaultLevel;
}
static addLevels(customLevels) {
if (customLevels) {
const levels = Object.keys(customLevels);
levels.forEach((l) => {
const levelStr = l.toUpperCase();
Level[levelStr] = new Level(
customLevels[l].value,
levelStr,
customLevels[l].colour
);
const existingLevelIndex = Level.levels.findIndex(
(lvl) => lvl.levelStr === levelStr
);
if (existingLevelIndex > -1) {
Level.levels[existingLevelIndex] = Level[levelStr];
} else {
Level.levels.push(Level[levelStr]);
}
});
Level.levels.sort((a, b) => a.level - b.level);
}
}
isLessThanOrEqualTo(otherLevel) {
if (typeof otherLevel === 'string') {
otherLevel = Level.getLevel(otherLevel);
}
return this.level <= otherLevel.level;
}
isGreaterThanOrEqualTo(otherLevel) {
if (typeof otherLevel === 'string') {
otherLevel = Level.getLevel(otherLevel);
}
return this.level >= otherLevel.level;
}
isEqualTo(otherLevel) {
if (typeof otherLevel === 'string') {
otherLevel = Level.getLevel(otherLevel);
}
return this.level === otherLevel.level;
}
}
Level.levels = [];
Level.addLevels({
ALL: { value: Number.MIN_VALUE, colour: 'grey' },
TRACE: { value: 5000, colour: 'blue' },
DEBUG: { value: 10000, colour: 'cyan' },
INFO: { value: 20000, colour: 'green' },
WARN: { value: 30000, colour: 'yellow' },
ERROR: { value: 40000, colour: 'red' },
FATAL: { value: 50000, colour: 'magenta' },
MARK: { value: 9007199254740992, colour: 'grey' }, // 2^53
OFF: { value: Number.MAX_VALUE, colour: 'grey' },
});
configuration.addListener((config) => {
const levelConfig = config.levels;
if (levelConfig) {
configuration.throwExceptionIf(
config,
configuration.not(configuration.anObject(levelConfig)),
'levels must be an object'
);
const newLevels = Object.keys(levelConfig);
newLevels.forEach((l) => {
configuration.throwExceptionIf(
config,
configuration.not(configuration.validIdentifier(l)),
`level name "${l}" is not a valid identifier (must start with a letter, only contain A-Z,a-z,0-9,_)`
);
configuration.throwExceptionIf(
config,
configuration.not(configuration.anObject(levelConfig[l])),
`level "${l}" must be an object`
);
configuration.throwExceptionIf(
config,
configuration.not(levelConfig[l].value),
`level "${l}" must have a 'value' property`
);
configuration.throwExceptionIf(
config,
configuration.not(configuration.anInteger(levelConfig[l].value)),
`level "${l}".value must have an integer value`
);
configuration.throwExceptionIf(
config,
configuration.not(levelConfig[l].colour),
`level "${l}" must have a 'colour' property`
);
configuration.throwExceptionIf(
config,
configuration.not(validColours.indexOf(levelConfig[l].colour) > -1),
`level "${l}".colour must be one of ${validColours.join(', ')}`
);
});
}
});
configuration.addListener((config) => {
Level.addLevels(config.levels);
});
module.exports = Level;

186
node_modules/log4js/lib/log4js.js generated vendored Normal file
View File

@@ -0,0 +1,186 @@
/**
* @fileoverview log4js is a library to log in JavaScript in similar manner
* than in log4j for Java (but not really).
*
* <h3>Example:</h3>
* <pre>
* const logging = require('log4js');
* const log = logging.getLogger('some-category');
*
* //call the log
* log.trace('trace me' );
* </pre>
*
* NOTE: the authors below are the original browser-based log4js authors
* don't try to contact them about bugs in this version :)
* @author Stephan Strittmatter - http://jroller.com/page/stritti
* @author Seth Chisamore - http://www.chisamore.com
* @since 2005-05-20
* Website: http://log4js.berlios.de
*/
const debug = require('debug')('log4js:main');
const fs = require('fs');
const deepClone = require('rfdc')({ proto: true });
const configuration = require('./configuration');
const layouts = require('./layouts');
const levels = require('./levels');
const appenders = require('./appenders');
const categories = require('./categories');
const Logger = require('./logger');
const clustering = require('./clustering');
const connectLogger = require('./connect-logger');
const recordingModule = require('./appenders/recording');
let enabled = false;
function sendLogEventToAppender(logEvent) {
if (!enabled) return;
debug('Received log event ', logEvent);
const categoryAppenders = categories.appendersForCategory(
logEvent.categoryName
);
categoryAppenders.forEach((appender) => {
appender(logEvent);
});
}
function loadConfigurationFile(filename) {
debug(`Loading configuration from ${filename}`);
try {
return JSON.parse(fs.readFileSync(filename, 'utf8'));
} catch (e) {
throw new Error(
`Problem reading config from file "${filename}". Error was ${e.message}`,
e
);
}
}
function configure(configurationFileOrObject) {
if (enabled) {
// eslint-disable-next-line no-use-before-define
shutdown();
}
let configObject = configurationFileOrObject;
if (typeof configObject === 'string') {
configObject = loadConfigurationFile(configurationFileOrObject);
}
debug(`Configuration is ${configObject}`);
configuration.configure(deepClone(configObject));
clustering.onMessage(sendLogEventToAppender);
enabled = true;
// eslint-disable-next-line no-use-before-define
return log4js;
}
function isConfigured() {
return enabled;
}
function recording() {
return recordingModule;
}
/**
* This callback type is called `shutdownCallback` and is displayed as a global symbol.
*
* @callback shutdownCallback
* @param {Error} [error]
*/
/**
* Shutdown all log appenders. This will first disable all writing to appenders
* and then call the shutdown function each appender.
*
* @param {shutdownCallback} [callback] - The callback to be invoked once all appenders have
* shutdown. If an error occurs, the callback will be given the error object
* as the first argument.
*/
function shutdown(callback = () => {}) {
if (typeof callback !== 'function') {
throw new TypeError('Invalid callback passed to shutdown');
}
debug('Shutdown called. Disabling all log writing.');
// First, disable all writing to appenders. This prevents appenders from
// not being able to be drained because of run-away log writes.
enabled = false;
// Clone out to maintain a reference
const appendersToCheck = Array.from(appenders.values());
// Reset immediately to prevent leaks
appenders.init();
categories.init();
// Count the number of shutdown functions
const shutdownFunctions = appendersToCheck.reduce(
(accum, next) => (next.shutdown ? accum + 1 : accum),
0
);
if (shutdownFunctions === 0) {
debug('No appenders with shutdown functions found.');
callback();
}
let completed = 0;
let error;
debug(`Found ${shutdownFunctions} appenders with shutdown functions.`);
function complete(err) {
error = error || err;
completed += 1;
debug(`Appender shutdowns complete: ${completed} / ${shutdownFunctions}`);
if (completed >= shutdownFunctions) {
debug('All shutdown functions completed.');
callback(error);
}
}
// Call each of the shutdown functions
appendersToCheck
.filter((a) => a.shutdown)
.forEach((a) => a.shutdown(complete));
}
/**
* Get a logger instance.
* @static
* @param {string} [category=default]
* @return {Logger} instance of logger for the category
*/
function getLogger(category) {
if (!enabled) {
configure(
process.env.LOG4JS_CONFIG || {
appenders: { out: { type: 'stdout' } },
categories: { default: { appenders: ['out'], level: 'OFF' } },
}
);
}
return new Logger(category || 'default');
}
/**
* @name log4js
* @namespace Log4js
* @property getLogger
* @property configure
* @property shutdown
*/
const log4js = {
getLogger,
configure,
isConfigured,
shutdown,
connectLogger,
levels,
addLayout: layouts.addLayout,
recording,
};
module.exports = log4js;

245
node_modules/log4js/lib/logger.js generated vendored Normal file
View File

@@ -0,0 +1,245 @@
/* eslint no-underscore-dangle: ["error", { "allow": ["_log"] }] */
const debug = require('debug')('log4js:logger');
const LoggingEvent = require('./LoggingEvent');
const levels = require('./levels');
const clustering = require('./clustering');
const categories = require('./categories');
const configuration = require('./configuration');
const stackReg = /^(?:\s*)at (?:(.+) \()?(?:([^(]+?):(\d+):(\d+))\)?$/;
/**
* The top entry is the Error
*/
const baseCallStackSkip = 1;
/**
* The _log function is 3 levels deep, we need to skip those to make it to the callSite
*/
const defaultErrorCallStackSkip = 3;
/**
*
* @param {Error} data
* @param {number} skipIdx
* @returns {import('../types/log4js').CallStack | null}
*/
function defaultParseCallStack(
data,
skipIdx = defaultErrorCallStackSkip + baseCallStackSkip
) {
try {
const stacklines = data.stack.split('\n').slice(skipIdx);
if (!stacklines.length) {
// There's no stack in this stack
// Should we try a previous index if skipIdx was set?
return null;
}
const lineMatch = stackReg.exec(stacklines[0]);
/* istanbul ignore else: failsafe */
if (lineMatch && lineMatch.length === 5) {
// extract class, function and alias names
let className = '';
let functionName = '';
let functionAlias = '';
if (lineMatch[1] && lineMatch[1] !== '') {
// WARN: this will unset alias if alias is not present.
[functionName, functionAlias] = lineMatch[1]
.replace(/[[\]]/g, '')
.split(' as ');
functionAlias = functionAlias || '';
if (functionName.includes('.'))
[className, functionName] = functionName.split('.');
}
return {
fileName: lineMatch[2],
lineNumber: parseInt(lineMatch[3], 10),
columnNumber: parseInt(lineMatch[4], 10),
callStack: stacklines.join('\n'),
className,
functionName,
functionAlias,
callerName: lineMatch[1] || '',
};
// eslint-disable-next-line no-else-return
} else {
// will never get here unless nodejs has changes to Error
console.error('log4js.logger - defaultParseCallStack error'); // eslint-disable-line no-console
}
} catch (err) {
// will never get error unless nodejs has breaking changes to Error
console.error('log4js.logger - defaultParseCallStack error', err); // eslint-disable-line no-console
}
return null;
}
/**
* Logger to log messages.
* use {@see log4js#getLogger(String)} to get an instance.
*
* @name Logger
* @namespace Log4js
* @param name name of category to log to
* @param level - the loglevel for the category
* @param dispatch - the function which will receive the logevents
*
* @author Stephan Strittmatter
*/
class Logger {
constructor(name) {
if (!name) {
throw new Error('No category provided.');
}
this.category = name;
this.context = {};
/** @private */
this.callStackSkipIndex = 0;
/** @private */
this.parseCallStack = defaultParseCallStack;
debug(`Logger created (${this.category}, ${this.level})`);
}
get level() {
return levels.getLevel(
categories.getLevelForCategory(this.category),
levels.OFF
);
}
set level(level) {
categories.setLevelForCategory(
this.category,
levels.getLevel(level, this.level)
);
}
get useCallStack() {
return categories.getEnableCallStackForCategory(this.category);
}
set useCallStack(bool) {
categories.setEnableCallStackForCategory(this.category, bool === true);
}
get callStackLinesToSkip() {
return this.callStackSkipIndex;
}
set callStackLinesToSkip(number) {
if (typeof number !== 'number') {
throw new TypeError('Must be a number');
}
if (number < 0) {
throw new RangeError('Must be >= 0');
}
this.callStackSkipIndex = number;
}
log(level, ...args) {
const logLevel = levels.getLevel(level);
if (!logLevel) {
if (configuration.validIdentifier(level) && args.length > 0) {
// logLevel not found but of valid signature, WARN before fallback to INFO
this.log(
levels.WARN,
'log4js:logger.log: valid log-level not found as first parameter given:',
level
);
this.log(levels.INFO, `[${level}]`, ...args);
} else {
// apart from fallback, allow .log(...args) to be synonym with .log("INFO", ...args)
this.log(levels.INFO, level, ...args);
}
} else if (this.isLevelEnabled(logLevel)) {
this._log(logLevel, args);
}
}
isLevelEnabled(otherLevel) {
return this.level.isLessThanOrEqualTo(otherLevel);
}
_log(level, data) {
debug(`sending log data (${level}) to appenders`);
const error = data.find((item) => item instanceof Error);
let callStack;
if (this.useCallStack) {
try {
if (error) {
callStack = this.parseCallStack(
error,
this.callStackSkipIndex + baseCallStackSkip
);
}
} catch (_err) {
// Ignore Error and use the original method of creating a new Error.
}
callStack =
callStack ||
this.parseCallStack(
new Error(),
this.callStackSkipIndex +
defaultErrorCallStackSkip +
baseCallStackSkip
);
}
const loggingEvent = new LoggingEvent(
this.category,
level,
data,
this.context,
callStack,
error
);
clustering.send(loggingEvent);
}
addContext(key, value) {
this.context[key] = value;
}
removeContext(key) {
delete this.context[key];
}
clearContext() {
this.context = {};
}
setParseCallStackFunction(parseFunction) {
if (typeof parseFunction === 'function') {
this.parseCallStack = parseFunction;
} else if (typeof parseFunction === 'undefined') {
this.parseCallStack = defaultParseCallStack;
} else {
throw new TypeError('Invalid type passed to setParseCallStackFunction');
}
}
}
function addLevelMethods(target) {
const level = levels.getLevel(target);
const levelStrLower = level.toString().toLowerCase();
const levelMethod = levelStrLower.replace(/_([a-z])/g, (g) =>
g[1].toUpperCase()
);
const isLevelMethod = levelMethod[0].toUpperCase() + levelMethod.slice(1);
Logger.prototype[`is${isLevelMethod}Enabled`] = function () {
return this.isLevelEnabled(level);
};
Logger.prototype[levelMethod] = function (...args) {
this.log(level, ...args);
};
}
levels.levels.forEach(addLevelMethods);
configuration.addListener(() => {
levels.levels.forEach(addLevelMethods);
});
module.exports = Logger;