caterpillar
Advanced tools
Comparing version 6.6.0 to 6.7.0-next.1627509327.95a1fdcc97d8933f808e570bda2cdb5db6d69c8d
@@ -1,6 +0,6 @@ | ||
export * from './transform.js' | ||
export * from './logger.js' | ||
export * from './transforms/filter.js' | ||
export * from './transforms/human.js' | ||
export * from './transforms/browser.js' | ||
//# sourceMappingURL=index.d.ts.map | ||
export * from './transform.js'; | ||
export * from './logger.js'; | ||
export * from './transforms/filter.js'; | ||
export * from './transforms/human.js'; | ||
export * from './transforms/browser.js'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -1,21 +0,21 @@ | ||
import { LevelInfo, LevelsMap } from 'rfc-log-levels' | ||
import { Offset, Location } from 'get-current-line' | ||
import { Transform } from './transform.js' | ||
import { LevelInfo, LevelsMap } from 'rfc-log-levels'; | ||
import { Offset, Location } from 'get-current-line'; | ||
import { Transform } from './transform.js'; | ||
/** The log entry that Caterpillar creates and forwards to its transforms */ | ||
export interface LogEntry extends LevelInfo, Location { | ||
/** the iso string of when the log occured */ | ||
date: string | ||
/** all the arguments that were after the log level */ | ||
args: any[] | ||
/** the iso string of when the log occured */ | ||
date: string; | ||
/** all the arguments that were after the log level */ | ||
args: any[]; | ||
} | ||
/** Configuration for the Caterpillar Logger */ | ||
export interface LoggerOptions { | ||
/** Use to override the default value of {@link Logger.lineOffset} */ | ||
lineOffset?: Offset | ||
/** Use to override the default value of {@link Logger.levels} */ | ||
levels?: LevelsMap | ||
/** Use to override the default value of {@link Logger.defaultLevelInfo} */ | ||
defaultLevel?: number | string | ||
/** Use to override the default value of {@link Logger.lineLevel} */ | ||
lineLevel?: number | ||
/** Use to override the default value of {@link Logger.lineOffset} */ | ||
lineOffset?: Offset; | ||
/** Use to override the default value of {@link Logger.levels} */ | ||
levels?: LevelsMap; | ||
/** Use to override the default value of {@link Logger.defaultLevelInfo} */ | ||
defaultLevel?: number | string; | ||
/** Use to override the default value of {@link Logger.lineLevel} */ | ||
lineLevel?: number; | ||
} | ||
@@ -33,78 +33,78 @@ /** | ||
export declare class Logger extends Transform { | ||
/** | ||
* The configuration to use for the line offset. | ||
* This defaults to any file path that includes `logger`, and any method that includes the word `log`. | ||
*/ | ||
lineOffset: Offset | ||
/** | ||
* The mapping of log level names to log level numbers. | ||
* Defaults to the RFC Log Level configuration. | ||
*/ | ||
levels: LevelsMap | ||
/** | ||
* The log level information to use when the log level was unable to be determined. | ||
* Defaults to the info log level. | ||
*/ | ||
defaultLevelInfo: LevelInfo | ||
/** Set the default level info via a level number or name. */ | ||
set defaultLevel(value: number | string) | ||
/** | ||
* Only fetch line information for entries that have a log level equal to, or below this number. | ||
* You should only specify this if you need it, as fFetching line information for thousands of log entries, which is typical in large applications, will slow your application down dramatically. | ||
* If not specified, defaults to `-Infinity` which effect is to ignore gathering line information for all log levels. | ||
*/ | ||
lineLevel: number | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts?: LoggerOptions) | ||
/** Alias for {@link getLogLevel} using the configured logger levels as reference. */ | ||
getLogLevel(value: number | string): LevelInfo | null | ||
/** Takes an arguments array and tranforms it into a log entry. */ | ||
format(args: any): LogEntry | ||
/** | ||
* Log the arguments into the logger stream as formatted data with debugging information. | ||
* Such that our transformers can deal with it intelligently. | ||
* | ||
* @example Inputs | ||
* ``` javascript | ||
* logger.log('note', 'this is working swell') | ||
* ``` | ||
* ``` javascript | ||
* logger.log('this', 'worked', 'swell') | ||
* ``` | ||
* | ||
* @example Results | ||
* ``` json | ||
* { | ||
* "args": ["this is working swell"], | ||
* "date": "2013-04-25T10:18:25.722Z", | ||
* "levelNumber": 5, | ||
* "levelName": "notice", | ||
* "line": "59", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
* ``` json | ||
* { | ||
* "args": ["this", "worked", "well"], | ||
* "date": "2013-04-25T10:18:26.539Z", | ||
* "levelNumber": 6, | ||
* "levelName": "info", | ||
* "line": "60", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
*/ | ||
log(...args: any): void | ||
/** Alias for log which prefixes the error log level */ | ||
error(...args: any): void | ||
/** Alias for log which prefixes the warn log level */ | ||
warn(...args: any): void | ||
/** Alias for log which prefixes the info log level */ | ||
info(...args: any): void | ||
/** Alias for log which prefixes the debug log level */ | ||
debug(...args: any): void | ||
/** | ||
* The configuration to use for the line offset. | ||
* This defaults to any file path that includes `logger`, and any method that includes the word `log`. | ||
*/ | ||
lineOffset: Offset; | ||
/** | ||
* The mapping of log level names to log level numbers. | ||
* Defaults to the RFC Log Level configuration. | ||
*/ | ||
levels: LevelsMap; | ||
/** | ||
* The log level information to use when the log level was unable to be determined. | ||
* Defaults to the info log level. | ||
*/ | ||
defaultLevelInfo: LevelInfo; | ||
/** Set the default level info via a level number or name. */ | ||
set defaultLevel(value: number | string); | ||
/** | ||
* Only fetch line information for entries that have a log level equal to, or below this number. | ||
* You should only specify this if you need it, as fFetching line information for thousands of log entries, which is typical in large applications, will slow your application down dramatically. | ||
* If not specified, defaults to `-Infinity` which effect is to ignore gathering line information for all log levels. | ||
*/ | ||
lineLevel: number; | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts?: LoggerOptions); | ||
/** Alias for {@link getLogLevel} using the configured logger levels as reference. */ | ||
getLogLevel(value: number | string): LevelInfo | null; | ||
/** Takes an arguments array and tranforms it into a log entry. */ | ||
format(args: any): LogEntry; | ||
/** | ||
* Log the arguments into the logger stream as formatted data with debugging information. | ||
* Such that our transformers can deal with it intelligently. | ||
* | ||
* @example Inputs | ||
* ``` javascript | ||
* logger.log('note', 'this is working swell') | ||
* ``` | ||
* ``` javascript | ||
* logger.log('this', 'worked', 'swell') | ||
* ``` | ||
* | ||
* @example Results | ||
* ``` json | ||
* { | ||
* "args": ["this is working swell"], | ||
* "date": "2013-04-25T10:18:25.722Z", | ||
* "levelNumber": 5, | ||
* "levelName": "notice", | ||
* "line": "59", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
* ``` json | ||
* { | ||
* "args": ["this", "worked", "well"], | ||
* "date": "2013-04-25T10:18:26.539Z", | ||
* "levelNumber": 6, | ||
* "levelName": "info", | ||
* "line": "60", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
*/ | ||
log(...args: any): void; | ||
/** Alias for log which prefixes the error log level */ | ||
error(...args: any): void; | ||
/** Alias for log which prefixes the warn log level */ | ||
warn(...args: any): void; | ||
/** Alias for log which prefixes the info log level */ | ||
info(...args: any): void; | ||
/** Alias for log which prefixes the debug log level */ | ||
debug(...args: any): void; | ||
} | ||
export default Logger | ||
//# sourceMappingURL=logger.d.ts.map | ||
export default Logger; | ||
//# sourceMappingURL=logger.d.ts.map |
@@ -13,5 +13,5 @@ /** | ||
export interface Pipeable { | ||
write(chunk: any): any | ||
end?(cb?: () => void): void | ||
close?(): Promise<void> | void | ||
write(chunk: any): any; | ||
end?(cb?: () => void): void; | ||
close?(): Promise<void> | void; | ||
} | ||
@@ -26,19 +26,19 @@ /** | ||
export declare class Transform implements Pipeable { | ||
/** Where is this Transform piping to? */ | ||
private pipes | ||
/** | ||
* Format the received log entry representation. | ||
* Your transformer should extend this. | ||
*/ | ||
format(message: any): any | ||
/** Pipe future log entries into a caterpillar transform or a stream. */ | ||
pipe<T extends Pipeable>(to: T): T | ||
/** Maintain a write queue such that multiple Deno writes do not stall */ | ||
private writer | ||
/** Write to the child pipes. */ | ||
write(chunk: any): Promise<void> | ||
/** Close the child pipes. */ | ||
close(): Promise<void> | ||
end(cb?: () => void): void | ||
/** Where is this Transform piping to? */ | ||
private pipes; | ||
/** | ||
* Format the received log entry representation. | ||
* Your transformer should extend this. | ||
*/ | ||
format(message: any): any; | ||
/** Pipe future log entries into a caterpillar transform or a stream. */ | ||
pipe<T extends Pipeable>(to: T): T; | ||
/** Maintain a write queue such that multiple Deno writes do not stall */ | ||
private writer; | ||
/** Write to the child pipes. */ | ||
write(chunk: any): Promise<void>; | ||
/** Close the child pipes. */ | ||
close(): Promise<void>; | ||
end(cb?: () => void): void; | ||
} | ||
//# sourceMappingURL=transform.d.ts.map | ||
//# sourceMappingURL=transform.d.ts.map |
@@ -1,21 +0,21 @@ | ||
import { Transform } from '../transform.js' | ||
import { Transform } from '../transform.js'; | ||
/** Mapping of ANSI color codes into a CSS style */ | ||
export interface Styles { | ||
[key: string]: { | ||
/** The ANSI color code used to start the style */ | ||
start: string | ||
/** The ANSI color code used to end the style */ | ||
end: string | ||
/** The CSS style value */ | ||
value: string | ||
} | ||
[key: string]: { | ||
/** The ANSI color code used to start the style */ | ||
start: string; | ||
/** The ANSI color code used to end the style */ | ||
end: string; | ||
/** The CSS style value */ | ||
value: string; | ||
}; | ||
} | ||
/** Configuration optons for the Caterpillar Browser Transform */ | ||
export interface BrowserOptions { | ||
/** Use to override the default value of {@link Filter.color} */ | ||
color?: boolean | ||
/** Use to override the default value of {@link Filter.console} */ | ||
output?: boolean | ||
/** Use to override the default value of {@link Filter.styles} */ | ||
styles?: Styles | ||
/** Use to override the default value of {@link Filter.color} */ | ||
color?: boolean; | ||
/** Use to override the default value of {@link Filter.console} */ | ||
output?: boolean; | ||
/** Use to override the default value of {@link Filter.styles} */ | ||
styles?: Styles; | ||
} | ||
@@ -33,17 +33,17 @@ /** | ||
export declare class Browser extends Transform { | ||
/** Whether or not we should use color. */ | ||
color: boolean | ||
/** Whether or not we should write to the browser console. */ | ||
output: boolean | ||
/** The objects that tell our browser transform how to convert terminal colours into console colours. */ | ||
styles: Styles | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts?: BrowserOptions) | ||
/** | ||
* Convert a human readable Caterpillar entry into a format that browser consoles can understand. | ||
* And if the `write` config property is `true` (it is by default), write the result to the browser console. | ||
*/ | ||
format(message: string): string[] | ||
/** Whether or not we should use color. */ | ||
color: boolean; | ||
/** Whether or not we should write to the browser console. */ | ||
output: boolean; | ||
/** The objects that tell our browser transform how to convert terminal colours into console colours. */ | ||
styles: Styles; | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts?: BrowserOptions); | ||
/** | ||
* Convert a human readable Caterpillar entry into a format that browser consoles can understand. | ||
* And if the `write` config property is `true` (it is by default), write the result to the browser console. | ||
*/ | ||
format(message: string): string[]; | ||
} | ||
export default Browser | ||
//# sourceMappingURL=browser.d.ts.map | ||
export default Browser; | ||
//# sourceMappingURL=browser.d.ts.map |
@@ -1,7 +0,7 @@ | ||
import { LogEntry } from '../logger.js' | ||
import { Transform } from '../transform.js' | ||
import { LogEntry } from '../logger.js'; | ||
import { Transform } from '../transform.js'; | ||
/** Configuration options for the Caterpillar Filter Transform */ | ||
export interface FilterOptions { | ||
/** Use to override the default value of {@link Filter.filterLevel} */ | ||
filterLevel?: number | ||
/** Use to override the default value of {@link Filter.filterLevel} */ | ||
filterLevel?: number; | ||
} | ||
@@ -25,13 +25,13 @@ /** | ||
export declare class Filter extends Transform { | ||
/** | ||
* Only display entries that have a log level below or equal to this number. | ||
* Defaults to `6`, which by default is the info log level. | ||
*/ | ||
filterLevel: number | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts?: FilterOptions) | ||
/** Retain only log entries that are equal to or less than the specified filter level. */ | ||
format(entry: LogEntry): LogEntry | null | ||
/** | ||
* Only display entries that have a log level below or equal to this number. | ||
* Defaults to `6`, which by default is the info log level. | ||
*/ | ||
filterLevel: number; | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts?: FilterOptions); | ||
/** Retain only log entries that are equal to or less than the specified filter level. */ | ||
format(entry: LogEntry): LogEntry | null; | ||
} | ||
export default Filter | ||
//# sourceMappingURL=filter.d.ts.map | ||
export default Filter; | ||
//# sourceMappingURL=filter.d.ts.map |
@@ -1,19 +0,14 @@ | ||
import { LogEntry } from '../logger.js' | ||
import { Transform } from '../transform.js' | ||
import * as ansi from '@bevry/ansi' | ||
/** | ||
* Return the given argument. | ||
* Used for when there is no formatter. | ||
*/ | ||
export declare function noop<T>(str: T): T | ||
import { LogEntry } from '../logger.js'; | ||
import { Transform } from '../transform.js'; | ||
import * as ansi from '@bevry/ansi'; | ||
/** A mapping of log level numbers to their intended colours */ | ||
interface LevelsToColorsMap { | ||
[logLevelNumber: string]: ansi.ANSIApplier | ||
[logLevelNumber: string]: ansi.ANSIApplier; | ||
} | ||
/** Configuration optons for the Caterpillar Human Transform */ | ||
/** Configuration options for the Caterpillar Human Transform */ | ||
export interface HumanOptions { | ||
/** Use to override the default value of {@link Human.color} */ | ||
color?: boolean | ||
/** Use to override the default value of {@link Human.colors} */ | ||
colors?: LevelsToColorsMap | ||
/** Use to override the default value of {@link Human.color} */ | ||
color?: boolean; | ||
/** Use to override the default value of {@link Human.colors} */ | ||
colors?: LevelsToColorsMap; | ||
} | ||
@@ -33,20 +28,20 @@ /** | ||
export declare class Human extends Transform { | ||
/** Whether or not to use colors? */ | ||
color: boolean | ||
/** Mapping of which log level numbers correspond to which colours */ | ||
colors: LevelsToColorsMap | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts?: HumanOptions) | ||
/** Get the color for the log level */ | ||
getColor(levelNumber: number): ansi.ANSIApplier | false | ||
/** Pad the left of some content if need be with the specified padding to make the content reach a certain size */ | ||
padLeft(padding: string, size: number, content: string | number): string | ||
/** Convert logger entry arguments into a human readable string */ | ||
formatArguments(args: any[]): string | ||
/** Convert a datetime into a human readable format */ | ||
formatDate(datetime: Date | number | string): string | ||
/** Convert a logger entry into a human readable format */ | ||
format(entry: LogEntry): string | ||
/** Whether or not to use colors? */ | ||
color: boolean; | ||
/** Mapping of which log level numbers correspond to which colours */ | ||
colors: LevelsToColorsMap; | ||
/** Create our instance and apply our configuration options. */ | ||
constructor(opts?: HumanOptions); | ||
/** Get the color for the log level */ | ||
getColor(levelNumber: number): ansi.ANSIApplier | false; | ||
/** Pad the left of some content if need be with the specified padding to make the content reach a certain size */ | ||
padLeft(padding: string, size: number, content: string | number): string; | ||
/** Convert logger entry arguments into a human readable string */ | ||
formatArguments(args: any[]): string; | ||
/** Convert a datetime into a human readable format */ | ||
formatDate(datetime: Date | number | string): string; | ||
/** Convert a logger entry into a human readable format */ | ||
format(entry: LogEntry): string; | ||
} | ||
export default Human | ||
//# sourceMappingURL=human.d.ts.map | ||
export default Human; | ||
//# sourceMappingURL=human.d.ts.map |
@@ -1,5 +0,5 @@ | ||
export * from './transform.js' | ||
export * from './logger.js' | ||
export * from './transforms/filter.js' | ||
export * from './transforms/human.js' | ||
export * from './transforms/browser.js' | ||
export * from './transform.js'; | ||
export * from './logger.js'; | ||
export * from './transforms/filter.js'; | ||
export * from './transforms/human.js'; | ||
export * from './transforms/browser.js'; |
@@ -1,4 +0,4 @@ | ||
import getLogLevel, { rfcLogLevels } from 'rfc-log-levels' | ||
import getCurrentLine from 'get-current-line' | ||
import { Transform } from './transform.js' | ||
import getLogLevel, { rfcLogLevels } from 'rfc-log-levels'; | ||
import getCurrentLine from 'get-current-line'; | ||
import { Transform } from './transform.js'; | ||
/** | ||
@@ -15,138 +15,129 @@ * Logger. | ||
export class Logger extends Transform { | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
var _a | ||
super() | ||
/** | ||
* The configuration to use for the line offset. | ||
* This defaults to any file path that includes `logger`, and any method that includes the word `log`. | ||
*/ | ||
this.lineOffset = { | ||
file: /logger/i, | ||
method: /log/i, | ||
} | ||
/** | ||
* The mapping of log level names to log level numbers. | ||
* Defaults to the RFC Log Level configuration. | ||
*/ | ||
this.levels = rfcLogLevels | ||
/** | ||
* Only fetch line information for entries that have a log level equal to, or below this number. | ||
* You should only specify this if you need it, as fFetching line information for thousands of log entries, which is typical in large applications, will slow your application down dramatically. | ||
* If not specified, defaults to `-Infinity` which effect is to ignore gathering line information for all log levels. | ||
*/ | ||
this.lineLevel = -Infinity | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.lineOffset) != null) | ||
this.lineOffset = opts.lineOffset | ||
if ((opts === null || opts === void 0 ? void 0 : opts.levels) != null) | ||
this.levels = opts.levels | ||
if ((opts === null || opts === void 0 ? void 0 : opts.lineLevel) != null) | ||
this.lineLevel = opts.lineLevel | ||
// options: default level | ||
this.defaultLevel = | ||
(_a = opts === null || opts === void 0 ? void 0 : opts.defaultLevel) !== | ||
null && _a !== void 0 | ||
? _a | ||
: 'info' | ||
// dereference | ||
this.levels = Object.assign({}, this.levels) | ||
} | ||
/** Set the default level info via a level number or name. */ | ||
set defaultLevel(value) { | ||
const levelInfo = this.getLogLevel(value) | ||
if (levelInfo == null) { | ||
throw new Error( | ||
`caterpillar: the intended value of ${value} for the default log level not found in the configured levels` | ||
) | ||
} | ||
this.defaultLevelInfo = levelInfo | ||
} | ||
/** Alias for {@link getLogLevel} using the configured logger levels as reference. */ | ||
getLogLevel(value) { | ||
return getLogLevel(value, this.levels) | ||
} | ||
/** Takes an arguments array and tranforms it into a log entry. */ | ||
format(args) { | ||
// fetch the level | ||
const level = args.shift() | ||
let levelInfo = | ||
level === 'default' ? this.defaultLevelInfo : this.getLogLevel(level) | ||
if (levelInfo == null) { | ||
// fallback to the default log level | ||
levelInfo = this.defaultLevelInfo | ||
// as the level (first param) was not actually a level, put it back | ||
args.unshift(level) | ||
} | ||
// fetch the date | ||
const date = new Date().toISOString() | ||
// fetch the line information | ||
const lineInfo = | ||
levelInfo.levelNumber <= this.lineLevel | ||
? getCurrentLine(this.lineOffset) | ||
: { | ||
line: -1, | ||
char: -1, | ||
method: '', | ||
file: '', | ||
} | ||
// put it all together | ||
return Object.assign({ date, args }, levelInfo, lineInfo) | ||
} | ||
/** | ||
* Log the arguments into the logger stream as formatted data with debugging information. | ||
* Such that our transformers can deal with it intelligently. | ||
* | ||
* @example Inputs | ||
* ``` javascript | ||
* logger.log('note', 'this is working swell') | ||
* ``` | ||
* ``` javascript | ||
* logger.log('this', 'worked', 'swell') | ||
* ``` | ||
* | ||
* @example Results | ||
* ``` json | ||
* { | ||
* "args": ["this is working swell"], | ||
* "date": "2013-04-25T10:18:25.722Z", | ||
* "levelNumber": 5, | ||
* "levelName": "notice", | ||
* "line": "59", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
* ``` json | ||
* { | ||
* "args": ["this", "worked", "well"], | ||
* "date": "2013-04-25T10:18:26.539Z", | ||
* "levelNumber": 6, | ||
* "levelName": "info", | ||
* "line": "60", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
*/ | ||
log(...args) { | ||
this.write(args) | ||
} | ||
/** Alias for log which prefixes the error log level */ | ||
error(...args) { | ||
this.write(['error', ...args]) | ||
} | ||
/** Alias for log which prefixes the warn log level */ | ||
warn(...args) { | ||
this.write(['warn', ...args]) | ||
} | ||
/** Alias for log which prefixes the info log level */ | ||
info(...args) { | ||
this.write(['info', ...args]) | ||
} | ||
/** Alias for log which prefixes the debug log level */ | ||
debug(...args) { | ||
this.write(['debug', ...args]) | ||
} | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super(); | ||
/** | ||
* The configuration to use for the line offset. | ||
* This defaults to any file path that includes `logger`, and any method that includes the word `log`. | ||
*/ | ||
this.lineOffset = { | ||
file: /logger/i, | ||
method: /log/i, | ||
}; | ||
/** | ||
* The mapping of log level names to log level numbers. | ||
* Defaults to the RFC Log Level configuration. | ||
*/ | ||
this.levels = rfcLogLevels; | ||
/** | ||
* Only fetch line information for entries that have a log level equal to, or below this number. | ||
* You should only specify this if you need it, as fFetching line information for thousands of log entries, which is typical in large applications, will slow your application down dramatically. | ||
* If not specified, defaults to `-Infinity` which effect is to ignore gathering line information for all log levels. | ||
*/ | ||
this.lineLevel = -Infinity; | ||
// options | ||
if (opts?.lineOffset != null) | ||
this.lineOffset = opts.lineOffset; | ||
if (opts?.levels != null) | ||
this.levels = opts.levels; | ||
if (opts?.lineLevel != null) | ||
this.lineLevel = opts.lineLevel; | ||
// options: default level | ||
this.defaultLevel = opts?.defaultLevel ?? 'info'; | ||
// dereference | ||
this.levels = Object.assign({}, this.levels); | ||
} | ||
/** Set the default level info via a level number or name. */ | ||
set defaultLevel(value) { | ||
const levelInfo = this.getLogLevel(value); | ||
if (levelInfo == null) { | ||
throw new Error(`caterpillar: the intended value of ${value} for the default log level not found in the configured levels`); | ||
} | ||
this.defaultLevelInfo = levelInfo; | ||
} | ||
/** Alias for {@link getLogLevel} using the configured logger levels as reference. */ | ||
getLogLevel(value) { | ||
return getLogLevel(value, this.levels); | ||
} | ||
/** Takes an arguments array and tranforms it into a log entry. */ | ||
format(args) { | ||
// fetch the level | ||
const level = args.shift(); | ||
let levelInfo = level === 'default' ? this.defaultLevelInfo : this.getLogLevel(level); | ||
if (levelInfo == null) { | ||
// fallback to the default log level | ||
levelInfo = this.defaultLevelInfo; | ||
// as the level (first param) was not actually a level, put it back | ||
args.unshift(level); | ||
} | ||
// fetch the date | ||
const date = new Date().toISOString(); | ||
// fetch the line information | ||
const lineInfo = levelInfo.levelNumber <= this.lineLevel | ||
? getCurrentLine(this.lineOffset) | ||
: { | ||
line: -1, | ||
char: -1, | ||
method: '', | ||
file: '', | ||
}; | ||
// put it all together | ||
return Object.assign({ date, args }, levelInfo, lineInfo); | ||
} | ||
/** | ||
* Log the arguments into the logger stream as formatted data with debugging information. | ||
* Such that our transformers can deal with it intelligently. | ||
* | ||
* @example Inputs | ||
* ``` javascript | ||
* logger.log('note', 'this is working swell') | ||
* ``` | ||
* ``` javascript | ||
* logger.log('this', 'worked', 'swell') | ||
* ``` | ||
* | ||
* @example Results | ||
* ``` json | ||
* { | ||
* "args": ["this is working swell"], | ||
* "date": "2013-04-25T10:18:25.722Z", | ||
* "levelNumber": 5, | ||
* "levelName": "notice", | ||
* "line": "59", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
* ``` json | ||
* { | ||
* "args": ["this", "worked", "well"], | ||
* "date": "2013-04-25T10:18:26.539Z", | ||
* "levelNumber": 6, | ||
* "levelName": "info", | ||
* "line": "60", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
*/ | ||
log(...args) { | ||
this.write(args); | ||
} | ||
/** Alias for log which prefixes the error log level */ | ||
error(...args) { | ||
this.write(['error', ...args]); | ||
} | ||
/** Alias for log which prefixes the warn log level */ | ||
warn(...args) { | ||
this.write(['warn', ...args]); | ||
} | ||
/** Alias for log which prefixes the info log level */ | ||
info(...args) { | ||
this.write(['info', ...args]); | ||
} | ||
/** Alias for log which prefixes the debug log level */ | ||
debug(...args) { | ||
this.write(['debug', ...args]); | ||
} | ||
} | ||
export default Logger | ||
export default Logger; |
@@ -9,69 +9,73 @@ /** | ||
export class Transform { | ||
constructor() { | ||
/** Where is this Transform piping to? */ | ||
this.pipes = [] | ||
/** Maintain a write queue such that multiple Deno writes do not stall */ | ||
this.writer = Promise.resolve() | ||
} | ||
/** | ||
* Format the received log entry representation. | ||
* Your transformer should extend this. | ||
*/ | ||
format(message) { | ||
return message | ||
} | ||
/** Pipe future log entries into a caterpillar transform or a stream. */ | ||
pipe(to) { | ||
this.pipes.push(to) | ||
return to | ||
} | ||
/** Write to the child pipes. */ | ||
write(chunk) { | ||
// format now, so that we have the correct stack | ||
const data = this.format(chunk) | ||
// exclude filtered entries | ||
if (data == null) return this.writer | ||
// now delegate back to the pipe | ||
this.writer = this.writer.then(async () => { | ||
// pipe to child transforms and streams | ||
for (const pipe of this.pipes) { | ||
if (pipe instanceof Transform) { | ||
// compatibility with caterpillar transforms | ||
await pipe.write(data) | ||
} else { | ||
const str = typeof data === 'string' ? data : JSON.stringify(data) | ||
// requires typescript dom lib to define TextEncoder global | ||
if (typeof TextEncoder !== 'undefined') { | ||
// compatibility with deno and later node streams | ||
await pipe.write(new TextEncoder().encode(str)) | ||
} else { | ||
// compatibility with earlier node streams | ||
await pipe.write(str) | ||
} | ||
} | ||
} | ||
}) | ||
return this.writer | ||
} | ||
/** Close the child pipes. */ | ||
async close() { | ||
await Promise.all( | ||
this.pipes.map((pipe) => { | ||
if (pipe.close) { | ||
return pipe.close() | ||
} else if (pipe.end) { | ||
return new Promise(function (resolve) { | ||
pipe.end(resolve) | ||
}) | ||
} else { | ||
return Promise.resolve() | ||
} | ||
}) | ||
) | ||
} | ||
/* Callback alias for close */ | ||
end(cb) { | ||
const p = this.close() | ||
if (cb) p.finally(cb) | ||
} | ||
constructor() { | ||
/** Where is this Transform piping to? */ | ||
this.pipes = []; | ||
/** Maintain a write queue such that multiple Deno writes do not stall */ | ||
this.writer = Promise.resolve(); | ||
} | ||
/** | ||
* Format the received log entry representation. | ||
* Your transformer should extend this. | ||
*/ | ||
format(message) { | ||
return message; | ||
} | ||
/** Pipe future log entries into a caterpillar transform or a stream. */ | ||
pipe(to) { | ||
this.pipes.push(to); | ||
return to; | ||
} | ||
/** Write to the child pipes. */ | ||
write(chunk) { | ||
// format now, so that we have the correct stack | ||
const data = this.format(chunk); | ||
// exclude filtered entries | ||
if (data == null) | ||
return this.writer; | ||
// now delegate back to the pipe | ||
this.writer = this.writer.then(async () => { | ||
// pipe to child transforms and streams | ||
for (const pipe of this.pipes) { | ||
if (pipe instanceof Transform) { | ||
// compatibility with caterpillar transforms | ||
await pipe.write(data); | ||
} | ||
else { | ||
const str = typeof data === 'string' ? data : JSON.stringify(data); | ||
// requires typescript dom lib to define TextEncoder global | ||
if (typeof TextEncoder !== 'undefined') { | ||
// compatibility with deno and later node streams | ||
await pipe.write(new TextEncoder().encode(str)); | ||
} | ||
else { | ||
// compatibility with earlier node streams | ||
await pipe.write(str); | ||
} | ||
} | ||
} | ||
}); | ||
return this.writer; | ||
} | ||
/** Close the child pipes. */ | ||
async close() { | ||
await Promise.all(this.pipes.map((pipe) => { | ||
if (pipe.close) { | ||
return pipe.close(); | ||
} | ||
else if (pipe.end) { | ||
return new Promise(function (resolve) { | ||
pipe.end(resolve); | ||
}); | ||
} | ||
else { | ||
return Promise.resolve(); | ||
} | ||
})); | ||
} | ||
/* Callback alias for close */ | ||
end(cb) { | ||
const p = this.close(); | ||
if (cb) | ||
p.finally(cb); | ||
} | ||
} |
// this cannot be located at source/brower.ts as otherwise it would become the browser entry | ||
// Imports | ||
import { Transform } from '../transform.js' | ||
import { Transform } from '../transform.js'; | ||
/** | ||
@@ -15,103 +15,101 @@ * Convert human readable Caterpillar entries into browser compatible entries. | ||
export class Browser extends Transform { | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super() | ||
/** Whether or not we should use color. */ | ||
this.color = true | ||
/** Whether or not we should write to the browser console. */ | ||
this.output = true | ||
/** The objects that tell our browser transform how to convert terminal colours into console colours. */ | ||
this.styles = { | ||
red: { | ||
start: '31', | ||
end: '39', | ||
value: 'color:red', | ||
}, | ||
yellow: { | ||
start: '33', | ||
end: '39', | ||
value: 'color:orange', | ||
}, | ||
green: { | ||
start: '32', | ||
end: '39', | ||
value: 'color:green', | ||
}, | ||
bright: { | ||
start: '1', | ||
end: '22', | ||
value: 'font-weight:bold', | ||
}, | ||
dim: { | ||
start: '2', | ||
end: '22', | ||
value: 'color:lightGray', | ||
}, | ||
italic: { | ||
start: '3', | ||
end: '23', | ||
value: 'font-style:italic', | ||
}, | ||
underline: { | ||
start: '4', | ||
end: '24', | ||
value: 'text-decoration:underline', | ||
}, | ||
} | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.color) != null) | ||
this.color = opts.color | ||
if ((opts === null || opts === void 0 ? void 0 : opts.output) != null) | ||
this.output = opts.output | ||
if ((opts === null || opts === void 0 ? void 0 : opts.styles) != null) | ||
this.styles = opts.styles | ||
} | ||
/** | ||
* Convert a human readable Caterpillar entry into a format that browser consoles can understand. | ||
* And if the `write` config property is `true` (it is by default), write the result to the browser console. | ||
*/ | ||
format(message) { | ||
// Prepare | ||
const { color, styles, output } = this | ||
// Replace caterpillar-human formatted entry | ||
/* eslint no-control-regex:0 */ | ||
const args = [] | ||
const result = message.replace( | ||
/\u001b\[([0-9]+)m(.+?)\u001b\[([0-9]+)m/g, | ||
function (match, start, content, end) { | ||
// Check | ||
if (color === false) return content | ||
// Prepare | ||
let matchedStyle, style | ||
// Find the matcing style for this combination | ||
for (const key in styles) { | ||
if (styles.hasOwnProperty(key)) { | ||
style = styles[key] | ||
if ( | ||
String(style.start) === String(start) && | ||
String(style.end) === String(end) | ||
) { | ||
matchedStyle = style | ||
break | ||
} | ||
} | ||
} | ||
// Check | ||
if (!matchedStyle) return content | ||
// Push the style | ||
args.push(matchedStyle.value) | ||
args.push(content) | ||
args.push('color:default; font:default; text-decoration:default') | ||
return '%c%s%c' | ||
} | ||
) | ||
// Final format | ||
const parts = [result.trim()].concat(args) | ||
// Write | ||
/* eslint no-console:0 */ | ||
if (output) console.log(...parts) | ||
// Return | ||
return parts | ||
} | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super(); | ||
/** Whether or not we should use color. */ | ||
this.color = true; | ||
/** Whether or not we should write to the browser console. */ | ||
this.output = true; | ||
/** The objects that tell our browser transform how to convert terminal colours into console colours. */ | ||
this.styles = { | ||
red: { | ||
start: '31', | ||
end: '39', | ||
value: 'color:red', | ||
}, | ||
yellow: { | ||
start: '33', | ||
end: '39', | ||
value: 'color:orange', | ||
}, | ||
green: { | ||
start: '32', | ||
end: '39', | ||
value: 'color:green', | ||
}, | ||
bright: { | ||
start: '1', | ||
end: '22', | ||
value: 'font-weight:bold', | ||
}, | ||
dim: { | ||
start: '2', | ||
end: '22', | ||
value: 'color:lightGray', | ||
}, | ||
italic: { | ||
start: '3', | ||
end: '23', | ||
value: 'font-style:italic', | ||
}, | ||
underline: { | ||
start: '4', | ||
end: '24', | ||
value: 'text-decoration:underline', | ||
}, | ||
}; | ||
// options | ||
if (opts?.color != null) | ||
this.color = opts.color; | ||
if (opts?.output != null) | ||
this.output = opts.output; | ||
if (opts?.styles != null) | ||
this.styles = opts.styles; | ||
} | ||
/** | ||
* Convert a human readable Caterpillar entry into a format that browser consoles can understand. | ||
* And if the `write` config property is `true` (it is by default), write the result to the browser console. | ||
*/ | ||
format(message) { | ||
// Prepare | ||
const { color, styles, output } = this; | ||
// Replace caterpillar-human formatted entry | ||
/* eslint no-control-regex:0 */ | ||
const args = []; | ||
const result = message.replace(/\u001b\[([0-9]+)m(.+?)\u001b\[([0-9]+)m/g, function (match, start, content, end) { | ||
// Check | ||
if (color === false) | ||
return content; | ||
// Prepare | ||
let matchedStyle, style; | ||
// Find the matcing style for this combination | ||
for (const key in styles) { | ||
if (styles.hasOwnProperty(key)) { | ||
style = styles[key]; | ||
if (String(style.start) === String(start) && | ||
String(style.end) === String(end)) { | ||
matchedStyle = style; | ||
break; | ||
} | ||
} | ||
} | ||
// Check | ||
if (!matchedStyle) | ||
return content; | ||
// Push the style | ||
args.push(matchedStyle.value); | ||
args.push(content); | ||
args.push('color:default; font:default; text-decoration:default'); | ||
return '%c%s%c'; | ||
}); | ||
// Final format | ||
const parts = [result.trim()].concat(args); | ||
// Write | ||
/* eslint no-console:0 */ | ||
if (output) | ||
console.log(...parts); | ||
// Return | ||
return parts; | ||
} | ||
} | ||
export default Browser | ||
export default Browser; |
@@ -1,2 +0,2 @@ | ||
import { Transform } from '../transform.js' | ||
import { Transform } from '../transform.js'; | ||
/** | ||
@@ -19,19 +19,19 @@ * Caterpillar Filter Transform. | ||
export class Filter extends Transform { | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super() | ||
/** | ||
* Only display entries that have a log level below or equal to this number. | ||
* Defaults to `6`, which by default is the info log level. | ||
*/ | ||
this.filterLevel = 6 | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.filterLevel) != null) | ||
this.filterLevel = opts.filterLevel | ||
} | ||
/** Retain only log entries that are equal to or less than the specified filter level. */ | ||
format(entry) { | ||
return entry.levelNumber <= this.filterLevel ? entry : null | ||
} | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super(); | ||
/** | ||
* Only display entries that have a log level below or equal to this number. | ||
* Defaults to `6`, which by default is the info log level. | ||
*/ | ||
this.filterLevel = 6; | ||
// options | ||
if (opts?.filterLevel != null) | ||
this.filterLevel = opts.filterLevel; | ||
} | ||
/** Retain only log entries that are equal to or less than the specified filter level. */ | ||
format(entry) { | ||
return entry.levelNumber <= this.filterLevel ? entry : null; | ||
} | ||
} | ||
export default Filter | ||
export default Filter; |
@@ -1,4 +0,4 @@ | ||
import { Transform } from '../transform.js' | ||
import { inspect } from 'util' | ||
import * as ansi from '@bevry/ansi' | ||
import { Transform } from '../transform.js'; | ||
import { inspect } from 'util'; | ||
import * as ansi from '@bevry/ansi'; | ||
/** | ||
@@ -8,4 +8,4 @@ * Return the given argument. | ||
*/ | ||
export function noop(str) { | ||
return str | ||
function ansiNoop(a) { | ||
return a; | ||
} | ||
@@ -25,117 +25,115 @@ /** | ||
export class Human extends Transform { | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super() | ||
/** Whether or not to use colors? */ | ||
this.color = true | ||
/** Mapping of which log level numbers correspond to which colours */ | ||
this.colors = { | ||
0: 'red', | ||
1: 'red', | ||
2: 'red', | ||
3: 'red', | ||
4: 'yellow', | ||
5: 'yellow', | ||
6: 'green', | ||
7: 'green', | ||
} | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.color) != null) | ||
this.color = opts.color | ||
if ((opts === null || opts === void 0 ? void 0 : opts.colors) != null) | ||
this.colors = opts.colors | ||
} | ||
/** Get the color for the log level */ | ||
getColor(levelNumber) { | ||
// Determine | ||
const color = this.colors[levelNumber] || false | ||
// Return | ||
return color | ||
} | ||
/** Pad the left of some content if need be with the specified padding to make the content reach a certain size */ | ||
padLeft(padding, size, content) { | ||
// Prepare | ||
padding = String(padding) | ||
content = String(content) | ||
// Handle | ||
if (content.length < size) { | ||
for (let i = 0, n = size - content.length; i < n; ++i) { | ||
content = padding + content | ||
} | ||
} | ||
// Return | ||
return content | ||
} | ||
/** Convert logger entry arguments into a human readable string */ | ||
formatArguments(args) { | ||
return args | ||
.map((value) => | ||
typeof value === 'string' | ||
? value | ||
: inspect(value, { | ||
showHidden: false, | ||
depth: 10, | ||
colors: this.color, | ||
}) | ||
) | ||
.join(' ') | ||
} | ||
/** Convert a datetime into a human readable format */ | ||
formatDate(datetime) { | ||
// Prepare | ||
const now = new Date(datetime) | ||
const year = now.getFullYear() | ||
const month = this.padLeft('0', 2, now.getMonth() + 1) | ||
const date = this.padLeft('0', 2, now.getDate()) | ||
const hours = this.padLeft('0', 2, now.getHours()) | ||
const minutes = this.padLeft('0', 2, now.getMinutes()) | ||
const seconds = this.padLeft('0', 2, now.getSeconds()) | ||
const ms = this.padLeft('0', 3, now.getMilliseconds()) | ||
// Apply | ||
const result = `${year}-${month}-${date} ${hours}:${minutes}:${seconds}.${ms}` | ||
// Return | ||
return result | ||
} | ||
/** Convert a logger entry into a human readable format */ | ||
format(entry) { | ||
// Prepare | ||
const { color } = this | ||
const useLine = entry.line !== -1 | ||
let result | ||
// Format | ||
const format = { | ||
color: this.getColor(entry.levelNumber), | ||
timestamp: this.formatDate(entry.date), | ||
text: this.formatArguments(entry.args), | ||
} | ||
// Check | ||
if (format.text) { | ||
// Formatters | ||
const levelFormatter = | ||
(color && format.color && ansi[format.color]) || noop | ||
const lineFormatter = (useLine && color && ansi.dim) || noop | ||
// Message | ||
const levelString = levelFormatter(`${entry.levelName}:`) | ||
const entryString = format.text | ||
const messageString = `${levelString} ${entryString}` | ||
// Format | ||
if (useLine) { | ||
// Line Information | ||
const seperator = '\n ' | ||
const debugString = lineFormatter( | ||
`→ [${format.timestamp}] [${entry.file}:${entry.line}:${entry.char}] [${entry.method}]` | ||
) | ||
// Result | ||
result = `${messageString}${seperator}${debugString}\n` | ||
} else { | ||
// Result | ||
result = `${messageString}\n` | ||
} | ||
} else { | ||
result = format.text | ||
} | ||
// Return | ||
return result | ||
} | ||
/** Create our instance and apply our configuration options. */ | ||
constructor(opts) { | ||
super(); | ||
/** Whether or not to use colors? */ | ||
this.color = true; | ||
/** Mapping of which log level numbers correspond to which colours */ | ||
this.colors = { | ||
'0': 'red', | ||
'1': 'red', | ||
'2': 'red', | ||
'3': 'red', | ||
'4': 'yellow', | ||
'5': 'yellow', | ||
'6': 'green', | ||
'7': 'green', | ||
}; | ||
// options | ||
if (opts?.color != null) | ||
this.color = opts.color; | ||
if (opts?.colors != null) | ||
this.colors = opts.colors; | ||
} | ||
/** Get the color for the log level */ | ||
getColor(levelNumber) { | ||
// Determine | ||
const color = this.colors[levelNumber] || false; | ||
// Return | ||
return color; | ||
} | ||
/** Pad the left of some content if need be with the specified padding to make the content reach a certain size */ | ||
padLeft(padding, size, content) { | ||
// Prepare | ||
padding = String(padding); | ||
content = String(content); | ||
// Handle | ||
if (content.length < size) { | ||
for (let i = 0, n = size - content.length; i < n; ++i) { | ||
content = padding + content; | ||
} | ||
} | ||
// Return | ||
return content; | ||
} | ||
/** Convert logger entry arguments into a human readable string */ | ||
formatArguments(args) { | ||
return args | ||
.map((value) => typeof value === 'string' | ||
? value | ||
: inspect(value, { | ||
showHidden: false, | ||
depth: 10, | ||
colors: this.color, | ||
})) | ||
.join(' '); | ||
} | ||
/** Convert a datetime into a human readable format */ | ||
formatDate(datetime) { | ||
// Prepare | ||
const now = new Date(datetime); | ||
const year = now.getFullYear(); | ||
const month = this.padLeft('0', 2, now.getMonth() + 1); | ||
const date = this.padLeft('0', 2, now.getDate()); | ||
const hours = this.padLeft('0', 2, now.getHours()); | ||
const minutes = this.padLeft('0', 2, now.getMinutes()); | ||
const seconds = this.padLeft('0', 2, now.getSeconds()); | ||
const ms = this.padLeft('0', 3, now.getMilliseconds()); | ||
// Apply | ||
const result = `${year}-${month}-${date} ${hours}:${minutes}:${seconds}.${ms}`; | ||
// Return | ||
return result; | ||
} | ||
/** Convert a logger entry into a human readable format */ | ||
format(entry) { | ||
// Prepare | ||
const { color } = this; | ||
const useLine = entry.line !== -1; | ||
let result; | ||
// Format | ||
const format = { | ||
color: this.getColor(entry.levelNumber), | ||
timestamp: this.formatDate(entry.date), | ||
text: this.formatArguments(entry.args), | ||
}; | ||
// Check | ||
if (format.text) { | ||
// Formatters | ||
const levelFormatter = (color && format.color && ansi[format.color]) || ansiNoop; | ||
const lineFormatter = (useLine && color && ansi.dim) || ansiNoop; | ||
// Message | ||
// @ts-ignore | ||
const levelString = levelFormatter(`${entry.levelName}:`); | ||
const entryString = format.text; | ||
const messageString = `${levelString} ${entryString}`; | ||
// Format | ||
if (useLine) { | ||
// Line Information | ||
const seperator = '\n '; | ||
const debugString = lineFormatter(`→ [${format.timestamp}] [${entry.file}:${entry.line}:${entry.char}] [${entry.method}]`); | ||
// Result | ||
result = `${messageString}${seperator}${debugString}\n`; | ||
} | ||
else { | ||
// Result | ||
result = `${messageString}\n`; | ||
} | ||
} | ||
else { | ||
result = format.text; | ||
} | ||
// Return | ||
return result; | ||
} | ||
} | ||
export default Human | ||
export default Human; |
@@ -1,5 +0,5 @@ | ||
export * from './transform.js' | ||
export * from './logger.js' | ||
export * from './transforms/filter.js' | ||
export * from './transforms/human.js' | ||
export * from './transforms/browser.js' | ||
export * from './transform.js'; | ||
export * from './logger.js'; | ||
export * from './transforms/filter.js'; | ||
export * from './transforms/human.js'; | ||
export * from './transforms/browser.js'; |
@@ -1,4 +0,4 @@ | ||
import getLogLevel, { rfcLogLevels } from 'rfc-log-levels' | ||
import getCurrentLine from 'get-current-line' | ||
import { Transform } from './transform.js' | ||
import getLogLevel, { rfcLogLevels } from 'rfc-log-levels'; | ||
import getCurrentLine from 'get-current-line'; | ||
import { Transform } from './transform.js'; | ||
/** | ||
@@ -15,138 +15,130 @@ * Logger. | ||
export class Logger extends Transform { | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
var _a | ||
super() | ||
/** | ||
* The configuration to use for the line offset. | ||
* This defaults to any file path that includes `logger`, and any method that includes the word `log`. | ||
*/ | ||
this.lineOffset = { | ||
file: /logger/i, | ||
method: /log/i, | ||
} | ||
/** | ||
* The mapping of log level names to log level numbers. | ||
* Defaults to the RFC Log Level configuration. | ||
*/ | ||
this.levels = rfcLogLevels | ||
/** | ||
* Only fetch line information for entries that have a log level equal to, or below this number. | ||
* You should only specify this if you need it, as fFetching line information for thousands of log entries, which is typical in large applications, will slow your application down dramatically. | ||
* If not specified, defaults to `-Infinity` which effect is to ignore gathering line information for all log levels. | ||
*/ | ||
this.lineLevel = -Infinity | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.lineOffset) != null) | ||
this.lineOffset = opts.lineOffset | ||
if ((opts === null || opts === void 0 ? void 0 : opts.levels) != null) | ||
this.levels = opts.levels | ||
if ((opts === null || opts === void 0 ? void 0 : opts.lineLevel) != null) | ||
this.lineLevel = opts.lineLevel | ||
// options: default level | ||
this.defaultLevel = | ||
(_a = opts === null || opts === void 0 ? void 0 : opts.defaultLevel) !== | ||
null && _a !== void 0 | ||
? _a | ||
: 'info' | ||
// dereference | ||
this.levels = Object.assign({}, this.levels) | ||
} | ||
/** Set the default level info via a level number or name. */ | ||
set defaultLevel(value) { | ||
const levelInfo = this.getLogLevel(value) | ||
if (levelInfo == null) { | ||
throw new Error( | ||
`caterpillar: the intended value of ${value} for the default log level not found in the configured levels` | ||
) | ||
} | ||
this.defaultLevelInfo = levelInfo | ||
} | ||
/** Alias for {@link getLogLevel} using the configured logger levels as reference. */ | ||
getLogLevel(value) { | ||
return getLogLevel(value, this.levels) | ||
} | ||
/** Takes an arguments array and tranforms it into a log entry. */ | ||
format(args) { | ||
// fetch the level | ||
const level = args.shift() | ||
let levelInfo = | ||
level === 'default' ? this.defaultLevelInfo : this.getLogLevel(level) | ||
if (levelInfo == null) { | ||
// fallback to the default log level | ||
levelInfo = this.defaultLevelInfo | ||
// as the level (first param) was not actually a level, put it back | ||
args.unshift(level) | ||
} | ||
// fetch the date | ||
const date = new Date().toISOString() | ||
// fetch the line information | ||
const lineInfo = | ||
levelInfo.levelNumber <= this.lineLevel | ||
? getCurrentLine(this.lineOffset) | ||
: { | ||
line: -1, | ||
char: -1, | ||
method: '', | ||
file: '', | ||
} | ||
// put it all together | ||
return Object.assign({ date, args }, levelInfo, lineInfo) | ||
} | ||
/** | ||
* Log the arguments into the logger stream as formatted data with debugging information. | ||
* Such that our transformers can deal with it intelligently. | ||
* | ||
* @example Inputs | ||
* ``` javascript | ||
* logger.log('note', 'this is working swell') | ||
* ``` | ||
* ``` javascript | ||
* logger.log('this', 'worked', 'swell') | ||
* ``` | ||
* | ||
* @example Results | ||
* ``` json | ||
* { | ||
* "args": ["this is working swell"], | ||
* "date": "2013-04-25T10:18:25.722Z", | ||
* "levelNumber": 5, | ||
* "levelName": "notice", | ||
* "line": "59", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
* ``` json | ||
* { | ||
* "args": ["this", "worked", "well"], | ||
* "date": "2013-04-25T10:18:26.539Z", | ||
* "levelNumber": 6, | ||
* "levelName": "info", | ||
* "line": "60", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
*/ | ||
log(...args) { | ||
this.write(args) | ||
} | ||
/** Alias for log which prefixes the error log level */ | ||
error(...args) { | ||
this.write(['error', ...args]) | ||
} | ||
/** Alias for log which prefixes the warn log level */ | ||
warn(...args) { | ||
this.write(['warn', ...args]) | ||
} | ||
/** Alias for log which prefixes the info log level */ | ||
info(...args) { | ||
this.write(['info', ...args]) | ||
} | ||
/** Alias for log which prefixes the debug log level */ | ||
debug(...args) { | ||
this.write(['debug', ...args]) | ||
} | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
var _a; | ||
super(); | ||
/** | ||
* The configuration to use for the line offset. | ||
* This defaults to any file path that includes `logger`, and any method that includes the word `log`. | ||
*/ | ||
this.lineOffset = { | ||
file: /logger/i, | ||
method: /log/i, | ||
}; | ||
/** | ||
* The mapping of log level names to log level numbers. | ||
* Defaults to the RFC Log Level configuration. | ||
*/ | ||
this.levels = rfcLogLevels; | ||
/** | ||
* Only fetch line information for entries that have a log level equal to, or below this number. | ||
* You should only specify this if you need it, as fFetching line information for thousands of log entries, which is typical in large applications, will slow your application down dramatically. | ||
* If not specified, defaults to `-Infinity` which effect is to ignore gathering line information for all log levels. | ||
*/ | ||
this.lineLevel = -Infinity; | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.lineOffset) != null) | ||
this.lineOffset = opts.lineOffset; | ||
if ((opts === null || opts === void 0 ? void 0 : opts.levels) != null) | ||
this.levels = opts.levels; | ||
if ((opts === null || opts === void 0 ? void 0 : opts.lineLevel) != null) | ||
this.lineLevel = opts.lineLevel; | ||
// options: default level | ||
this.defaultLevel = (_a = opts === null || opts === void 0 ? void 0 : opts.defaultLevel) !== null && _a !== void 0 ? _a : 'info'; | ||
// dereference | ||
this.levels = Object.assign({}, this.levels); | ||
} | ||
/** Set the default level info via a level number or name. */ | ||
set defaultLevel(value) { | ||
const levelInfo = this.getLogLevel(value); | ||
if (levelInfo == null) { | ||
throw new Error(`caterpillar: the intended value of ${value} for the default log level not found in the configured levels`); | ||
} | ||
this.defaultLevelInfo = levelInfo; | ||
} | ||
/** Alias for {@link getLogLevel} using the configured logger levels as reference. */ | ||
getLogLevel(value) { | ||
return getLogLevel(value, this.levels); | ||
} | ||
/** Takes an arguments array and tranforms it into a log entry. */ | ||
format(args) { | ||
// fetch the level | ||
const level = args.shift(); | ||
let levelInfo = level === 'default' ? this.defaultLevelInfo : this.getLogLevel(level); | ||
if (levelInfo == null) { | ||
// fallback to the default log level | ||
levelInfo = this.defaultLevelInfo; | ||
// as the level (first param) was not actually a level, put it back | ||
args.unshift(level); | ||
} | ||
// fetch the date | ||
const date = new Date().toISOString(); | ||
// fetch the line information | ||
const lineInfo = levelInfo.levelNumber <= this.lineLevel | ||
? getCurrentLine(this.lineOffset) | ||
: { | ||
line: -1, | ||
char: -1, | ||
method: '', | ||
file: '', | ||
}; | ||
// put it all together | ||
return Object.assign({ date, args }, levelInfo, lineInfo); | ||
} | ||
/** | ||
* Log the arguments into the logger stream as formatted data with debugging information. | ||
* Such that our transformers can deal with it intelligently. | ||
* | ||
* @example Inputs | ||
* ``` javascript | ||
* logger.log('note', 'this is working swell') | ||
* ``` | ||
* ``` javascript | ||
* logger.log('this', 'worked', 'swell') | ||
* ``` | ||
* | ||
* @example Results | ||
* ``` json | ||
* { | ||
* "args": ["this is working swell"], | ||
* "date": "2013-04-25T10:18:25.722Z", | ||
* "levelNumber": 5, | ||
* "levelName": "notice", | ||
* "line": "59", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
* ``` json | ||
* { | ||
* "args": ["this", "worked", "well"], | ||
* "date": "2013-04-25T10:18:26.539Z", | ||
* "levelNumber": 6, | ||
* "levelName": "info", | ||
* "line": "60", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
*/ | ||
log(...args) { | ||
this.write(args); | ||
} | ||
/** Alias for log which prefixes the error log level */ | ||
error(...args) { | ||
this.write(['error', ...args]); | ||
} | ||
/** Alias for log which prefixes the warn log level */ | ||
warn(...args) { | ||
this.write(['warn', ...args]); | ||
} | ||
/** Alias for log which prefixes the info log level */ | ||
info(...args) { | ||
this.write(['info', ...args]); | ||
} | ||
/** Alias for log which prefixes the debug log level */ | ||
debug(...args) { | ||
this.write(['debug', ...args]); | ||
} | ||
} | ||
export default Logger | ||
export default Logger; |
@@ -1,3 +0,1 @@ | ||
{ | ||
"type": "module" | ||
} | ||
{"type": "module"} |
@@ -9,69 +9,73 @@ /** | ||
export class Transform { | ||
constructor() { | ||
/** Where is this Transform piping to? */ | ||
this.pipes = [] | ||
/** Maintain a write queue such that multiple Deno writes do not stall */ | ||
this.writer = Promise.resolve() | ||
} | ||
/** | ||
* Format the received log entry representation. | ||
* Your transformer should extend this. | ||
*/ | ||
format(message) { | ||
return message | ||
} | ||
/** Pipe future log entries into a caterpillar transform or a stream. */ | ||
pipe(to) { | ||
this.pipes.push(to) | ||
return to | ||
} | ||
/** Write to the child pipes. */ | ||
write(chunk) { | ||
// format now, so that we have the correct stack | ||
const data = this.format(chunk) | ||
// exclude filtered entries | ||
if (data == null) return this.writer | ||
// now delegate back to the pipe | ||
this.writer = this.writer.then(async () => { | ||
// pipe to child transforms and streams | ||
for (const pipe of this.pipes) { | ||
if (pipe instanceof Transform) { | ||
// compatibility with caterpillar transforms | ||
await pipe.write(data) | ||
} else { | ||
const str = typeof data === 'string' ? data : JSON.stringify(data) | ||
// requires typescript dom lib to define TextEncoder global | ||
if (typeof TextEncoder !== 'undefined') { | ||
// compatibility with deno and later node streams | ||
await pipe.write(new TextEncoder().encode(str)) | ||
} else { | ||
// compatibility with earlier node streams | ||
await pipe.write(str) | ||
} | ||
} | ||
} | ||
}) | ||
return this.writer | ||
} | ||
/** Close the child pipes. */ | ||
async close() { | ||
await Promise.all( | ||
this.pipes.map((pipe) => { | ||
if (pipe.close) { | ||
return pipe.close() | ||
} else if (pipe.end) { | ||
return new Promise(function (resolve) { | ||
pipe.end(resolve) | ||
}) | ||
} else { | ||
return Promise.resolve() | ||
} | ||
}) | ||
) | ||
} | ||
/* Callback alias for close */ | ||
end(cb) { | ||
const p = this.close() | ||
if (cb) p.finally(cb) | ||
} | ||
constructor() { | ||
/** Where is this Transform piping to? */ | ||
this.pipes = []; | ||
/** Maintain a write queue such that multiple Deno writes do not stall */ | ||
this.writer = Promise.resolve(); | ||
} | ||
/** | ||
* Format the received log entry representation. | ||
* Your transformer should extend this. | ||
*/ | ||
format(message) { | ||
return message; | ||
} | ||
/** Pipe future log entries into a caterpillar transform or a stream. */ | ||
pipe(to) { | ||
this.pipes.push(to); | ||
return to; | ||
} | ||
/** Write to the child pipes. */ | ||
write(chunk) { | ||
// format now, so that we have the correct stack | ||
const data = this.format(chunk); | ||
// exclude filtered entries | ||
if (data == null) | ||
return this.writer; | ||
// now delegate back to the pipe | ||
this.writer = this.writer.then(async () => { | ||
// pipe to child transforms and streams | ||
for (const pipe of this.pipes) { | ||
if (pipe instanceof Transform) { | ||
// compatibility with caterpillar transforms | ||
await pipe.write(data); | ||
} | ||
else { | ||
const str = typeof data === 'string' ? data : JSON.stringify(data); | ||
// requires typescript dom lib to define TextEncoder global | ||
if (typeof TextEncoder !== 'undefined') { | ||
// compatibility with deno and later node streams | ||
await pipe.write(new TextEncoder().encode(str)); | ||
} | ||
else { | ||
// compatibility with earlier node streams | ||
await pipe.write(str); | ||
} | ||
} | ||
} | ||
}); | ||
return this.writer; | ||
} | ||
/** Close the child pipes. */ | ||
async close() { | ||
await Promise.all(this.pipes.map((pipe) => { | ||
if (pipe.close) { | ||
return pipe.close(); | ||
} | ||
else if (pipe.end) { | ||
return new Promise(function (resolve) { | ||
pipe.end(resolve); | ||
}); | ||
} | ||
else { | ||
return Promise.resolve(); | ||
} | ||
})); | ||
} | ||
/* Callback alias for close */ | ||
end(cb) { | ||
const p = this.close(); | ||
if (cb) | ||
p.finally(cb); | ||
} | ||
} |
// this cannot be located at source/brower.ts as otherwise it would become the browser entry | ||
// Imports | ||
import { Transform } from '../transform.js' | ||
import { Transform } from '../transform.js'; | ||
/** | ||
@@ -15,103 +15,101 @@ * Convert human readable Caterpillar entries into browser compatible entries. | ||
export class Browser extends Transform { | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super() | ||
/** Whether or not we should use color. */ | ||
this.color = true | ||
/** Whether or not we should write to the browser console. */ | ||
this.output = true | ||
/** The objects that tell our browser transform how to convert terminal colours into console colours. */ | ||
this.styles = { | ||
red: { | ||
start: '31', | ||
end: '39', | ||
value: 'color:red', | ||
}, | ||
yellow: { | ||
start: '33', | ||
end: '39', | ||
value: 'color:orange', | ||
}, | ||
green: { | ||
start: '32', | ||
end: '39', | ||
value: 'color:green', | ||
}, | ||
bright: { | ||
start: '1', | ||
end: '22', | ||
value: 'font-weight:bold', | ||
}, | ||
dim: { | ||
start: '2', | ||
end: '22', | ||
value: 'color:lightGray', | ||
}, | ||
italic: { | ||
start: '3', | ||
end: '23', | ||
value: 'font-style:italic', | ||
}, | ||
underline: { | ||
start: '4', | ||
end: '24', | ||
value: 'text-decoration:underline', | ||
}, | ||
} | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.color) != null) | ||
this.color = opts.color | ||
if ((opts === null || opts === void 0 ? void 0 : opts.output) != null) | ||
this.output = opts.output | ||
if ((opts === null || opts === void 0 ? void 0 : opts.styles) != null) | ||
this.styles = opts.styles | ||
} | ||
/** | ||
* Convert a human readable Caterpillar entry into a format that browser consoles can understand. | ||
* And if the `write` config property is `true` (it is by default), write the result to the browser console. | ||
*/ | ||
format(message) { | ||
// Prepare | ||
const { color, styles, output } = this | ||
// Replace caterpillar-human formatted entry | ||
/* eslint no-control-regex:0 */ | ||
const args = [] | ||
const result = message.replace( | ||
/\u001b\[([0-9]+)m(.+?)\u001b\[([0-9]+)m/g, | ||
function (match, start, content, end) { | ||
// Check | ||
if (color === false) return content | ||
// Prepare | ||
let matchedStyle, style | ||
// Find the matcing style for this combination | ||
for (const key in styles) { | ||
if (styles.hasOwnProperty(key)) { | ||
style = styles[key] | ||
if ( | ||
String(style.start) === String(start) && | ||
String(style.end) === String(end) | ||
) { | ||
matchedStyle = style | ||
break | ||
} | ||
} | ||
} | ||
// Check | ||
if (!matchedStyle) return content | ||
// Push the style | ||
args.push(matchedStyle.value) | ||
args.push(content) | ||
args.push('color:default; font:default; text-decoration:default') | ||
return '%c%s%c' | ||
} | ||
) | ||
// Final format | ||
const parts = [result.trim()].concat(args) | ||
// Write | ||
/* eslint no-console:0 */ | ||
if (output) console.log(...parts) | ||
// Return | ||
return parts | ||
} | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super(); | ||
/** Whether or not we should use color. */ | ||
this.color = true; | ||
/** Whether or not we should write to the browser console. */ | ||
this.output = true; | ||
/** The objects that tell our browser transform how to convert terminal colours into console colours. */ | ||
this.styles = { | ||
red: { | ||
start: '31', | ||
end: '39', | ||
value: 'color:red', | ||
}, | ||
yellow: { | ||
start: '33', | ||
end: '39', | ||
value: 'color:orange', | ||
}, | ||
green: { | ||
start: '32', | ||
end: '39', | ||
value: 'color:green', | ||
}, | ||
bright: { | ||
start: '1', | ||
end: '22', | ||
value: 'font-weight:bold', | ||
}, | ||
dim: { | ||
start: '2', | ||
end: '22', | ||
value: 'color:lightGray', | ||
}, | ||
italic: { | ||
start: '3', | ||
end: '23', | ||
value: 'font-style:italic', | ||
}, | ||
underline: { | ||
start: '4', | ||
end: '24', | ||
value: 'text-decoration:underline', | ||
}, | ||
}; | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.color) != null) | ||
this.color = opts.color; | ||
if ((opts === null || opts === void 0 ? void 0 : opts.output) != null) | ||
this.output = opts.output; | ||
if ((opts === null || opts === void 0 ? void 0 : opts.styles) != null) | ||
this.styles = opts.styles; | ||
} | ||
/** | ||
* Convert a human readable Caterpillar entry into a format that browser consoles can understand. | ||
* And if the `write` config property is `true` (it is by default), write the result to the browser console. | ||
*/ | ||
format(message) { | ||
// Prepare | ||
const { color, styles, output } = this; | ||
// Replace caterpillar-human formatted entry | ||
/* eslint no-control-regex:0 */ | ||
const args = []; | ||
const result = message.replace(/\u001b\[([0-9]+)m(.+?)\u001b\[([0-9]+)m/g, function (match, start, content, end) { | ||
// Check | ||
if (color === false) | ||
return content; | ||
// Prepare | ||
let matchedStyle, style; | ||
// Find the matcing style for this combination | ||
for (const key in styles) { | ||
if (styles.hasOwnProperty(key)) { | ||
style = styles[key]; | ||
if (String(style.start) === String(start) && | ||
String(style.end) === String(end)) { | ||
matchedStyle = style; | ||
break; | ||
} | ||
} | ||
} | ||
// Check | ||
if (!matchedStyle) | ||
return content; | ||
// Push the style | ||
args.push(matchedStyle.value); | ||
args.push(content); | ||
args.push('color:default; font:default; text-decoration:default'); | ||
return '%c%s%c'; | ||
}); | ||
// Final format | ||
const parts = [result.trim()].concat(args); | ||
// Write | ||
/* eslint no-console:0 */ | ||
if (output) | ||
console.log(...parts); | ||
// Return | ||
return parts; | ||
} | ||
} | ||
export default Browser | ||
export default Browser; |
@@ -1,2 +0,2 @@ | ||
import { Transform } from '../transform.js' | ||
import { Transform } from '../transform.js'; | ||
/** | ||
@@ -19,19 +19,19 @@ * Caterpillar Filter Transform. | ||
export class Filter extends Transform { | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super() | ||
/** | ||
* Only display entries that have a log level below or equal to this number. | ||
* Defaults to `6`, which by default is the info log level. | ||
*/ | ||
this.filterLevel = 6 | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.filterLevel) != null) | ||
this.filterLevel = opts.filterLevel | ||
} | ||
/** Retain only log entries that are equal to or less than the specified filter level. */ | ||
format(entry) { | ||
return entry.levelNumber <= this.filterLevel ? entry : null | ||
} | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super(); | ||
/** | ||
* Only display entries that have a log level below or equal to this number. | ||
* Defaults to `6`, which by default is the info log level. | ||
*/ | ||
this.filterLevel = 6; | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.filterLevel) != null) | ||
this.filterLevel = opts.filterLevel; | ||
} | ||
/** Retain only log entries that are equal to or less than the specified filter level. */ | ||
format(entry) { | ||
return entry.levelNumber <= this.filterLevel ? entry : null; | ||
} | ||
} | ||
export default Filter | ||
export default Filter; |
@@ -1,4 +0,4 @@ | ||
import { Transform } from '../transform.js' | ||
import { inspect } from 'util' | ||
import * as ansi from '@bevry/ansi' | ||
import { Transform } from '../transform.js'; | ||
import { inspect } from 'util'; | ||
import * as ansi from '@bevry/ansi'; | ||
/** | ||
@@ -8,4 +8,4 @@ * Return the given argument. | ||
*/ | ||
export function noop(str) { | ||
return str | ||
function ansiNoop(a) { | ||
return a; | ||
} | ||
@@ -25,117 +25,115 @@ /** | ||
export class Human extends Transform { | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super() | ||
/** Whether or not to use colors? */ | ||
this.color = true | ||
/** Mapping of which log level numbers correspond to which colours */ | ||
this.colors = { | ||
0: 'red', | ||
1: 'red', | ||
2: 'red', | ||
3: 'red', | ||
4: 'yellow', | ||
5: 'yellow', | ||
6: 'green', | ||
7: 'green', | ||
} | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.color) != null) | ||
this.color = opts.color | ||
if ((opts === null || opts === void 0 ? void 0 : opts.colors) != null) | ||
this.colors = opts.colors | ||
} | ||
/** Get the color for the log level */ | ||
getColor(levelNumber) { | ||
// Determine | ||
const color = this.colors[levelNumber] || false | ||
// Return | ||
return color | ||
} | ||
/** Pad the left of some content if need be with the specified padding to make the content reach a certain size */ | ||
padLeft(padding, size, content) { | ||
// Prepare | ||
padding = String(padding) | ||
content = String(content) | ||
// Handle | ||
if (content.length < size) { | ||
for (let i = 0, n = size - content.length; i < n; ++i) { | ||
content = padding + content | ||
} | ||
} | ||
// Return | ||
return content | ||
} | ||
/** Convert logger entry arguments into a human readable string */ | ||
formatArguments(args) { | ||
return args | ||
.map((value) => | ||
typeof value === 'string' | ||
? value | ||
: inspect(value, { | ||
showHidden: false, | ||
depth: 10, | ||
colors: this.color, | ||
}) | ||
) | ||
.join(' ') | ||
} | ||
/** Convert a datetime into a human readable format */ | ||
formatDate(datetime) { | ||
// Prepare | ||
const now = new Date(datetime) | ||
const year = now.getFullYear() | ||
const month = this.padLeft('0', 2, now.getMonth() + 1) | ||
const date = this.padLeft('0', 2, now.getDate()) | ||
const hours = this.padLeft('0', 2, now.getHours()) | ||
const minutes = this.padLeft('0', 2, now.getMinutes()) | ||
const seconds = this.padLeft('0', 2, now.getSeconds()) | ||
const ms = this.padLeft('0', 3, now.getMilliseconds()) | ||
// Apply | ||
const result = `${year}-${month}-${date} ${hours}:${minutes}:${seconds}.${ms}` | ||
// Return | ||
return result | ||
} | ||
/** Convert a logger entry into a human readable format */ | ||
format(entry) { | ||
// Prepare | ||
const { color } = this | ||
const useLine = entry.line !== -1 | ||
let result | ||
// Format | ||
const format = { | ||
color: this.getColor(entry.levelNumber), | ||
timestamp: this.formatDate(entry.date), | ||
text: this.formatArguments(entry.args), | ||
} | ||
// Check | ||
if (format.text) { | ||
// Formatters | ||
const levelFormatter = | ||
(color && format.color && ansi[format.color]) || noop | ||
const lineFormatter = (useLine && color && ansi.dim) || noop | ||
// Message | ||
const levelString = levelFormatter(`${entry.levelName}:`) | ||
const entryString = format.text | ||
const messageString = `${levelString} ${entryString}` | ||
// Format | ||
if (useLine) { | ||
// Line Information | ||
const seperator = '\n ' | ||
const debugString = lineFormatter( | ||
`→ [${format.timestamp}] [${entry.file}:${entry.line}:${entry.char}] [${entry.method}]` | ||
) | ||
// Result | ||
result = `${messageString}${seperator}${debugString}\n` | ||
} else { | ||
// Result | ||
result = `${messageString}\n` | ||
} | ||
} else { | ||
result = format.text | ||
} | ||
// Return | ||
return result | ||
} | ||
/** Create our instance and apply our configuration options. */ | ||
constructor(opts) { | ||
super(); | ||
/** Whether or not to use colors? */ | ||
this.color = true; | ||
/** Mapping of which log level numbers correspond to which colours */ | ||
this.colors = { | ||
'0': 'red', | ||
'1': 'red', | ||
'2': 'red', | ||
'3': 'red', | ||
'4': 'yellow', | ||
'5': 'yellow', | ||
'6': 'green', | ||
'7': 'green', | ||
}; | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.color) != null) | ||
this.color = opts.color; | ||
if ((opts === null || opts === void 0 ? void 0 : opts.colors) != null) | ||
this.colors = opts.colors; | ||
} | ||
/** Get the color for the log level */ | ||
getColor(levelNumber) { | ||
// Determine | ||
const color = this.colors[levelNumber] || false; | ||
// Return | ||
return color; | ||
} | ||
/** Pad the left of some content if need be with the specified padding to make the content reach a certain size */ | ||
padLeft(padding, size, content) { | ||
// Prepare | ||
padding = String(padding); | ||
content = String(content); | ||
// Handle | ||
if (content.length < size) { | ||
for (let i = 0, n = size - content.length; i < n; ++i) { | ||
content = padding + content; | ||
} | ||
} | ||
// Return | ||
return content; | ||
} | ||
/** Convert logger entry arguments into a human readable string */ | ||
formatArguments(args) { | ||
return args | ||
.map((value) => typeof value === 'string' | ||
? value | ||
: inspect(value, { | ||
showHidden: false, | ||
depth: 10, | ||
colors: this.color, | ||
})) | ||
.join(' '); | ||
} | ||
/** Convert a datetime into a human readable format */ | ||
formatDate(datetime) { | ||
// Prepare | ||
const now = new Date(datetime); | ||
const year = now.getFullYear(); | ||
const month = this.padLeft('0', 2, now.getMonth() + 1); | ||
const date = this.padLeft('0', 2, now.getDate()); | ||
const hours = this.padLeft('0', 2, now.getHours()); | ||
const minutes = this.padLeft('0', 2, now.getMinutes()); | ||
const seconds = this.padLeft('0', 2, now.getSeconds()); | ||
const ms = this.padLeft('0', 3, now.getMilliseconds()); | ||
// Apply | ||
const result = `${year}-${month}-${date} ${hours}:${minutes}:${seconds}.${ms}`; | ||
// Return | ||
return result; | ||
} | ||
/** Convert a logger entry into a human readable format */ | ||
format(entry) { | ||
// Prepare | ||
const { color } = this; | ||
const useLine = entry.line !== -1; | ||
let result; | ||
// Format | ||
const format = { | ||
color: this.getColor(entry.levelNumber), | ||
timestamp: this.formatDate(entry.date), | ||
text: this.formatArguments(entry.args), | ||
}; | ||
// Check | ||
if (format.text) { | ||
// Formatters | ||
const levelFormatter = (color && format.color && ansi[format.color]) || ansiNoop; | ||
const lineFormatter = (useLine && color && ansi.dim) || ansiNoop; | ||
// Message | ||
// @ts-ignore | ||
const levelString = levelFormatter(`${entry.levelName}:`); | ||
const entryString = format.text; | ||
const messageString = `${levelString} ${entryString}`; | ||
// Format | ||
if (useLine) { | ||
// Line Information | ||
const seperator = '\n '; | ||
const debugString = lineFormatter(`→ [${format.timestamp}] [${entry.file}:${entry.line}:${entry.char}] [${entry.method}]`); | ||
// Result | ||
result = `${messageString}${seperator}${debugString}\n`; | ||
} | ||
else { | ||
// Result | ||
result = `${messageString}\n`; | ||
} | ||
} | ||
else { | ||
result = format.text; | ||
} | ||
// Return | ||
return result; | ||
} | ||
} | ||
export default Human | ||
export default Human; |
@@ -1,30 +0,17 @@ | ||
'use strict' | ||
var __createBinding = | ||
(this && this.__createBinding) || | ||
(Object.create | ||
? function (o, m, k, k2) { | ||
if (k2 === undefined) k2 = k | ||
Object.defineProperty(o, k2, { | ||
enumerable: true, | ||
get: function () { | ||
return m[k] | ||
}, | ||
}) | ||
} | ||
: function (o, m, k, k2) { | ||
if (k2 === undefined) k2 = k | ||
o[k2] = m[k] | ||
}) | ||
var __exportStar = | ||
(this && this.__exportStar) || | ||
function (m, exports) { | ||
for (var p in m) | ||
if (p !== 'default' && !Object.prototype.hasOwnProperty.call(exports, p)) | ||
__createBinding(exports, m, p) | ||
} | ||
Object.defineProperty(exports, '__esModule', { value: true }) | ||
__exportStar(require('./transform.js'), exports) | ||
__exportStar(require('./logger.js'), exports) | ||
__exportStar(require('./transforms/filter.js'), exports) | ||
__exportStar(require('./transforms/human.js'), exports) | ||
__exportStar(require('./transforms/browser.js'), exports) | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./transform.js"), exports); | ||
__exportStar(require("./logger.js"), exports); | ||
__exportStar(require("./transforms/filter.js"), exports); | ||
__exportStar(require("./transforms/human.js"), exports); | ||
__exportStar(require("./transforms/browser.js"), exports); |
@@ -1,49 +0,29 @@ | ||
'use strict' | ||
var __createBinding = | ||
(this && this.__createBinding) || | ||
(Object.create | ||
? function (o, m, k, k2) { | ||
if (k2 === undefined) k2 = k | ||
Object.defineProperty(o, k2, { | ||
enumerable: true, | ||
get: function () { | ||
return m[k] | ||
}, | ||
}) | ||
} | ||
: function (o, m, k, k2) { | ||
if (k2 === undefined) k2 = k | ||
o[k2] = m[k] | ||
}) | ||
var __setModuleDefault = | ||
(this && this.__setModuleDefault) || | ||
(Object.create | ||
? function (o, v) { | ||
Object.defineProperty(o, 'default', { enumerable: true, value: v }) | ||
} | ||
: function (o, v) { | ||
o['default'] = v | ||
}) | ||
var __importStar = | ||
(this && this.__importStar) || | ||
function (mod) { | ||
if (mod && mod.__esModule) return mod | ||
var result = {} | ||
if (mod != null) | ||
for (var k in mod) | ||
if (k !== 'default' && Object.prototype.hasOwnProperty.call(mod, k)) | ||
__createBinding(result, mod, k) | ||
__setModuleDefault(result, mod) | ||
return result | ||
} | ||
var __importDefault = | ||
(this && this.__importDefault) || | ||
function (mod) { | ||
return mod && mod.__esModule ? mod : { default: mod } | ||
} | ||
Object.defineProperty(exports, '__esModule', { value: true }) | ||
exports.Logger = void 0 | ||
const rfc_log_levels_1 = __importStar(require('rfc-log-levels')) | ||
const get_current_line_1 = __importDefault(require('get-current-line')) | ||
const transform_js_1 = require('./transform.js') | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Logger = void 0; | ||
const rfc_log_levels_1 = __importStar(require("rfc-log-levels")); | ||
const get_current_line_1 = __importDefault(require("get-current-line")); | ||
const transform_js_1 = require("./transform.js"); | ||
/** | ||
@@ -60,139 +40,131 @@ * Logger. | ||
class Logger extends transform_js_1.Transform { | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
var _a | ||
super() | ||
/** | ||
* The configuration to use for the line offset. | ||
* This defaults to any file path that includes `logger`, and any method that includes the word `log`. | ||
*/ | ||
this.lineOffset = { | ||
file: /logger/i, | ||
method: /log/i, | ||
} | ||
/** | ||
* The mapping of log level names to log level numbers. | ||
* Defaults to the RFC Log Level configuration. | ||
*/ | ||
this.levels = rfc_log_levels_1.rfcLogLevels | ||
/** | ||
* Only fetch line information for entries that have a log level equal to, or below this number. | ||
* You should only specify this if you need it, as fFetching line information for thousands of log entries, which is typical in large applications, will slow your application down dramatically. | ||
* If not specified, defaults to `-Infinity` which effect is to ignore gathering line information for all log levels. | ||
*/ | ||
this.lineLevel = -Infinity | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.lineOffset) != null) | ||
this.lineOffset = opts.lineOffset | ||
if ((opts === null || opts === void 0 ? void 0 : opts.levels) != null) | ||
this.levels = opts.levels | ||
if ((opts === null || opts === void 0 ? void 0 : opts.lineLevel) != null) | ||
this.lineLevel = opts.lineLevel | ||
// options: default level | ||
this.defaultLevel = | ||
(_a = opts === null || opts === void 0 ? void 0 : opts.defaultLevel) !== | ||
null && _a !== void 0 | ||
? _a | ||
: 'info' | ||
// dereference | ||
this.levels = Object.assign({}, this.levels) | ||
} | ||
/** Set the default level info via a level number or name. */ | ||
set defaultLevel(value) { | ||
const levelInfo = this.getLogLevel(value) | ||
if (levelInfo == null) { | ||
throw new Error( | ||
`caterpillar: the intended value of ${value} for the default log level not found in the configured levels` | ||
) | ||
} | ||
this.defaultLevelInfo = levelInfo | ||
} | ||
/** Alias for {@link getLogLevel} using the configured logger levels as reference. */ | ||
getLogLevel(value) { | ||
return rfc_log_levels_1.default(value, this.levels) | ||
} | ||
/** Takes an arguments array and tranforms it into a log entry. */ | ||
format(args) { | ||
// fetch the level | ||
const level = args.shift() | ||
let levelInfo = | ||
level === 'default' ? this.defaultLevelInfo : this.getLogLevel(level) | ||
if (levelInfo == null) { | ||
// fallback to the default log level | ||
levelInfo = this.defaultLevelInfo | ||
// as the level (first param) was not actually a level, put it back | ||
args.unshift(level) | ||
} | ||
// fetch the date | ||
const date = new Date().toISOString() | ||
// fetch the line information | ||
const lineInfo = | ||
levelInfo.levelNumber <= this.lineLevel | ||
? get_current_line_1.default(this.lineOffset) | ||
: { | ||
line: -1, | ||
char: -1, | ||
method: '', | ||
file: '', | ||
} | ||
// put it all together | ||
return Object.assign({ date, args }, levelInfo, lineInfo) | ||
} | ||
/** | ||
* Log the arguments into the logger stream as formatted data with debugging information. | ||
* Such that our transformers can deal with it intelligently. | ||
* | ||
* @example Inputs | ||
* ``` javascript | ||
* logger.log('note', 'this is working swell') | ||
* ``` | ||
* ``` javascript | ||
* logger.log('this', 'worked', 'swell') | ||
* ``` | ||
* | ||
* @example Results | ||
* ``` json | ||
* { | ||
* "args": ["this is working swell"], | ||
* "date": "2013-04-25T10:18:25.722Z", | ||
* "levelNumber": 5, | ||
* "levelName": "notice", | ||
* "line": "59", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
* ``` json | ||
* { | ||
* "args": ["this", "worked", "well"], | ||
* "date": "2013-04-25T10:18:26.539Z", | ||
* "levelNumber": 6, | ||
* "levelName": "info", | ||
* "line": "60", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
*/ | ||
log(...args) { | ||
this.write(args) | ||
} | ||
/** Alias for log which prefixes the error log level */ | ||
error(...args) { | ||
this.write(['error', ...args]) | ||
} | ||
/** Alias for log which prefixes the warn log level */ | ||
warn(...args) { | ||
this.write(['warn', ...args]) | ||
} | ||
/** Alias for log which prefixes the info log level */ | ||
info(...args) { | ||
this.write(['info', ...args]) | ||
} | ||
/** Alias for log which prefixes the debug log level */ | ||
debug(...args) { | ||
this.write(['debug', ...args]) | ||
} | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
var _a; | ||
super(); | ||
/** | ||
* The configuration to use for the line offset. | ||
* This defaults to any file path that includes `logger`, and any method that includes the word `log`. | ||
*/ | ||
this.lineOffset = { | ||
file: /logger/i, | ||
method: /log/i, | ||
}; | ||
/** | ||
* The mapping of log level names to log level numbers. | ||
* Defaults to the RFC Log Level configuration. | ||
*/ | ||
this.levels = rfc_log_levels_1.rfcLogLevels; | ||
/** | ||
* Only fetch line information for entries that have a log level equal to, or below this number. | ||
* You should only specify this if you need it, as fFetching line information for thousands of log entries, which is typical in large applications, will slow your application down dramatically. | ||
* If not specified, defaults to `-Infinity` which effect is to ignore gathering line information for all log levels. | ||
*/ | ||
this.lineLevel = -Infinity; | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.lineOffset) != null) | ||
this.lineOffset = opts.lineOffset; | ||
if ((opts === null || opts === void 0 ? void 0 : opts.levels) != null) | ||
this.levels = opts.levels; | ||
if ((opts === null || opts === void 0 ? void 0 : opts.lineLevel) != null) | ||
this.lineLevel = opts.lineLevel; | ||
// options: default level | ||
this.defaultLevel = (_a = opts === null || opts === void 0 ? void 0 : opts.defaultLevel) !== null && _a !== void 0 ? _a : 'info'; | ||
// dereference | ||
this.levels = Object.assign({}, this.levels); | ||
} | ||
/** Set the default level info via a level number or name. */ | ||
set defaultLevel(value) { | ||
const levelInfo = this.getLogLevel(value); | ||
if (levelInfo == null) { | ||
throw new Error(`caterpillar: the intended value of ${value} for the default log level not found in the configured levels`); | ||
} | ||
this.defaultLevelInfo = levelInfo; | ||
} | ||
/** Alias for {@link getLogLevel} using the configured logger levels as reference. */ | ||
getLogLevel(value) { | ||
return rfc_log_levels_1.default(value, this.levels); | ||
} | ||
/** Takes an arguments array and tranforms it into a log entry. */ | ||
format(args) { | ||
// fetch the level | ||
const level = args.shift(); | ||
let levelInfo = level === 'default' ? this.defaultLevelInfo : this.getLogLevel(level); | ||
if (levelInfo == null) { | ||
// fallback to the default log level | ||
levelInfo = this.defaultLevelInfo; | ||
// as the level (first param) was not actually a level, put it back | ||
args.unshift(level); | ||
} | ||
// fetch the date | ||
const date = new Date().toISOString(); | ||
// fetch the line information | ||
const lineInfo = levelInfo.levelNumber <= this.lineLevel | ||
? get_current_line_1.default(this.lineOffset) | ||
: { | ||
line: -1, | ||
char: -1, | ||
method: '', | ||
file: '', | ||
}; | ||
// put it all together | ||
return Object.assign({ date, args }, levelInfo, lineInfo); | ||
} | ||
/** | ||
* Log the arguments into the logger stream as formatted data with debugging information. | ||
* Such that our transformers can deal with it intelligently. | ||
* | ||
* @example Inputs | ||
* ``` javascript | ||
* logger.log('note', 'this is working swell') | ||
* ``` | ||
* ``` javascript | ||
* logger.log('this', 'worked', 'swell') | ||
* ``` | ||
* | ||
* @example Results | ||
* ``` json | ||
* { | ||
* "args": ["this is working swell"], | ||
* "date": "2013-04-25T10:18:25.722Z", | ||
* "levelNumber": 5, | ||
* "levelName": "notice", | ||
* "line": "59", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
* ``` json | ||
* { | ||
* "args": ["this", "worked", "well"], | ||
* "date": "2013-04-25T10:18:26.539Z", | ||
* "levelNumber": 6, | ||
* "levelName": "info", | ||
* "line": "60", | ||
* "method": "Object.<anonymous>", | ||
* "file": "/Users/balupton/some-project/calling-file.js" | ||
* } | ||
* ``` | ||
*/ | ||
log(...args) { | ||
this.write(args); | ||
} | ||
/** Alias for log which prefixes the error log level */ | ||
error(...args) { | ||
this.write(['error', ...args]); | ||
} | ||
/** Alias for log which prefixes the warn log level */ | ||
warn(...args) { | ||
this.write(['warn', ...args]); | ||
} | ||
/** Alias for log which prefixes the info log level */ | ||
info(...args) { | ||
this.write(['info', ...args]); | ||
} | ||
/** Alias for log which prefixes the debug log level */ | ||
debug(...args) { | ||
this.write(['debug', ...args]); | ||
} | ||
} | ||
exports.Logger = Logger | ||
exports.default = Logger | ||
exports.Logger = Logger; | ||
exports.default = Logger; |
@@ -1,3 +0,1 @@ | ||
{ | ||
"type": "commonjs" | ||
} | ||
{"type": "commonjs"} |
@@ -1,4 +0,4 @@ | ||
'use strict' | ||
Object.defineProperty(exports, '__esModule', { value: true }) | ||
exports.Transform = void 0 | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Transform = void 0; | ||
/** | ||
@@ -12,70 +12,74 @@ * Caterpillar Transform Class. | ||
class Transform { | ||
constructor() { | ||
/** Where is this Transform piping to? */ | ||
this.pipes = [] | ||
/** Maintain a write queue such that multiple Deno writes do not stall */ | ||
this.writer = Promise.resolve() | ||
} | ||
/** | ||
* Format the received log entry representation. | ||
* Your transformer should extend this. | ||
*/ | ||
format(message) { | ||
return message | ||
} | ||
/** Pipe future log entries into a caterpillar transform or a stream. */ | ||
pipe(to) { | ||
this.pipes.push(to) | ||
return to | ||
} | ||
/** Write to the child pipes. */ | ||
write(chunk) { | ||
// format now, so that we have the correct stack | ||
const data = this.format(chunk) | ||
// exclude filtered entries | ||
if (data == null) return this.writer | ||
// now delegate back to the pipe | ||
this.writer = this.writer.then(async () => { | ||
// pipe to child transforms and streams | ||
for (const pipe of this.pipes) { | ||
if (pipe instanceof Transform) { | ||
// compatibility with caterpillar transforms | ||
await pipe.write(data) | ||
} else { | ||
const str = typeof data === 'string' ? data : JSON.stringify(data) | ||
// requires typescript dom lib to define TextEncoder global | ||
if (typeof TextEncoder !== 'undefined') { | ||
// compatibility with deno and later node streams | ||
await pipe.write(new TextEncoder().encode(str)) | ||
} else { | ||
// compatibility with earlier node streams | ||
await pipe.write(str) | ||
} | ||
} | ||
} | ||
}) | ||
return this.writer | ||
} | ||
/** Close the child pipes. */ | ||
async close() { | ||
await Promise.all( | ||
this.pipes.map((pipe) => { | ||
if (pipe.close) { | ||
return pipe.close() | ||
} else if (pipe.end) { | ||
return new Promise(function (resolve) { | ||
pipe.end(resolve) | ||
}) | ||
} else { | ||
return Promise.resolve() | ||
} | ||
}) | ||
) | ||
} | ||
/* Callback alias for close */ | ||
end(cb) { | ||
const p = this.close() | ||
if (cb) p.finally(cb) | ||
} | ||
constructor() { | ||
/** Where is this Transform piping to? */ | ||
this.pipes = []; | ||
/** Maintain a write queue such that multiple Deno writes do not stall */ | ||
this.writer = Promise.resolve(); | ||
} | ||
/** | ||
* Format the received log entry representation. | ||
* Your transformer should extend this. | ||
*/ | ||
format(message) { | ||
return message; | ||
} | ||
/** Pipe future log entries into a caterpillar transform or a stream. */ | ||
pipe(to) { | ||
this.pipes.push(to); | ||
return to; | ||
} | ||
/** Write to the child pipes. */ | ||
write(chunk) { | ||
// format now, so that we have the correct stack | ||
const data = this.format(chunk); | ||
// exclude filtered entries | ||
if (data == null) | ||
return this.writer; | ||
// now delegate back to the pipe | ||
this.writer = this.writer.then(async () => { | ||
// pipe to child transforms and streams | ||
for (const pipe of this.pipes) { | ||
if (pipe instanceof Transform) { | ||
// compatibility with caterpillar transforms | ||
await pipe.write(data); | ||
} | ||
else { | ||
const str = typeof data === 'string' ? data : JSON.stringify(data); | ||
// requires typescript dom lib to define TextEncoder global | ||
if (typeof TextEncoder !== 'undefined') { | ||
// compatibility with deno and later node streams | ||
await pipe.write(new TextEncoder().encode(str)); | ||
} | ||
else { | ||
// compatibility with earlier node streams | ||
await pipe.write(str); | ||
} | ||
} | ||
} | ||
}); | ||
return this.writer; | ||
} | ||
/** Close the child pipes. */ | ||
async close() { | ||
await Promise.all(this.pipes.map((pipe) => { | ||
if (pipe.close) { | ||
return pipe.close(); | ||
} | ||
else if (pipe.end) { | ||
return new Promise(function (resolve) { | ||
pipe.end(resolve); | ||
}); | ||
} | ||
else { | ||
return Promise.resolve(); | ||
} | ||
})); | ||
} | ||
/* Callback alias for close */ | ||
end(cb) { | ||
const p = this.close(); | ||
if (cb) | ||
p.finally(cb); | ||
} | ||
} | ||
exports.Transform = Transform | ||
exports.Transform = Transform; |
@@ -1,7 +0,7 @@ | ||
'use strict' | ||
"use strict"; | ||
// this cannot be located at source/brower.ts as otherwise it would become the browser entry | ||
Object.defineProperty(exports, '__esModule', { value: true }) | ||
exports.Browser = void 0 | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Browser = void 0; | ||
// Imports | ||
const transform_js_1 = require('../transform.js') | ||
const transform_js_1 = require("../transform.js"); | ||
/** | ||
@@ -18,104 +18,102 @@ * Convert human readable Caterpillar entries into browser compatible entries. | ||
class Browser extends transform_js_1.Transform { | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super() | ||
/** Whether or not we should use color. */ | ||
this.color = true | ||
/** Whether or not we should write to the browser console. */ | ||
this.output = true | ||
/** The objects that tell our browser transform how to convert terminal colours into console colours. */ | ||
this.styles = { | ||
red: { | ||
start: '31', | ||
end: '39', | ||
value: 'color:red', | ||
}, | ||
yellow: { | ||
start: '33', | ||
end: '39', | ||
value: 'color:orange', | ||
}, | ||
green: { | ||
start: '32', | ||
end: '39', | ||
value: 'color:green', | ||
}, | ||
bright: { | ||
start: '1', | ||
end: '22', | ||
value: 'font-weight:bold', | ||
}, | ||
dim: { | ||
start: '2', | ||
end: '22', | ||
value: 'color:lightGray', | ||
}, | ||
italic: { | ||
start: '3', | ||
end: '23', | ||
value: 'font-style:italic', | ||
}, | ||
underline: { | ||
start: '4', | ||
end: '24', | ||
value: 'text-decoration:underline', | ||
}, | ||
} | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.color) != null) | ||
this.color = opts.color | ||
if ((opts === null || opts === void 0 ? void 0 : opts.output) != null) | ||
this.output = opts.output | ||
if ((opts === null || opts === void 0 ? void 0 : opts.styles) != null) | ||
this.styles = opts.styles | ||
} | ||
/** | ||
* Convert a human readable Caterpillar entry into a format that browser consoles can understand. | ||
* And if the `write` config property is `true` (it is by default), write the result to the browser console. | ||
*/ | ||
format(message) { | ||
// Prepare | ||
const { color, styles, output } = this | ||
// Replace caterpillar-human formatted entry | ||
/* eslint no-control-regex:0 */ | ||
const args = [] | ||
const result = message.replace( | ||
/\u001b\[([0-9]+)m(.+?)\u001b\[([0-9]+)m/g, | ||
function (match, start, content, end) { | ||
// Check | ||
if (color === false) return content | ||
// Prepare | ||
let matchedStyle, style | ||
// Find the matcing style for this combination | ||
for (const key in styles) { | ||
if (styles.hasOwnProperty(key)) { | ||
style = styles[key] | ||
if ( | ||
String(style.start) === String(start) && | ||
String(style.end) === String(end) | ||
) { | ||
matchedStyle = style | ||
break | ||
} | ||
} | ||
} | ||
// Check | ||
if (!matchedStyle) return content | ||
// Push the style | ||
args.push(matchedStyle.value) | ||
args.push(content) | ||
args.push('color:default; font:default; text-decoration:default') | ||
return '%c%s%c' | ||
} | ||
) | ||
// Final format | ||
const parts = [result.trim()].concat(args) | ||
// Write | ||
/* eslint no-console:0 */ | ||
if (output) console.log(...parts) | ||
// Return | ||
return parts | ||
} | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super(); | ||
/** Whether or not we should use color. */ | ||
this.color = true; | ||
/** Whether or not we should write to the browser console. */ | ||
this.output = true; | ||
/** The objects that tell our browser transform how to convert terminal colours into console colours. */ | ||
this.styles = { | ||
red: { | ||
start: '31', | ||
end: '39', | ||
value: 'color:red', | ||
}, | ||
yellow: { | ||
start: '33', | ||
end: '39', | ||
value: 'color:orange', | ||
}, | ||
green: { | ||
start: '32', | ||
end: '39', | ||
value: 'color:green', | ||
}, | ||
bright: { | ||
start: '1', | ||
end: '22', | ||
value: 'font-weight:bold', | ||
}, | ||
dim: { | ||
start: '2', | ||
end: '22', | ||
value: 'color:lightGray', | ||
}, | ||
italic: { | ||
start: '3', | ||
end: '23', | ||
value: 'font-style:italic', | ||
}, | ||
underline: { | ||
start: '4', | ||
end: '24', | ||
value: 'text-decoration:underline', | ||
}, | ||
}; | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.color) != null) | ||
this.color = opts.color; | ||
if ((opts === null || opts === void 0 ? void 0 : opts.output) != null) | ||
this.output = opts.output; | ||
if ((opts === null || opts === void 0 ? void 0 : opts.styles) != null) | ||
this.styles = opts.styles; | ||
} | ||
/** | ||
* Convert a human readable Caterpillar entry into a format that browser consoles can understand. | ||
* And if the `write` config property is `true` (it is by default), write the result to the browser console. | ||
*/ | ||
format(message) { | ||
// Prepare | ||
const { color, styles, output } = this; | ||
// Replace caterpillar-human formatted entry | ||
/* eslint no-control-regex:0 */ | ||
const args = []; | ||
const result = message.replace(/\u001b\[([0-9]+)m(.+?)\u001b\[([0-9]+)m/g, function (match, start, content, end) { | ||
// Check | ||
if (color === false) | ||
return content; | ||
// Prepare | ||
let matchedStyle, style; | ||
// Find the matcing style for this combination | ||
for (const key in styles) { | ||
if (styles.hasOwnProperty(key)) { | ||
style = styles[key]; | ||
if (String(style.start) === String(start) && | ||
String(style.end) === String(end)) { | ||
matchedStyle = style; | ||
break; | ||
} | ||
} | ||
} | ||
// Check | ||
if (!matchedStyle) | ||
return content; | ||
// Push the style | ||
args.push(matchedStyle.value); | ||
args.push(content); | ||
args.push('color:default; font:default; text-decoration:default'); | ||
return '%c%s%c'; | ||
}); | ||
// Final format | ||
const parts = [result.trim()].concat(args); | ||
// Write | ||
/* eslint no-console:0 */ | ||
if (output) | ||
console.log(...parts); | ||
// Return | ||
return parts; | ||
} | ||
} | ||
exports.Browser = Browser | ||
exports.default = Browser | ||
exports.Browser = Browser; | ||
exports.default = Browser; |
@@ -1,5 +0,5 @@ | ||
'use strict' | ||
Object.defineProperty(exports, '__esModule', { value: true }) | ||
exports.Filter = void 0 | ||
const transform_js_1 = require('../transform.js') | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Filter = void 0; | ||
const transform_js_1 = require("../transform.js"); | ||
/** | ||
@@ -22,20 +22,20 @@ * Caterpillar Filter Transform. | ||
class Filter extends transform_js_1.Transform { | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super() | ||
/** | ||
* Only display entries that have a log level below or equal to this number. | ||
* Defaults to `6`, which by default is the info log level. | ||
*/ | ||
this.filterLevel = 6 | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.filterLevel) != null) | ||
this.filterLevel = opts.filterLevel | ||
} | ||
/** Retain only log entries that are equal to or less than the specified filter level. */ | ||
format(entry) { | ||
return entry.levelNumber <= this.filterLevel ? entry : null | ||
} | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super(); | ||
/** | ||
* Only display entries that have a log level below or equal to this number. | ||
* Defaults to `6`, which by default is the info log level. | ||
*/ | ||
this.filterLevel = 6; | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.filterLevel) != null) | ||
this.filterLevel = opts.filterLevel; | ||
} | ||
/** Retain only log entries that are equal to or less than the specified filter level. */ | ||
format(entry) { | ||
return entry.levelNumber <= this.filterLevel ? entry : null; | ||
} | ||
} | ||
exports.Filter = Filter | ||
exports.default = Filter | ||
exports.Filter = Filter; | ||
exports.default = Filter; |
@@ -1,44 +0,26 @@ | ||
'use strict' | ||
var __createBinding = | ||
(this && this.__createBinding) || | ||
(Object.create | ||
? function (o, m, k, k2) { | ||
if (k2 === undefined) k2 = k | ||
Object.defineProperty(o, k2, { | ||
enumerable: true, | ||
get: function () { | ||
return m[k] | ||
}, | ||
}) | ||
} | ||
: function (o, m, k, k2) { | ||
if (k2 === undefined) k2 = k | ||
o[k2] = m[k] | ||
}) | ||
var __setModuleDefault = | ||
(this && this.__setModuleDefault) || | ||
(Object.create | ||
? function (o, v) { | ||
Object.defineProperty(o, 'default', { enumerable: true, value: v }) | ||
} | ||
: function (o, v) { | ||
o['default'] = v | ||
}) | ||
var __importStar = | ||
(this && this.__importStar) || | ||
function (mod) { | ||
if (mod && mod.__esModule) return mod | ||
var result = {} | ||
if (mod != null) | ||
for (var k in mod) | ||
if (k !== 'default' && Object.prototype.hasOwnProperty.call(mod, k)) | ||
__createBinding(result, mod, k) | ||
__setModuleDefault(result, mod) | ||
return result | ||
} | ||
Object.defineProperty(exports, '__esModule', { value: true }) | ||
exports.Human = exports.noop = void 0 | ||
const transform_js_1 = require('../transform.js') | ||
const util_1 = require('util') | ||
const ansi = __importStar(require('@bevry/ansi')) | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Human = void 0; | ||
const transform_js_1 = require("../transform.js"); | ||
const util_1 = require("util"); | ||
const ansi = __importStar(require("@bevry/ansi")); | ||
/** | ||
@@ -48,6 +30,5 @@ * Return the given argument. | ||
*/ | ||
function noop(str) { | ||
return str | ||
function ansiNoop(a) { | ||
return a; | ||
} | ||
exports.noop = noop | ||
/** | ||
@@ -66,118 +47,116 @@ * Convert Logger entries into human readable format. | ||
class Human extends transform_js_1.Transform { | ||
/** Create our instance and apply our configuraiton options. */ | ||
constructor(opts) { | ||
super() | ||
/** Whether or not to use colors? */ | ||
this.color = true | ||
/** Mapping of which log level numbers correspond to which colours */ | ||
this.colors = { | ||
0: 'red', | ||
1: 'red', | ||
2: 'red', | ||
3: 'red', | ||
4: 'yellow', | ||
5: 'yellow', | ||
6: 'green', | ||
7: 'green', | ||
} | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.color) != null) | ||
this.color = opts.color | ||
if ((opts === null || opts === void 0 ? void 0 : opts.colors) != null) | ||
this.colors = opts.colors | ||
} | ||
/** Get the color for the log level */ | ||
getColor(levelNumber) { | ||
// Determine | ||
const color = this.colors[levelNumber] || false | ||
// Return | ||
return color | ||
} | ||
/** Pad the left of some content if need be with the specified padding to make the content reach a certain size */ | ||
padLeft(padding, size, content) { | ||
// Prepare | ||
padding = String(padding) | ||
content = String(content) | ||
// Handle | ||
if (content.length < size) { | ||
for (let i = 0, n = size - content.length; i < n; ++i) { | ||
content = padding + content | ||
} | ||
} | ||
// Return | ||
return content | ||
} | ||
/** Convert logger entry arguments into a human readable string */ | ||
formatArguments(args) { | ||
return args | ||
.map((value) => | ||
typeof value === 'string' | ||
? value | ||
: util_1.inspect(value, { | ||
showHidden: false, | ||
depth: 10, | ||
colors: this.color, | ||
}) | ||
) | ||
.join(' ') | ||
} | ||
/** Convert a datetime into a human readable format */ | ||
formatDate(datetime) { | ||
// Prepare | ||
const now = new Date(datetime) | ||
const year = now.getFullYear() | ||
const month = this.padLeft('0', 2, now.getMonth() + 1) | ||
const date = this.padLeft('0', 2, now.getDate()) | ||
const hours = this.padLeft('0', 2, now.getHours()) | ||
const minutes = this.padLeft('0', 2, now.getMinutes()) | ||
const seconds = this.padLeft('0', 2, now.getSeconds()) | ||
const ms = this.padLeft('0', 3, now.getMilliseconds()) | ||
// Apply | ||
const result = `${year}-${month}-${date} ${hours}:${minutes}:${seconds}.${ms}` | ||
// Return | ||
return result | ||
} | ||
/** Convert a logger entry into a human readable format */ | ||
format(entry) { | ||
// Prepare | ||
const { color } = this | ||
const useLine = entry.line !== -1 | ||
let result | ||
// Format | ||
const format = { | ||
color: this.getColor(entry.levelNumber), | ||
timestamp: this.formatDate(entry.date), | ||
text: this.formatArguments(entry.args), | ||
} | ||
// Check | ||
if (format.text) { | ||
// Formatters | ||
const levelFormatter = | ||
(color && format.color && ansi[format.color]) || noop | ||
const lineFormatter = (useLine && color && ansi.dim) || noop | ||
// Message | ||
const levelString = levelFormatter(`${entry.levelName}:`) | ||
const entryString = format.text | ||
const messageString = `${levelString} ${entryString}` | ||
// Format | ||
if (useLine) { | ||
// Line Information | ||
const seperator = '\n ' | ||
const debugString = lineFormatter( | ||
`→ [${format.timestamp}] [${entry.file}:${entry.line}:${entry.char}] [${entry.method}]` | ||
) | ||
// Result | ||
result = `${messageString}${seperator}${debugString}\n` | ||
} else { | ||
// Result | ||
result = `${messageString}\n` | ||
} | ||
} else { | ||
result = format.text | ||
} | ||
// Return | ||
return result | ||
} | ||
/** Create our instance and apply our configuration options. */ | ||
constructor(opts) { | ||
super(); | ||
/** Whether or not to use colors? */ | ||
this.color = true; | ||
/** Mapping of which log level numbers correspond to which colours */ | ||
this.colors = { | ||
'0': 'red', | ||
'1': 'red', | ||
'2': 'red', | ||
'3': 'red', | ||
'4': 'yellow', | ||
'5': 'yellow', | ||
'6': 'green', | ||
'7': 'green', | ||
}; | ||
// options | ||
if ((opts === null || opts === void 0 ? void 0 : opts.color) != null) | ||
this.color = opts.color; | ||
if ((opts === null || opts === void 0 ? void 0 : opts.colors) != null) | ||
this.colors = opts.colors; | ||
} | ||
/** Get the color for the log level */ | ||
getColor(levelNumber) { | ||
// Determine | ||
const color = this.colors[levelNumber] || false; | ||
// Return | ||
return color; | ||
} | ||
/** Pad the left of some content if need be with the specified padding to make the content reach a certain size */ | ||
padLeft(padding, size, content) { | ||
// Prepare | ||
padding = String(padding); | ||
content = String(content); | ||
// Handle | ||
if (content.length < size) { | ||
for (let i = 0, n = size - content.length; i < n; ++i) { | ||
content = padding + content; | ||
} | ||
} | ||
// Return | ||
return content; | ||
} | ||
/** Convert logger entry arguments into a human readable string */ | ||
formatArguments(args) { | ||
return args | ||
.map((value) => typeof value === 'string' | ||
? value | ||
: util_1.inspect(value, { | ||
showHidden: false, | ||
depth: 10, | ||
colors: this.color, | ||
})) | ||
.join(' '); | ||
} | ||
/** Convert a datetime into a human readable format */ | ||
formatDate(datetime) { | ||
// Prepare | ||
const now = new Date(datetime); | ||
const year = now.getFullYear(); | ||
const month = this.padLeft('0', 2, now.getMonth() + 1); | ||
const date = this.padLeft('0', 2, now.getDate()); | ||
const hours = this.padLeft('0', 2, now.getHours()); | ||
const minutes = this.padLeft('0', 2, now.getMinutes()); | ||
const seconds = this.padLeft('0', 2, now.getSeconds()); | ||
const ms = this.padLeft('0', 3, now.getMilliseconds()); | ||
// Apply | ||
const result = `${year}-${month}-${date} ${hours}:${minutes}:${seconds}.${ms}`; | ||
// Return | ||
return result; | ||
} | ||
/** Convert a logger entry into a human readable format */ | ||
format(entry) { | ||
// Prepare | ||
const { color } = this; | ||
const useLine = entry.line !== -1; | ||
let result; | ||
// Format | ||
const format = { | ||
color: this.getColor(entry.levelNumber), | ||
timestamp: this.formatDate(entry.date), | ||
text: this.formatArguments(entry.args), | ||
}; | ||
// Check | ||
if (format.text) { | ||
// Formatters | ||
const levelFormatter = (color && format.color && ansi[format.color]) || ansiNoop; | ||
const lineFormatter = (useLine && color && ansi.dim) || ansiNoop; | ||
// Message | ||
// @ts-ignore | ||
const levelString = levelFormatter(`${entry.levelName}:`); | ||
const entryString = format.text; | ||
const messageString = `${levelString} ${entryString}`; | ||
// Format | ||
if (useLine) { | ||
// Line Information | ||
const seperator = '\n '; | ||
const debugString = lineFormatter(`→ [${format.timestamp}] [${entry.file}:${entry.line}:${entry.char}] [${entry.method}]`); | ||
// Result | ||
result = `${messageString}${seperator}${debugString}\n`; | ||
} | ||
else { | ||
// Result | ||
result = `${messageString}\n`; | ||
} | ||
} | ||
else { | ||
result = format.text; | ||
} | ||
// Return | ||
return result; | ||
} | ||
} | ||
exports.Human = Human | ||
exports.default = Human | ||
exports.Human = Human; | ||
exports.default = Human; |
# History | ||
## v6.7.0 2021 July 29 | ||
- Updated dependencies, [base files](https://github.com/bevry/base), and [editions](https://editions.bevry.me) using [boundation](https://github.com/bevry/boundation) | ||
## v6.6.0 2020 October 29 | ||
@@ -4,0 +8,0 @@ |
@@ -19,3 +19,3 @@ <!-- LICENSEFILE/ --> | ||
The above copyright notice and this permission notice (including the next paragraph) 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. | ||
@@ -22,0 +22,0 @@ 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. |
{ | ||
"title": "Caterpillar", | ||
"name": "caterpillar", | ||
"version": "6.6.0", | ||
"version": "6.7.0-next.1627509327.95a1fdcc97d8933f808e570bda2cdb5db6d69c8d", | ||
"description": "Caterpillar is the ultimate logging system for Deno, Node.js, and Web Browsers. Log levels are implemented to the RFC standard. Log entries can be filtered and piped to various streams, including coloured output to the terminal, the browser's console, and debug files. You can even write your own transforms.", | ||
@@ -15,3 +15,2 @@ "homepage": "https://github.com/bevry/caterpillar", | ||
"es2019", | ||
"esnext", | ||
"log", | ||
@@ -30,3 +29,3 @@ "logger", | ||
"list": [ | ||
"travisci", | ||
"githubworkflow", | ||
"npmversion", | ||
@@ -48,2 +47,3 @@ "npmdownloads", | ||
"config": { | ||
"githubWorkflow": "bevry", | ||
"githubSponsorsUsername": "balupton", | ||
@@ -58,3 +58,2 @@ "buymeacoffeeUsername": "balupton", | ||
"wishlistURL": "https://bevry.me/wishlist", | ||
"travisTLD": "com", | ||
"githubUsername": "bevry", | ||
@@ -99,3 +98,3 @@ "githubRepository": "caterpillar", | ||
{ | ||
"description": "TypeScript compiled against ES2019 for web browsers with Import for modules", | ||
"description": "TypeScript compiled against ES2020 for web browsers with Import for modules", | ||
"directory": "edition-browsers", | ||
@@ -114,18 +113,3 @@ "entry": "index.js", | ||
{ | ||
"description": "TypeScript compiled against ESNext for Node.js 14 || 15 with Require for modules", | ||
"directory": "edition-esnext", | ||
"entry": "index.js", | ||
"tags": [ | ||
"compiled", | ||
"javascript", | ||
"esnext", | ||
"require" | ||
], | ||
"engines": { | ||
"node": "14 || 15", | ||
"browsers": false | ||
} | ||
}, | ||
{ | ||
"description": "TypeScript compiled against ES2019 for Node.js 10 || 12 || 14 || 15 with Require for modules", | ||
"description": "TypeScript compiled against ES2019 for Node.js 10 || 12 || 14 || 16 with Require for modules", | ||
"directory": "edition-es2019", | ||
@@ -140,3 +124,3 @@ "entry": "index.js", | ||
"engines": { | ||
"node": "10 || 12 || 14 || 15", | ||
"node": "10 || 12 || 14 || 16", | ||
"browsers": false | ||
@@ -146,3 +130,3 @@ } | ||
{ | ||
"description": "TypeScript compiled against ES2019 for Node.js 12 || 14 || 15 with Import for modules", | ||
"description": "TypeScript compiled against ES2019 for Node.js 12 || 14 || 16 with Import for modules", | ||
"directory": "edition-es2019-esm", | ||
@@ -157,3 +141,3 @@ "entry": "index.js", | ||
"engines": { | ||
"node": "12 || 14 || 15", | ||
"node": "12 || 14 || 16", | ||
"browsers": false | ||
@@ -165,8 +149,7 @@ } | ||
"type": "module", | ||
"main": "index.cjs", | ||
"main": "edition-es2019/index.js", | ||
"exports": { | ||
"node": { | ||
"import": "./edition-es2019-esm/index.js", | ||
"default": "./index.cjs", | ||
"require": "./edition-esnext/index.js" | ||
"require": "./edition-es2019/index.js" | ||
}, | ||
@@ -180,34 +163,32 @@ "browser": { | ||
"dependencies": { | ||
"@bevry/ansi": "^2.1.0", | ||
"editions": "^6.0.0", | ||
"get-current-line": "^6.2.0", | ||
"rfc-log-levels": "^3.14.0" | ||
"@bevry/ansi": "^3.0.0", | ||
"get-current-line": "^6.5.0", | ||
"rfc-log-levels": "^3.16.0" | ||
}, | ||
"devDependencies": { | ||
"@bevry/update-contributors": "^1.17.0", | ||
"@typescript-eslint/eslint-plugin": "^4.6.0", | ||
"@typescript-eslint/parser": "^4.6.0", | ||
"assert-helpers": "^8.1.0", | ||
"eslint": "^7.12.1", | ||
"eslint-config-bevry": "^3.22.0", | ||
"eslint-config-prettier": "^6.15.0", | ||
"eslint-plugin-prettier": "^3.1.4", | ||
"kava": "^5.12.0", | ||
"make-deno-edition": "^1.2.0", | ||
"prettier": "^2.1.2", | ||
"projectz": "^2.16.0", | ||
"surge": "^0.21.6", | ||
"typedoc": "^0.19.2", | ||
"typescript": "^4.0.5", | ||
"valid-directory": "^3.4.0", | ||
"valid-module": "^1.14.0" | ||
"@bevry/update-contributors": "^1.19.0", | ||
"@typescript-eslint/eslint-plugin": "^4.28.5", | ||
"@typescript-eslint/parser": "^4.28.5", | ||
"assert-helpers": "^8.2.0", | ||
"eslint": "^7.31.0", | ||
"eslint-config-bevry": "^3.25.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"eslint-plugin-prettier": "^3.4.0", | ||
"kava": "^5.14.0", | ||
"make-deno-edition": "^1.3.0", | ||
"prettier": "^2.3.2", | ||
"projectz": "^2.19.0", | ||
"surge": "^0.23.0", | ||
"typedoc": "^0.21.4", | ||
"typescript": "4.3.5", | ||
"valid-directory": "^3.7.0", | ||
"valid-module": "^1.16.0" | ||
}, | ||
"scripts": { | ||
"our:clean": "rm -Rf ./docs ./edition* ./es2015 ./es5 ./out ./.next", | ||
"our:compile": "npm run our:compile:deno && npm run our:compile:edition-browsers && npm run our:compile:edition-es2019 && npm run our:compile:edition-es2019-esm && npm run our:compile:edition-esnext && npm run our:compile:types", | ||
"our:compile": "npm run our:compile:deno && npm run our:compile:edition-browsers && npm run our:compile:edition-es2019 && npm run our:compile:edition-es2019-esm && npm run our:compile:types", | ||
"our:compile:deno": "make-deno-edition --attempt", | ||
"our:compile:edition-browsers": "tsc --module ESNext --target ES2019 --outDir ./edition-browsers --project tsconfig.json && ( test ! -d edition-browsers/source || ( mv edition-browsers/source edition-temp && rm -Rf edition-browsers && mv edition-temp edition-browsers ) )", | ||
"our:compile:edition-browsers": "tsc --module ESNext --target ES2020 --outDir ./edition-browsers --project tsconfig.json && ( test ! -d edition-browsers/source || ( mv edition-browsers/source edition-temp && rm -Rf edition-browsers && mv edition-temp edition-browsers ) )", | ||
"our:compile:edition-es2019": "tsc --module commonjs --target ES2019 --outDir ./edition-es2019 --project tsconfig.json && ( test ! -d edition-es2019/source || ( mv edition-es2019/source edition-temp && rm -Rf edition-es2019 && mv edition-temp edition-es2019 ) ) && echo '{\"type\": \"commonjs\"}' > edition-es2019/package.json", | ||
"our:compile:edition-es2019-esm": "tsc --module ESNext --target ES2019 --outDir ./edition-es2019-esm --project tsconfig.json && ( test ! -d edition-es2019-esm/source || ( mv edition-es2019-esm/source edition-temp && rm -Rf edition-es2019-esm && mv edition-temp edition-es2019-esm ) ) && echo '{\"type\": \"module\"}' > edition-es2019-esm/package.json", | ||
"our:compile:edition-esnext": "tsc --module commonjs --target ESNext --outDir ./edition-esnext --project tsconfig.json && ( test ! -d edition-esnext/source || ( mv edition-esnext/source edition-temp && rm -Rf edition-esnext && mv edition-temp edition-esnext ) ) && echo '{\"type\": \"commonjs\"}' > edition-esnext/package.json", | ||
"our:compile:types": "tsc --project tsconfig.json --emitDeclarationOnly --declaration --declarationMap --declarationDir ./compiled-types && ( test ! -d compiled-types/source || ( mv compiled-types/source edition-temp && rm -Rf compiled-types && mv edition-temp compiled-types ) )", | ||
@@ -218,3 +199,3 @@ "our:deploy": "echo no need for this project", | ||
"our:meta:docs": "npm run our:meta:docs:typedoc", | ||
"our:meta:docs:typedoc": "rm -Rf ./docs && typedoc --mode file --exclude '**/+(*test*|node_modules)' --excludeExternals --name \"$npm_package_name\" --readme ./README.md --out ./docs ./source", | ||
"our:meta:docs:typedoc": "rm -Rf ./docs && typedoc --exclude '**/+(*test*|node_modules)' --excludeExternals --out ./docs ./source", | ||
"our:meta:projectz": "projectz compile", | ||
@@ -225,3 +206,3 @@ "our:release": "npm run our:release:prepare && npm run our:release:check-changelog && npm run our:release:check-dirty && npm run our:release:tag && npm run our:release:push", | ||
"our:release:prepare": "npm run our:clean && npm run our:compile && npm run our:test && npm run our:meta", | ||
"our:release:push": "git push origin master && git push origin --tags", | ||
"our:release:push": "git push origin && git push origin --tags", | ||
"our:release:tag": "export MESSAGE=$(cat ./HISTORY.md | sed -n \"/## v$npm_package_version/,/##/p\" | sed 's/## //' | awk 'NR>1{print buf}{buf = $0}') && test \"$MESSAGE\" || (echo 'proper changelog entry not found' && exit -1) && git tag v$npm_package_version -am \"$MESSAGE\"", | ||
@@ -236,3 +217,3 @@ "our:setup": "npm run our:setup:install", | ||
"our:verify:prettier": "prettier --write .", | ||
"test": "node ./test.cjs" | ||
"test": "node ./edition-es2019/test.js" | ||
}, | ||
@@ -239,0 +220,0 @@ "eslintConfig": { |
@@ -10,3 +10,3 @@ <!-- TITLE/ --> | ||
<span class="badge-travisci"><a href="http://travis-ci.com/bevry/caterpillar" title="Check this project's build status on TravisCI"><img src="https://img.shields.io/travis/com/bevry/caterpillar/master.svg" alt="Travis CI Build Status" /></a></span> | ||
<span class="badge-githubworkflow"><a href="https://github.com/bevry/caterpillar/actions?query=workflow%3Abevry" title="View the status of this project's GitHub Workflow: bevry"><img src="https://github.com/bevry/caterpillar/workflows/bevry/badge.svg" alt="Status of the GitHub Workflow: bevry" /></a></span> | ||
<span class="badge-npmversion"><a href="https://npmjs.org/package/caterpillar" title="View this project on NPM"><img src="https://img.shields.io/npm/v/caterpillar.svg" alt="NPM version" /></a></span> | ||
@@ -255,3 +255,3 @@ <span class="badge-npmdownloads"><a href="https://npmjs.org/package/caterpillar" title="View this project on NPM"><img src="https://img.shields.io/npm/dm/caterpillar.svg" alt="NPM downloads" /></a></span> | ||
<script type="module"> | ||
import * as pkg from '//cdn.skypack.dev/caterpillar@^6.6.0' | ||
import * as pkg from '//cdn.skypack.dev/caterpillar@^6.7.0' | ||
</script> | ||
@@ -264,3 +264,3 @@ ``` | ||
<script type="module"> | ||
import * as pkg from '//unpkg.com/caterpillar@^6.6.0' | ||
import * as pkg from '//unpkg.com/caterpillar@^6.7.0' | ||
</script> | ||
@@ -273,3 +273,3 @@ ``` | ||
<script type="module"> | ||
import * as pkg from '//dev.jspm.io/caterpillar@6.6.0' | ||
import * as pkg from '//dev.jspm.io/caterpillar@6.7.0' | ||
</script> | ||
@@ -282,8 +282,7 @@ ``` | ||
<ul><li><code>caterpillar</code> aliases <code>caterpillar/index.cjs</code> which uses the <a href="https://github.com/bevry/editions" title="You can use the Editions Autoloader to autoload the appropriate edition for your consumers environment">Editions Autoloader</a> to automatically select the correct edition for the consumer's environment</li> | ||
<li><code>caterpillar/source/index.ts</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> source code with <a href="https://babeljs.io/docs/learn-es2015/#modules" title="ECMAScript Modules">Import</a> for modules</li> | ||
<li><code>caterpillar/edition-browsers/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against <a href="https://en.wikipedia.org/wiki/ECMAScript#10th_Edition_-_ECMAScript_2019" title="ECMAScript ES2019">ES2019</a> for web browsers with <a href="https://babeljs.io/docs/learn-es2015/#modules" title="ECMAScript Modules">Import</a> for modules</li> | ||
<li><code>caterpillar/edition-esnext/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against <a href="https://en.wikipedia.org/wiki/ECMAScript#ES.Next" title="ECMAScript Next">ESNext</a> for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 14 || 15 with <a href="https://nodejs.org/dist/latest-v5.x/docs/api/modules.html" title="Node/CJS Modules">Require</a> for modules</li> | ||
<li><code>caterpillar/edition-es2019/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against <a href="https://en.wikipedia.org/wiki/ECMAScript#10th_Edition_-_ECMAScript_2019" title="ECMAScript ES2019">ES2019</a> for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 10 || 12 || 14 || 15 with <a href="https://nodejs.org/dist/latest-v5.x/docs/api/modules.html" title="Node/CJS Modules">Require</a> for modules</li> | ||
<li><code>caterpillar/edition-es2019-esm/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against <a href="https://en.wikipedia.org/wiki/ECMAScript#10th_Edition_-_ECMAScript_2019" title="ECMAScript ES2019">ES2019</a> for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 12 || 14 || 15 with <a href="https://babeljs.io/docs/learn-es2015/#modules" title="ECMAScript Modules">Import</a> for modules</li></ul> | ||
<ul><li><code>caterpillar/source/index.ts</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> source code with <a href="https://babeljs.io/docs/learn-es2015/#modules" title="ECMAScript Modules">Import</a> for modules</li> | ||
<li><code>caterpillar/edition-browsers/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against <a href="https://en.wikipedia.org/wiki/ECMAScript#11th_Edition_–_ECMAScript_2020" title="ECMAScript ES2020">ES2020</a> for web browsers with <a href="https://babeljs.io/docs/learn-es2015/#modules" title="ECMAScript Modules">Import</a> for modules</li> | ||
<li><code>caterpillar</code> aliases <code>caterpillar/edition-es2019/index.js</code></li> | ||
<li><code>caterpillar/edition-es2019/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against <a href="https://en.wikipedia.org/wiki/ECMAScript#10th_Edition_-_ECMAScript_2019" title="ECMAScript ES2019">ES2019</a> for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 10 || 12 || 14 || 16 with <a href="https://nodejs.org/dist/latest-v5.x/docs/api/modules.html" title="Node/CJS Modules">Require</a> for modules</li> | ||
<li><code>caterpillar/edition-es2019-esm/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against <a href="https://en.wikipedia.org/wiki/ECMAScript#10th_Edition_-_ECMAScript_2019" title="ECMAScript ES2019">ES2019</a> for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 12 || 14 || 16 with <a href="https://babeljs.io/docs/learn-es2015/#modules" title="ECMAScript Modules">Import</a> for modules</li></ul> | ||
@@ -290,0 +289,0 @@ <!-- /INSTALL --> |
@@ -82,3 +82,3 @@ /** | ||
} else if (pipe.end) { | ||
return new Promise(function (resolve) { | ||
return new Promise<void>(function (resolve) { | ||
pipe.end!(resolve) | ||
@@ -85,0 +85,0 @@ }) |
@@ -11,4 +11,4 @@ // Imports | ||
*/ | ||
export function noop<T>(str: T): T { | ||
return str | ||
function ansiNoop(a: string): string { | ||
return a | ||
} | ||
@@ -21,3 +21,3 @@ | ||
/** Configuration optons for the Caterpillar Human Transform */ | ||
/** Configuration options for the Caterpillar Human Transform */ | ||
export interface HumanOptions { | ||
@@ -59,3 +59,3 @@ /** Use to override the default value of {@link Human.color} */ | ||
/** Create our instance and apply our configuraiton options. */ | ||
/** Create our instance and apply our configuration options. */ | ||
constructor(opts?: HumanOptions) { | ||
@@ -147,6 +147,7 @@ super() | ||
const levelFormatter = | ||
(color && format.color && ansi[format.color]) || noop | ||
const lineFormatter = (useLine && color && ansi.dim) || noop | ||
(color && format.color && ansi[format.color]) || ansiNoop | ||
const lineFormatter = (useLine && color && ansi.dim) || ansiNoop | ||
// Message | ||
// @ts-ignore | ||
const levelString = levelFormatter(`${entry.levelName}:`) | ||
@@ -153,0 +154,0 @@ const entryString = format.text |
@@ -9,4 +9,4 @@ { | ||
"strict": true, | ||
"target": "ESNext", | ||
"lib": ["DOM.Iterable", "DOM", "ESNext"], | ||
"target": "ES2019", | ||
"lib": ["DOM.Iterable", "DOM"], | ||
"module": "ESNext" | ||
@@ -13,0 +13,0 @@ }, |
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
3
132906
43
2498
1
347
+ Added@bevry/ansi@3.5.0(transitive)
- Removededitions@^6.0.0
- Removed@bevry/ansi@2.1.0(transitive)
Updated@bevry/ansi@^3.0.0
Updatedget-current-line@^6.5.0
Updatedrfc-log-levels@^3.16.0