Compare commits

..

2 Commits

Author SHA1 Message Date
Fabian Stamm
9182efe7e7 Fixing some problems with the adapter API 2020-04-09 18:00:59 +02:00
Fabian Stamm
94d9731cdd Running everything through prettier 2020-04-09 17:50:30 +02:00
7 changed files with 605 additions and 538 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@hibas123/logging", "name": "@hibas123/logging",
"version": "2.2.2", "version": "2.3.0",
"description": "", "description": "",
"main": "out/index.js", "main": "out/index.js",
"types": "out/index.d.ts", "types": "out/index.d.ts",

View File

@ -21,7 +21,7 @@ Logging.error("Just an simple message as error")
Logging.errorMessage("Nearly the same as error") Logging.errorMessage("Nearly the same as error")
``` ```
All Logging types except the simple error take as many arguments as you want. These will be joined with spaces and serialized with the node util.inspect function. All Logging types except the simple error take as many arguments as you want. These will be joined with spaces and serialized with the node util.inspect function.
# Setup # Setup
@ -81,7 +81,7 @@ The `ObservableInterface` comes from `@hibas123/utils`. It provides a very simpl
More Details on Observable [git](https://git.stamm.me/OpenServer/Utils) or [npm](https://www.npmjs.com/package/@hibas123/utils) More Details on Observable [git](https://git.stamm.me/OpenServer/Utils) or [npm](https://www.npmjs.com/package/@hibas123/utils)
# License # License
MIT MIT
Copyright (c) 2018 Fabian Stamm Copyright (c) 2018 Fabian Stamm
@ -90,4 +90,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -42,6 +42,7 @@ export interface LoggingBaseOptions {
console: boolean; console: boolean;
} }
const adapterCache = new WeakMap<Adapter, number>();
export class LoggingBase { export class LoggingBase {
private _formatMap: FormatConfig = new DefaultFormatConfig(); private _formatMap: FormatConfig = new DefaultFormatConfig();
@ -110,8 +111,12 @@ export class LoggingBase {
addAdapter(adapter: Adapter) { addAdapter(adapter: Adapter) {
if (!this.adapter.has(adapter)) { if (!this.adapter.has(adapter)) {
this.adapter.add(adapter); this.adapter.add(adapter);
let cached = adapterCache.get(adapter) || 0;
adapterCache.set(adapter, cached + 1);
let prms = Promise.resolve( let prms = Promise.resolve(
adapter.init(this.messageObservable.getPublicApi(), this._name) adapter.init(this.messageObservable.getPublicApi())
); );
this.adapter_init.push(prms); this.adapter_init.push(prms);
} }
@ -129,10 +134,29 @@ export class LoggingBase {
} }
} }
private $closed = false;
public close() { public close() {
this.adapter.forEach((adapter) => if (this.$closed) return;
adapter.close ? adapter.close() : undefined this.$closed = true;
);
this.adapter.forEach((adapter) => {
let cached = adapterCache.get(adapter);
if (cached) {
cached--;
if (cached <= 0) {
adapterCache.delete(adapter);
adapter.close();
} else adapterCache.set(adapter, cached);
}
adapter.close ? adapter.close() : undefined;
});
this.adapter = undefined;
this.messageObservable.close();
} }
public waitForSetup() { public waitForSetup() {
@ -234,6 +258,8 @@ export class LoggingBase {
message: any[], message: any[],
caller?: { file: string; line: number } caller?: { file: string; line: number }
) { ) {
if (this.$closed) return;
let date = new Date().toISOString().replace(/T/, " ").replace(/\..+/, ""); let date = new Date().toISOString().replace(/T/, " ").replace(/\..+/, "");
let file_raw = caller || getCallerFile(); let file_raw = caller || getCallerFile();

View File

@ -1,166 +1,154 @@
import { ObservableInterface } from "@hibas123/utils"; import { ObservableInterface } from "@hibas123/utils";
import { Colors } from "./index"; import { Colors } from "./index";
import { import {
<<<<<<< HEAD
Adapter,
Message,
FormattedLine,
TerminalFormats,
FormatTypes
=======
Adapter, Adapter,
Message, Message,
FormattedLine, FormattedLine,
TerminalFormats, TerminalFormats,
FormatTypes, FormatTypes,
>>>>>>> facb7e7b403e1dfaa8790426259e6effb0618efb
} from "./types"; } from "./types";
const browser = typeof window !== "undefined"; const browser = typeof window !== "undefined";
export class ConsoleAdapter implements Adapter { export class ConsoleAdapter implements Adapter {
init(observable: ObservableInterface<Message>) { init(observable: ObservableInterface<Message>) {
observable.subscribe(this.onMessage.bind(this)); observable.subscribe(this.onMessage.bind(this));
} }
<<<<<<< HEAD
flush() {}
=======
flush() {} flush() {}
>>>>>>> facb7e7b403e1dfaa8790426259e6effb0618efb
// TODO: Check if required! // TODO: Check if required!
// private escape(text: string): string { // private escape(text: string): string {
// return text // return text
// .replace(/%s/g, "%%s") // .replace(/%s/g, "%%s")
// .replace(/%c/g, "%%c") // .replace(/%c/g, "%%c")
// } // }
private formatLine(line: FormattedLine): [string, string[] | undefined] { private formatLine(line: FormattedLine): [string, string[] | undefined] {
let text = ""; let text = "";
let style_formats: string[] = []; let style_formats: string[] = [];
if (!browser) { if (!browser) {
for (let part of line) { for (let part of line) {
let formats = ""; let formats = "";
for (let format of part.formats) { for (let format of part.formats) {
switch (format.type) { switch (format.type) {
case FormatTypes.BOLD: case FormatTypes.BOLD:
formats += TerminalFormats.Bold; formats += TerminalFormats.Bold;
break; break;
case FormatTypes.UNDERSCORE: case FormatTypes.UNDERSCORE:
formats += TerminalFormats.Underscore; formats += TerminalFormats.Underscore;
break; break;
case FormatTypes.BLINK: case FormatTypes.BLINK:
formats += TerminalFormats.Blink; formats += TerminalFormats.Blink;
break; break;
case FormatTypes.COLOR: case FormatTypes.COLOR:
switch (format.color) { switch (format.color) {
case Colors.RED: case Colors.RED:
formats += TerminalFormats.FgRed; formats += TerminalFormats.FgRed;
break; break;
case Colors.GREEN: case Colors.GREEN:
formats += TerminalFormats.FgGreen; formats += TerminalFormats.FgGreen;
break; break;
case Colors.YELLOW: case Colors.YELLOW:
formats += TerminalFormats.FgYellow; formats += TerminalFormats.FgYellow;
break; break;
case Colors.BLUE: case Colors.BLUE:
formats += TerminalFormats.FgBlue; formats += TerminalFormats.FgBlue;
break; break;
case Colors.MAGENTA: case Colors.MAGENTA:
formats += TerminalFormats.FgMagenta; formats += TerminalFormats.FgMagenta;
break; break;
case Colors.CYAN: case Colors.CYAN:
formats += TerminalFormats.FgCyan; formats += TerminalFormats.FgCyan;
break; break;
case Colors.WHITE: case Colors.WHITE:
formats += TerminalFormats.FgWhite; formats += TerminalFormats.FgWhite;
break; break;
} }
break; break;
} }
} }
text += formats + part.text + TerminalFormats.Reset; text += formats + part.text + TerminalFormats.Reset;
}
} else {
for (let part of line) {
let styles: string[] = [];
let resetStyles: string[] = [];
for (let format of part.formats) {
switch (format.type) {
case FormatTypes.BOLD:
styles.push("font-weight: bold;");
resetStyles.push("font-weight: unset");
break;
case FormatTypes.UNDERSCORE:
styles.push("text-decoration: underline");
resetStyles.push("text-decoration: unset");
break;
case FormatTypes.BLINK:
styles.push("text-decoration: blink");
resetStyles.push("text-decoration: unset");
break;
case FormatTypes.COLOR:
let color = "";
switch (format.color) {
case Colors.RED:
color = "red";
break;
case Colors.GREEN:
color = "green";
break;
case Colors.YELLOW:
color = "gold";
break;
case Colors.BLUE:
color = "blue";
break;
case Colors.MAGENTA:
color = "magenta";
break;
case Colors.CYAN:
color = "cyan";
break;
case Colors.WHITE:
color = "white";
break;
}
styles.push("color: " + color);
resetStyles.push("color: unset");
break;
}
}
text += "%c" + part.text.replace(/%c/g, "%%c") + "%c";
style_formats.push(styles.join(";"), resetStyles.join(";"));
}
} }
} else {
for (let part of line) { return [text, style_formats];
let styles: string[] = []; }
let resetStyles: string[] = [];
for (let format of part.formats) { onMessage(message: Message) {
switch (format.type) { let lines = message.text.formatted;
case FormatTypes.BOLD:
styles.push("font-weight: bold;"); let prefix = "";
resetStyles.push("font-weight: unset"); if (message.name) prefix = `[${message.name}]=>`;
break;
case FormatTypes.UNDERSCORE: if (browser) {
styles.push("text-decoration: underline"); let formats: string[] = [];
resetStyles.push("text-decoration: unset"); let text = lines
break; .map((line) => {
case FormatTypes.BLINK: let [t, fmts] = this.formatLine(line);
styles.push("text-decoration: blink"); formats.push(...fmts);
resetStyles.push("text-decoration: unset"); return prefix + t;
break; })
case FormatTypes.COLOR: .join("\n");
let color = ""; // console.log(formats);
switch (format.color) { console.log(text, ...formats);
case Colors.RED: } else {
color = "red"; lines.forEach((line) => {
break; let [text] = this.formatLine(line);
case Colors.GREEN: console.log(prefix + text);
color = "green"; });
break;
case Colors.YELLOW:
color = "gold";
break;
case Colors.BLUE:
color = "blue";
break;
case Colors.MAGENTA:
color = "magenta";
break;
case Colors.CYAN:
color = "cyan";
break;
case Colors.WHITE:
color = "white";
break;
}
styles.push("color: " + color);
resetStyles.push("color: unset");
break;
}
}
text += "%c" + part.text.replace(/%c/g, "%%c") + "%c";
style_formats.push(styles.join(";"), resetStyles.join(";"));
} }
} }
return [text, style_formats];
}
onMessage(message: Message) {
let lines = message.text.formatted;
let prefix = "";
if (message.name) prefix = `[${message.name}]=>`;
if (browser) {
let formats: string[] = [];
let text = lines
.map(line => {
let [t, fmts] = this.formatLine(line);
formats.push(...fmts);
return prefix + t;
})
.join("\n");
// console.log(formats);
console.log(text, ...formats);
} else {
lines.forEach(line => {
let [text] = this.formatLine(line);
console.log(prefix + text);
});
}
}
} }

View File

@ -1,18 +1,23 @@
import { LoggingBase } from "./base"; import { LoggingBase } from "./base";
export { ConsoleAdapter } from "./consolewriter"; export { ConsoleAdapter } from "./consolewriter";
export { LoggingBase, LoggingBaseOptions, removeColors, withColor } from "./base";
export { export {
Adapter, LoggingBase,
LoggingTypes, LoggingBaseOptions,
Message, removeColors,
FormatConfig, withColor,
FormattedLine, } from "./base";
DefaultFormatConfig as DefaultColorMap, export {
FormattedText, Adapter,
Colors, LoggingTypes,
Format, Message,
FormatTypes, FormatConfig,
TerminalFormats FormattedLine,
DefaultFormatConfig as DefaultColorMap,
FormattedText,
Colors,
Format,
FormatTypes,
TerminalFormats,
} from "./types"; } from "./types";
export { ObservableInterface } from "@hibas123/utils"; export { ObservableInterface } from "@hibas123/utils";

View File

@ -1,12 +1,11 @@
/** /**
* Module exports. * Module exports.
*/ */
interface InspectOptions { interface InspectOptions {
depth: number; depth: number;
colors: boolean; colors: boolean;
showHidden: boolean; showHidden: boolean;
} }
/** /**
@ -19,397 +18,440 @@ interface InspectOptions {
*/ */
/* legacy: obj, showHidden, depth, colors*/ /* legacy: obj, showHidden, depth, colors*/
export default function inspect(obj: any, opts: Partial<InspectOptions>) { export default function inspect(obj: any, opts: Partial<InspectOptions>) {
// default options // default options
let ctx = { let ctx = {
seen: [], seen: [],
stylize: stylizeNoColor, stylize: stylizeNoColor,
depth: undefined, depth: undefined,
colors: undefined, colors: undefined,
showHidden: undefined, showHidden: undefined,
customInspect: undefined customInspect: undefined,
}; };
// legacy... // legacy...
if (arguments.length >= 3) ctx.depth = arguments[2]; if (arguments.length >= 3) ctx.depth = arguments[2];
if (arguments.length >= 4) ctx.colors = arguments[3]; if (arguments.length >= 4) ctx.colors = arguments[3];
if (isBoolean(opts)) { if (isBoolean(opts)) {
// legacy... // legacy...
ctx.showHidden = opts; ctx.showHidden = opts;
} else if (opts) { } else if (opts) {
// got an "options" object // got an "options" object
_extend(ctx, opts); _extend(ctx, opts);
} }
// set default options // set default options
if (isUndefined(ctx.showHidden)) ctx.showHidden = false; if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
if (isUndefined(ctx.depth)) ctx.depth = 2; if (isUndefined(ctx.depth)) ctx.depth = 2;
if (isUndefined(ctx.colors)) ctx.colors = false; if (isUndefined(ctx.colors)) ctx.colors = false;
if (isUndefined(ctx.customInspect)) ctx.customInspect = true; if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
if (ctx.colors) ctx.stylize = stylizeWithColor; if (ctx.colors) ctx.stylize = stylizeWithColor;
return formatValue(ctx, obj, ctx.depth); return formatValue(ctx, obj, ctx.depth);
} }
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = { inspect.colors = {
'bold': [1, 22], bold: [1, 22],
'italic': [3, 23], italic: [3, 23],
'underline': [4, 24], underline: [4, 24],
'inverse': [7, 27], inverse: [7, 27],
'white': [37, 39], white: [37, 39],
'grey': [90, 39], grey: [90, 39],
'black': [30, 39], black: [30, 39],
'blue': [34, 39], blue: [34, 39],
'cyan': [36, 39], cyan: [36, 39],
'green': [32, 39], green: [32, 39],
'magenta': [35, 39], magenta: [35, 39],
'red': [31, 39], red: [31, 39],
'yellow': [33, 39] yellow: [33, 39],
}; };
// Don't use 'blue' not visible on cmd.exe // Don't use 'blue' not visible on cmd.exe
inspect.styles = { inspect.styles = {
'special': 'cyan', special: "cyan",
'number': 'yellow', number: "yellow",
'boolean': 'yellow', boolean: "yellow",
'undefined': 'grey', undefined: "grey",
'null': 'bold', null: "bold",
'string': 'green', string: "green",
'date': 'magenta', date: "magenta",
// "name": intentionally not styling // "name": intentionally not styling
'regexp': 'red' regexp: "red",
}; };
function stylizeNoColor(str, styleType) { function stylizeNoColor(str, styleType) {
return str; return str;
} }
function isBoolean(arg) { function isBoolean(arg) {
return typeof arg === 'boolean'; return typeof arg === "boolean";
} }
function isUndefined(arg) { function isUndefined(arg) {
return arg === void 0; return arg === void 0;
} }
function stylizeWithColor(str, styleType) { function stylizeWithColor(str, styleType) {
var style = inspect.styles[styleType]; var style = inspect.styles[styleType];
if (style) { if (style) {
return '\u001b[' + inspect.colors[style][0] + 'm' + str + return (
'\u001b[' + inspect.colors[style][1] + 'm'; "\u001b[" +
} else { inspect.colors[style][0] +
return str; "m" +
} str +
"\u001b[" +
inspect.colors[style][1] +
"m"
);
} else {
return str;
}
} }
function isFunction(arg) { function isFunction(arg) {
return typeof arg === 'function'; return typeof arg === "function";
} }
function isString(arg) { function isString(arg) {
return typeof arg === 'string'; return typeof arg === "string";
} }
function isNumber(arg) { function isNumber(arg) {
return typeof arg === 'number'; return typeof arg === "number";
} }
function isNull(arg) { function isNull(arg) {
return arg === null; return arg === null;
} }
function hasOwn(obj, prop) { function hasOwn(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop); return Object.prototype.hasOwnProperty.call(obj, prop);
} }
function isRegExp(re) { function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]'; return isObject(re) && objectToString(re) === "[object RegExp]";
} }
function isObject(arg) { function isObject(arg) {
return typeof arg === 'object' && arg !== null; return typeof arg === "object" && arg !== null;
} }
function isError(e) { function isError(e) {
return isObject(e) && return (
(objectToString(e) === '[object Error]' || e instanceof Error); isObject(e) &&
(objectToString(e) === "[object Error]" || e instanceof Error)
);
} }
function isDate(d) { function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]'; return isObject(d) && objectToString(d) === "[object Date]";
} }
function objectToString(o) { function objectToString(o) {
return Object.prototype.toString.call(o); return Object.prototype.toString.call(o);
} }
function arrayToHash(array) { function arrayToHash(array) {
var hash = {}; var hash = {};
array.forEach(function (val, idx) { array.forEach(function (val, idx) {
hash[val] = true; hash[val] = true;
}); });
return hash; return hash;
} }
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = []; var output = [];
for (var i = 0, l = value.length; i < l; ++i) { for (var i = 0, l = value.length; i < l; ++i) {
if (hasOwn(value, String(i))) { if (hasOwn(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, output.push(
String(i), true)); formatProperty(
} else { ctx,
output.push(''); value,
} recurseTimes,
} visibleKeys,
keys.forEach(function (key) { String(i),
if (!key.match(/^\d+$/)) { true
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, )
key, true)); );
} } else {
}); output.push("");
return output; }
}
keys.forEach(function (key) {
if (!key.match(/^\d+$/)) {
output.push(
formatProperty(ctx, value, recurseTimes, visibleKeys, key, true)
);
}
});
return output;
} }
function formatError(value) { function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']'; return "[" + Error.prototype.toString.call(value) + "]";
} }
function formatValue(ctx, value, recurseTimes) { function formatValue(ctx, value, recurseTimes) {
// Provide a hook for user-specified inspect functions. // Provide a hook for user-specified inspect functions.
// Check that value is an object with an inspect function on it // Check that value is an object with an inspect function on it
if (ctx.customInspect && if (
value && ctx.customInspect &&
isFunction(value.inspect) && value &&
// Filter out the util module, it's inspect function is special isFunction(value.inspect) &&
value.inspect !== inspect && // Filter out the util module, it's inspect function is special
// Also filter out any prototype objects using the circular check. value.inspect !== inspect &&
!(value.constructor && value.constructor.prototype === value)) { // Also filter out any prototype objects using the circular check.
var ret = value.inspect(recurseTimes, ctx); !(value.constructor && value.constructor.prototype === value)
if (!isString(ret)) { ) {
ret = formatValue(ctx, ret, recurseTimes); var ret = value.inspect(recurseTimes, ctx);
} if (!isString(ret)) {
return ret; ret = formatValue(ctx, ret, recurseTimes);
} }
return ret;
}
// Primitive types cannot have properties // Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value); var primitive = formatPrimitive(ctx, value);
if (primitive) { if (primitive) {
return primitive; return primitive;
} }
// Look up the keys of the object. // Look up the keys of the object.
var keys = Object.keys(value); var keys = Object.keys(value);
var visibleKeys = arrayToHash(keys); var visibleKeys = arrayToHash(keys);
try { try {
if (ctx.showHidden && Object.getOwnPropertyNames) { if (ctx.showHidden && Object.getOwnPropertyNames) {
keys = Object.getOwnPropertyNames(value); keys = Object.getOwnPropertyNames(value);
} }
} catch (e) { } catch (e) {
// ignore // ignore
} }
// IE doesn't make error fields non-enumerable // IE doesn't make error fields non-enumerable
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
if (isError(value) if (
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { isError(value) &&
return formatError(value); (keys.indexOf("message") >= 0 || keys.indexOf("description") >= 0)
} ) {
return formatError(value);
}
// Some type of object without properties can be shortcutted. // Some type of object without properties can be shortcutted.
if (keys.length === 0) { if (keys.length === 0) {
if (isFunction(value)) { if (isFunction(value)) {
var name = value.name ? ': ' + value.name : ''; var name = value.name ? ": " + value.name : "";
return ctx.stylize('[Function' + name + ']', 'special'); return ctx.stylize("[Function" + name + "]", "special");
} }
if (isRegExp(value)) { if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); return ctx.stylize(RegExp.prototype.toString.call(value), "regexp");
} }
if (isDate(value)) { if (isDate(value)) {
return ctx.stylize(Date.prototype.toString.call(value), 'date'); return ctx.stylize(Date.prototype.toString.call(value), "date");
} }
if (isError(value)) { if (isError(value)) {
return formatError(value); return formatError(value);
} }
} }
var base = '', array = false, braces = ['{', '}']; var base = "",
array = false,
braces = ["{", "}"];
// Make Array say that they are Array // Make Array say that they are Array
if (Array.isArray(value)) { if (Array.isArray(value)) {
array = true; array = true;
braces = ['[', ']']; braces = ["[", "]"];
} }
// Make functions say that they are functions // Make functions say that they are functions
if (isFunction(value)) { if (isFunction(value)) {
var n = value.name ? ': ' + value.name : ''; var n = value.name ? ": " + value.name : "";
base = ' [Function' + n + ']'; base = " [Function" + n + "]";
} }
// Make RegExps say that they are RegExps // Make RegExps say that they are RegExps
if (isRegExp(value)) { if (isRegExp(value)) {
base = ' ' + RegExp.prototype.toString.call(value); base = " " + RegExp.prototype.toString.call(value);
} }
// Make dates with properties first say the date // Make dates with properties first say the date
if (isDate(value)) { if (isDate(value)) {
base = ' ' + Date.prototype.toUTCString.call(value); base = " " + Date.prototype.toUTCString.call(value);
} }
// Make error with message first say the error // Make error with message first say the error
if (isError(value)) { if (isError(value)) {
base = ' ' + formatError(value); base = " " + formatError(value);
} }
if (keys.length === 0 && (!array || value.length == 0)) { if (keys.length === 0 && (!array || value.length == 0)) {
return braces[0] + base + braces[1]; return braces[0] + base + braces[1];
} }
if (recurseTimes < 0) { if (recurseTimes < 0) {
if (isRegExp(value)) { if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); return ctx.stylize(RegExp.prototype.toString.call(value), "regexp");
} else { } else {
return ctx.stylize('[Object]', 'special'); return ctx.stylize("[Object]", "special");
} }
} }
ctx.seen.push(value); ctx.seen.push(value);
var output; var output;
if (array) { if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else { } else {
output = keys.map(function (key) { output = keys.map(function (key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); return formatProperty(
}); ctx,
} value,
recurseTimes,
visibleKeys,
key,
array
);
});
}
ctx.seen.pop(); ctx.seen.pop();
return reduceToSingleString(output, base, braces); return reduceToSingleString(output, base, braces);
} }
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc; var name, str, desc;
desc = { value: void 0 }; desc = { value: void 0 };
try { try {
// ie6 navigator.toString // ie6 navigator.toString
// throws Error: Object doesn't support this property or method // throws Error: Object doesn't support this property or method
desc.value = value[key]; desc.value = value[key];
} catch (e) { } catch (e) {
// ignore // ignore
} }
try { try {
// ie10 Object.getOwnPropertyDescriptor(window.location, 'hash') // ie10 Object.getOwnPropertyDescriptor(window.location, 'hash')
// throws TypeError: Object doesn't support this action // throws TypeError: Object doesn't support this action
if (Object.getOwnPropertyDescriptor) { if (Object.getOwnPropertyDescriptor) {
desc = Object.getOwnPropertyDescriptor(value, key) || desc; desc = Object.getOwnPropertyDescriptor(value, key) || desc;
} }
} catch (e) { } catch (e) {
// ignore // ignore
} }
if (desc.get) { if (desc.get) {
if (desc.set) { if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special'); str = ctx.stylize("[Getter/Setter]", "special");
} else { } else {
str = ctx.stylize('[Getter]', 'special'); str = ctx.stylize("[Getter]", "special");
} }
} else { } else {
if (desc.set) { if (desc.set) {
str = ctx.stylize('[Setter]', 'special'); str = ctx.stylize("[Setter]", "special");
} }
} }
if (!hasOwn(visibleKeys, key)) { if (!hasOwn(visibleKeys, key)) {
name = '[' + key + ']'; name = "[" + key + "]";
} }
if (!str) { if (!str) {
if (ctx.seen.indexOf(desc.value) < 0) { if (ctx.seen.indexOf(desc.value) < 0) {
if (isNull(recurseTimes)) { if (isNull(recurseTimes)) {
str = formatValue(ctx, desc.value, null); str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf("\n") > -1) {
if (array) {
str = str
.split("\n")
.map(function (line) {
return " " + line;
})
.join("\n")
.substr(2);
} else { } else {
str = formatValue(ctx, desc.value, recurseTimes - 1); str =
"\n" +
str
.split("\n")
.map(function (line) {
return " " + line;
})
.join("\n");
} }
if (str.indexOf('\n') > -1) { }
if (array) { } else {
str = str.split('\n').map(function (line) { str = ctx.stylize("[Circular]", "special");
return ' ' + line; }
}).join('\n').substr(2); }
} else { if (isUndefined(name)) {
str = '\n' + str.split('\n').map(function (line) { if (array && key.match(/^\d+$/)) {
return ' ' + line; return str;
}).join('\n'); }
} name = JSON.stringify("" + key);
} if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
} else { name = name.substr(1, name.length - 2);
str = ctx.stylize('[Circular]', 'special'); name = ctx.stylize(name, "name");
} } else {
} name = name
if (isUndefined(name)) { .replace(/'/g, "\\'")
if (array && key.match(/^\d+$/)) { .replace(/\\"/g, '"')
return str; .replace(/(^"|"$)/g, "'");
} name = ctx.stylize(name, "string");
name = JSON.stringify('' + key); }
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { }
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'")
.replace(/\\"/g, '"')
.replace(/(^"|"$)/g, "'");
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str; return name + ": " + str;
} }
function formatPrimitive(ctx, value) { function formatPrimitive(ctx, value) {
if (isUndefined(value)) if (isUndefined(value)) return ctx.stylize("undefined", "undefined");
return ctx.stylize('undefined', 'undefined'); if (isString(value)) {
if (isString(value)) { var simple =
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') "'" +
JSON.stringify(value)
.replace(/^"|"$/g, "")
.replace(/'/g, "\\'") .replace(/'/g, "\\'")
.replace(/\\"/g, '"') + '\''; .replace(/\\"/g, '"') +
return ctx.stylize(simple, 'string'); "'";
} return ctx.stylize(simple, "string");
if (isNumber(value)) }
return ctx.stylize('' + value, 'number'); if (isNumber(value)) return ctx.stylize("" + value, "number");
if (isBoolean(value)) if (isBoolean(value)) return ctx.stylize("" + value, "boolean");
return ctx.stylize('' + value, 'boolean'); // For some reason typeof null is "object", so special case here.
// For some reason typeof null is "object", so special case here. if (isNull(value)) return ctx.stylize("null", "null");
if (isNull(value))
return ctx.stylize('null', 'null');
} }
function reduceToSingleString(output, base, braces) { function reduceToSingleString(output, base, braces) {
var numLinesEst = 0; var numLinesEst = 0;
var length = output.reduce(function (prev, cur) { var length = output.reduce(function (prev, cur) {
numLinesEst++; numLinesEst++;
if (cur.indexOf('\n') >= 0) numLinesEst++; if (cur.indexOf("\n") >= 0) numLinesEst++;
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; return prev + cur.replace(/\u001b\[\d\d?m/g, "").length + 1;
}, 0); }, 0);
if (length > 60) { if (length > 60) {
return braces[0] + return (
(base === '' ? '' : base + '\n ') + braces[0] +
' ' + (base === "" ? "" : base + "\n ") +
output.join(',\n ') + " " +
' ' + output.join(",\n ") +
braces[1]; " " +
} braces[1]
);
}
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; return braces[0] + base + " " + output.join(", ") + " " + braces[1];
} }
function _extend<T extends Y, Y>(origin: T, add: Y) { function _extend<T extends Y, Y>(origin: T, add: Y) {
// Don't do anything if add isn't an object // Don't do anything if add isn't an object
if (!add || !isObject(add)) return origin; if (!add || !isObject(add)) return origin;
var keys = Object.keys(add); var keys = Object.keys(add);
var i = keys.length; var i = keys.length;
while (i--) { while (i--) {
origin[keys[i]] = add[keys[i]]; origin[keys[i]] = add[keys[i]];
} }
return origin; return origin;
} }

View File

@ -1,119 +1,125 @@
import { ObservableInterface } from "@hibas123/utils"; import { ObservableInterface } from "@hibas123/utils";
export enum LoggingTypes { export enum LoggingTypes {
Debug, Debug,
Log, Log,
Warning, Warning,
Error Error,
} }
export const TerminalFormats = { export const TerminalFormats = {
Reset: "\x1b[0m", Reset: "\x1b[0m",
Bold: "\x1b[1m", Bold: "\x1b[1m",
Underscore: "\x1b[4m", Underscore: "\x1b[4m",
Blink: "\x1b[5m", Blink: "\x1b[5m",
Reverse: "\x1b[7m", Reverse: "\x1b[7m",
Hidden: "\x1b[8m", Hidden: "\x1b[8m",
FgBlack: "\x1b[30m", FgBlack: "\x1b[30m",
FgRed: "\x1b[31m", FgRed: "\x1b[31m",
FgGreen: "\x1b[32m", FgGreen: "\x1b[32m",
FgYellow: "\x1b[33m", FgYellow: "\x1b[33m",
FgBlue: "\x1b[34m", FgBlue: "\x1b[34m",
FgMagenta: "\x1b[35m", FgMagenta: "\x1b[35m",
FgCyan: "\x1b[36m", FgCyan: "\x1b[36m",
FgWhite: "\x1b[37m", FgWhite: "\x1b[37m",
BgBlack: "\x1b[40m",
BgRed: "\x1b[41m",
BgGreen: "\x1b[42m",
BgYellow: "\x1b[43m",
BgBlue: "\x1b[44m",
BgMagenta: "\x1b[45m",
BgCyan: "\x1b[46m",
BgWhite: "\x1b[47m"
}
BgBlack: "\x1b[40m",
BgRed: "\x1b[41m",
BgGreen: "\x1b[42m",
BgYellow: "\x1b[43m",
BgBlue: "\x1b[44m",
BgMagenta: "\x1b[45m",
BgCyan: "\x1b[46m",
BgWhite: "\x1b[47m",
};
export enum FormatTypes { export enum FormatTypes {
COLOR, COLOR,
BOLD, BOLD,
UNDERSCORE, UNDERSCORE,
BLINK BLINK,
} }
export enum Colors { export enum Colors {
NONE, NONE,
RED, RED,
GREEN, GREEN,
YELLOW, YELLOW,
BLUE, BLUE,
MAGENTA, MAGENTA,
CYAN, CYAN,
WHITE WHITE,
} }
export interface FormatConfig { export interface FormatConfig {
error: Format[]; error: Format[];
warning: Format[]; warning: Format[];
log: Format[]; log: Format[];
debug: Format[]; debug: Format[];
date: Format[]; date: Format[];
file: Format[]; file: Format[];
} }
function colorFormat(color: Colors) { function colorFormat(color: Colors) {
return { return {
type: FormatTypes.COLOR, type: FormatTypes.COLOR,
color color,
} };
} }
const boldFormat = { const boldFormat = {
type: FormatTypes.BOLD type: FormatTypes.BOLD,
}; };
export class DefaultFormatConfig implements FormatConfig { export class DefaultFormatConfig implements FormatConfig {
error = [colorFormat(Colors.RED), boldFormat]; error = [colorFormat(Colors.RED), boldFormat];
warning = [colorFormat(Colors.YELLOW), boldFormat]; warning = [colorFormat(Colors.YELLOW), boldFormat];
log = [colorFormat(Colors.NONE), boldFormat]; log = [colorFormat(Colors.NONE), boldFormat];
debug = [colorFormat(Colors.CYAN), boldFormat]; debug = [colorFormat(Colors.CYAN), boldFormat];
date = [colorFormat(Colors.NONE)]; date = [colorFormat(Colors.NONE)];
file = [colorFormat(Colors.NONE)]; file = [colorFormat(Colors.NONE)];
} }
export interface Format { export interface Format {
type: FormatTypes; type: FormatTypes;
color?: Colors; color?: Colors;
} }
export interface FormattedText { export interface FormattedText {
text: string; text: string;
formats: Format[]; formats: Format[];
} }
export type FormattedLine = FormattedText[]; export type FormattedLine = FormattedText[];
export interface Message { export interface Message {
type: LoggingTypes; type: LoggingTypes;
name?: string; name?: string;
text: { text: {
raw: string[], raw: string[];
formatted: FormattedLine[] formatted: FormattedLine[];
}; };
date: Date; date: Date;
file: string; file: string;
} }
export interface Adapter { export interface Adapter {
init(observable: ObservableInterface<Message>, name?: string): void | Promise<void>; /**
* This function initialises the Adapter. It might be called multiple times, when added to multiple instances
* @param observable An observable to subscribe to messages
*/
init(observable: ObservableInterface<Message>): void | Promise<void>;
flush(sync: true): void; flush(sync: true): void;
flush(sync: false): void | Promise<void>; flush(sync: false): void | Promise<void>;
/**
close?(): void; * When a close function is available, it will be called when no logging instance references it anymore.
} *
* WARNING: The adapter might be reinitialised, when it is added to a new Logging instance
*/
close?(): void;
}