[READ-ONLY] Mirror of https://github.com/FoxxMD/logging. A typed, opinionated, batteries-included, Pino-based logging solution for backend TS/JS projects foxxmd.github.io/logging
child-logger logging logging-library nodejs pinojs typescript-library
0

Configure Feed

Select the types of activity you want to include in your feed.

reactor: Reorganize for single responsibility and simplify exports

* Break up funcs into own files for single responsibility and simpler imports
* Remove duplicate/unused functions
* Simplify types and naming (don't need to include pino in name)
* Simplify exports to default (types, log options parsing, pre-built loggers) and factory (pretty/destination/log building functions)

FoxxMD (Feb 29, 2024, 1:49 PM EST) 7ea5eb32 38f7231e

+254 -260
+9 -6
package.json
··· 23 23 "dist" 24 24 ], 25 25 "tshy": { 26 + "project": "./tsconfig.build.json", 26 27 "exports": { 27 28 "./package.json": "./package.json", 28 - ".": { 29 - "import": { 30 - "types": "./dist/esm/index.d.ts", 31 - "default": "./dist/esm/index.js" 32 - } 33 - } 29 + ".": "./src/index.js", 30 + "./factory": "./src/factory.js" 34 31 }, 35 32 "dialects": [ 36 33 "esm" ··· 69 66 "import": { 70 67 "types": "./dist/esm/index.d.ts", 71 68 "default": "./dist/esm/index.js" 69 + } 70 + }, 71 + "./factory": { 72 + "import": { 73 + "types": "./dist/esm/factory.d.ts", 74 + "default": "./dist/esm/factory.js" 72 75 } 73 76 } 74 77 }
+13
src/constants.ts
··· 1 + import path from "path"; 2 + import process from "process"; 3 + 4 + export const projectDir = process.cwd(); 5 + export const configDir: string = path.resolve(projectDir, './config'); 6 + let logPath = path.resolve(configDir, `./logs`); 7 + if (typeof process.env.CONFIG_DIR === 'string') { 8 + logPath = path.resolve(process.env.CONFIG_DIR, './logs'); 9 + } 10 + 11 + export { 12 + logPath 13 + }
+51
src/destinations.ts
··· 1 + import pinoRoll from 'pino-roll'; 2 + import {LogLevelStreamEntry, LogLevel, LogOptions} from "./types.js"; 3 + import {DestinationStream} from "pino"; 4 + import prettyDef, {PrettyOptions} from "pino-pretty"; 5 + import {prettyConsole, prettyFile} from "./pretty.js"; 6 + import {logPath} from "./constants.js"; 7 + import {fileOrDirectoryIsWriteable} from "./util.js"; 8 + import path from "path"; 9 + import {ErrorWithCause} from "pony-cause"; 10 + 11 + const pRoll = pinoRoll as unknown as typeof pinoRoll.default; 12 + export const buildDestinationFile = async (options: Required<LogOptions> & { 13 + path?: string 14 + }): Promise<LogLevelStreamEntry | undefined> => { 15 + const {file} = options; 16 + if (file === false) { 17 + return undefined; 18 + } 19 + 20 + const logToPath = options.path ?? logPath; 21 + 22 + try { 23 + fileOrDirectoryIsWriteable(logToPath); 24 + const rollingDest = await pRoll({ 25 + file: path.resolve(logToPath, 'app'), 26 + size: 10, 27 + frequency: 'daily', 28 + get extension() { 29 + return `-${new Date().toISOString().split('T')[0]}.log` 30 + }, 31 + mkdir: true, 32 + sync: false, 33 + }); 34 + 35 + return { 36 + level: file as LogLevel, 37 + stream: prettyDef.default({...prettyFile, destination: rollingDest}) 38 + }; 39 + } catch (e: any) { 40 + throw new ErrorWithCause<Error>('WILL NOT write logs to rotating file due to an error while trying to access the specified logging directory', {cause: e as Error}); 41 + } 42 + } 43 + export const buildDestinationStream = (options: Required<LogOptions> & { 44 + stream?: DestinationStream | NodeJS.WritableStream 45 + } & PrettyOptions): LogLevelStreamEntry => { 46 + const {console, stream = 1, ...rest} = options; 47 + return { 48 + level: console as LogLevel, 49 + stream: prettyDef.default({...prettyConsole, ...rest, destination: stream, sync: true}) 50 + } 51 + }
+12
src/factory.ts
··· 1 + import {prettyConsole, prettyFile, prettyOptsFactory} from "./pretty.js"; 2 + import {buildDestinationStream, buildDestinationFile} from "./destinations.js"; 3 + import {buildLogger} from './loggers.js'; 4 + 5 + export { 6 + prettyConsole, 7 + prettyFile, 8 + prettyOptsFactory, 9 + buildDestinationStream, 10 + buildDestinationFile, 11 + buildLogger 12 + }
+4 -170
src/funcs.ts
··· 1 - import path from "path"; 2 1 import process from "process"; 3 - import {ErrorWithCause} from "pony-cause"; 4 - import { 5 - AllLevelStreamEntry, 6 - asLogOptions, 7 - LabelledLogger, 8 - LogLevel, 9 - LogOptions 10 - } from "./types.js"; 11 - import { 12 - pino, 13 - LevelWithSilentOrString, DestinationStream, 14 - } from 'pino'; 15 - import pinoRoll from 'pino-roll'; 16 - import prettyDef, {PrettyOptions} from 'pino-pretty'; 17 - import {createColors} from 'colorette'; 18 - import {fileOrDirectoryIsWriteable} from "./util.js"; 19 - 20 - const projectDir = process.cwd(); 21 - const configDir: string = path.resolve(projectDir, './config'); 22 - 23 - const pRoll = pinoRoll as unknown as typeof pinoRoll.default; 24 - 25 - let logPath = path.resolve(configDir, `./logs`); 26 - if (typeof process.env.CONFIG_DIR === 'string') { 27 - logPath = path.resolve(process.env.CONFIG_DIR, './logs'); 28 - } 29 - 30 - export type AppLogger = LabelledLogger 31 - 32 - const CWD = process.cwd(); 33 - export const prettyOptsFactory = (opts: PrettyOptions = {}): PrettyOptions => { 34 - const {colorize} = opts; 35 - const colorizeOpts: undefined | {useColor: boolean} = colorize === undefined ? undefined : {useColor: colorize}; 36 - const colors = createColors(colorizeOpts) 2 + import {isLogOptions, LogLevel, LogOptions} from "./types.js"; 37 3 38 - return { 39 - ...prettyCommon(), 40 - ...opts 41 - } 42 - } 43 - 44 - export const prettyCommon = (): PrettyOptions => { 45 - return { 46 - messageFormat: (log, messageKey, levelLabel, { colors }) => { 47 - const labels: string[] = log.labels as string[] ?? []; 48 - const leaf = log.leaf as string | undefined; 49 - const nodes = labels; 50 - if (leaf !== null && leaf !== undefined && !nodes.includes(leaf)) { 51 - nodes.push(leaf); 52 - } 53 - const labelContent = nodes.length === 0 ? '' : `${nodes.map((x: string) => colors.blackBright(`[${x}]`)).join(' ')} `; 54 - const msg = log[messageKey]; 55 - const stackTrace = log.err !== undefined ? `\n${(log.err as any).stack.replace(CWD, 'CWD')}` : ''; 56 - return `${labelContent}${msg}${stackTrace}`; 57 - }, 58 - hideObject: false, 59 - ignore: 'pid,hostname,labels,err', 60 - translateTime: 'SYS:standard', 61 - customLevels: { 62 - verbose: 25, 63 - log: 21, 64 - }, 65 - customColors: 'verbose:magenta,log:greenBright', 66 - colorizeObjects: true, 67 - // @ts-ignore 68 - useOnlyCustomProps: false, 69 - } 70 - } 71 - 72 - export const prettyConsole: PrettyOptions = prettyOptsFactory() 73 - export const prettyFile: PrettyOptions = prettyOptsFactory({ 74 - colorize: false, 75 - }); 76 - 77 - export const buildParsedLogOptions = (config: object = {}): Required<LogOptions> => { 78 - if (!asLogOptions(config)) { 79 - throw new Error(`Logging levels were not valid. Must be one of: 'error', 'warn', 'info', 'verbose', 'debug', 'silent' -- 'file' may be false.`) 4 + export const parseLogOptions = (config: LogOptions = {}): Required<LogOptions> => { 5 + if (!isLogOptions(config)) { 6 + throw new Error(`Logging levels were not valid. Must be one of: 'silent', 'fatal', 'error', 'warn', 'info', 'verbose', 'debug', -- 'file' may be false.`) 80 7 } 81 8 82 9 const {level: configLevel} = config; ··· 94 21 console 95 22 }; 96 23 } 97 - 98 - export const buildPinoFileStream = async (options: Required<LogOptions> & { path?: string }): Promise<AllLevelStreamEntry | undefined> => { 99 - const {file} = options; 100 - if(file === false) { 101 - return undefined; 102 - } 103 - 104 - const logToPath = options.path ?? logPath; 105 - 106 - try { 107 - fileOrDirectoryIsWriteable(logToPath); 108 - const rollingDest = await pRoll({ 109 - file: path.resolve(logToPath, 'app'), 110 - size: 10, 111 - frequency: 'daily', 112 - get extension() {return `-${new Date().toISOString().split('T')[0]}.log`}, 113 - mkdir: true, 114 - sync: false, 115 - }); 116 - 117 - return { 118 - level: file as LogLevel, 119 - stream: prettyDef.default({...prettyFile, destination: rollingDest}) 120 - }; 121 - } catch (e: any) { 122 - throw new ErrorWithCause<Error>('WILL NOT write logs to rotating file due to an error while trying to access the specified logging directory', {cause: e as Error}); 123 - } 124 - } 125 - 126 - export const buildPinoConsoleStream = (options: Required<LogOptions> & {stream?: DestinationStream | NodeJS.WritableStream} & PrettyOptions): AllLevelStreamEntry => { 127 - const {console, stream = 1, ...rest} = options; 128 - return { 129 - level: console as LogLevel, 130 - stream: prettyDef.default({...prettyConsole, ...rest, destination: stream, sync: true}) 131 - } 132 - } 133 - 134 - export const buildPinoLogger = (defaultLevel: LevelWithSilentOrString, streams: AllLevelStreamEntry[]): LabelledLogger => { 135 - const plogger = pino({ 136 - // @ts-ignore 137 - mixin: (obj, num, loggerThis) => { 138 - return { 139 - labels: loggerThis.labels ?? [] 140 - } 141 - }, 142 - level: defaultLevel, 143 - customLevels: { 144 - verbose: 25, 145 - log: 21 146 - }, 147 - useOnlyCustomLevels: false, 148 - }, pino.multistream(streams)) as LabelledLogger; 149 - plogger.labels = []; 150 - 151 - plogger.addLabel = function (value) { 152 - if (this.labels === undefined) { 153 - this.labels = []; 154 - } 155 - this.labels.push(value) 156 - } 157 - return plogger; 158 - } 159 - 160 - export const testPinoLogger = buildPinoLogger('silent', [buildPinoConsoleStream(buildParsedLogOptions({level: 'debug'}))]); 161 - 162 - export const initPinoLogger = buildPinoLogger('debug', [buildPinoConsoleStream(buildParsedLogOptions({level: 'debug'}))]); 163 - 164 - export const appPinoLogger = async (config: LogOptions | object = {}, name = 'App') => { 165 - const options = buildParsedLogOptions(config); 166 - const streams: AllLevelStreamEntry[] = [buildPinoConsoleStream(options)]; 167 - const file = await buildPinoFileStream(options); 168 - if(file !== undefined) { 169 - streams.push(file); 170 - } 171 - return buildPinoLogger('debug' as LevelWithSilentOrString, streams); 172 - } 173 - 174 - export const createChildPinoLogger = (parent: LabelledLogger, labelsVal: any | any[] = [], context: object = {}, options = {}) => { 175 - const newChild = parent.child(context, options) as LabelledLogger; 176 - const labels = Array.isArray(labelsVal) ? labelsVal : [labelsVal]; 177 - newChild.labels = [...[...(parent.labels ?? [])], ...labels]; 178 - newChild.addLabel = function (value) { 179 - if(this.labels === undefined) { 180 - this.labels = []; 181 - } 182 - this.labels.push(value); 183 - } 184 - return newChild 185 - } 186 - export const createChildLogger = (logger: AppLogger, labelsVal: any | any[] = []): AppLogger => { 187 - const labels = Array.isArray(labelsVal) ? labelsVal : [labelsVal]; 188 - return createChildPinoLogger(logger as LabelledLogger, labels); 189 - }
+20 -43
src/index.ts
··· 1 1 import { 2 - LabelledLogger, 3 - AllLevels, 4 - AllLevelStreamEntry, 2 + Logger, 3 + LogLevelStreamEntry, 5 4 LogOptions, 6 - asLogOptions, 7 - LogData 5 + isLogOptions, 6 + LogData, 7 + LogLevel, 8 + LOG_LEVELS 8 9 } from './types.js' 9 10 10 11 import { 11 - prettyOptsFactory, 12 - prettyFile, 13 - prettyConsole, 14 - buildPinoLogger, 15 - buildPinoConsoleStream, 16 - buildPinoFileStream, 17 - buildParsedLogOptions, 18 - testPinoLogger, 19 - initPinoLogger, 20 - appPinoLogger, 21 - createChildLogger, 12 + parseLogOptions, 22 13 } from './funcs.js' 23 14 15 + import {childLogger, loggerApp, loggerInit, loggerTest} from './loggers.js'; 16 + 24 17 export type { 25 - LabelledLogger, 26 - AllLevels, 27 - AllLevelStreamEntry, 18 + Logger, 19 + LogLevelStreamEntry, 28 20 LogOptions, 29 - LogData 21 + LogData, 22 + LogLevel, 23 + LOG_LEVELS 30 24 } 31 25 32 26 export { 33 - asLogOptions, 34 - buildParsedLogOptions 35 - } 36 - 37 - export const streamBuilders = { 38 - file: buildPinoFileStream, 39 - console: buildPinoConsoleStream, 27 + loggerApp, 28 + loggerInit, 29 + loggerTest, 30 + childLogger, 31 + parseLogOptions, 32 + isLogOptions 40 33 } 41 - 42 - export const pretty = { 43 - buildPretty: prettyOptsFactory, 44 - prettyFile, 45 - prettyConsole, 46 - }; 47 - 48 - export const buildLogger = buildPinoLogger; 49 - 50 - export const loggers = { 51 - init: initPinoLogger, 52 - test: testPinoLogger, 53 - app: appPinoLogger 54 - }; 55 - 56 - export const childLogger = createChildLogger;
+55
src/loggers.ts
··· 1 + import {parseLogOptions} from "./funcs.js"; 2 + import {Logger, LogLevel, LogLevelStreamEntry, LogOptions} from "./types.js"; 3 + import {buildDestinationStream, buildDestinationFile} from "./destinations.js"; 4 + import {pino} from "pino"; 5 + 6 + export const buildLogger = (defaultLevel: LogLevel, streams: LogLevelStreamEntry[]): Logger => { 7 + const plogger = pino({ 8 + // @ts-ignore 9 + mixin: (obj, num, loggerThis) => { 10 + return { 11 + labels: loggerThis.labels ?? [] 12 + } 13 + }, 14 + level: defaultLevel, 15 + customLevels: { 16 + verbose: 25, 17 + log: 21 18 + }, 19 + useOnlyCustomLevels: false, 20 + }, pino.multistream(streams)) as Logger; 21 + plogger.labels = []; 22 + 23 + plogger.addLabel = function (value) { 24 + if (this.labels === undefined) { 25 + this.labels = []; 26 + } 27 + this.labels.push(value) 28 + } 29 + return plogger; 30 + } 31 + export const childLogger = (parent: Logger, labelsVal: any | any[] = [], context: object = {}, options = {}): Logger => { 32 + const newChild = parent.child(context, options) as Logger; 33 + const labels = Array.isArray(labelsVal) ? labelsVal : [labelsVal]; 34 + newChild.labels = [...[...(parent.labels ?? [])], ...labels]; 35 + newChild.addLabel = function (value) { 36 + if (this.labels === undefined) { 37 + this.labels = []; 38 + } 39 + this.labels.push(value); 40 + } 41 + return newChild 42 + } 43 + export const loggerTest = buildLogger('silent', [buildDestinationStream(parseLogOptions({level: 'debug'}))]); 44 + 45 + export const loggerInit = buildLogger('debug', [buildDestinationStream(parseLogOptions({level: 'debug'}))]); 46 + 47 + export const loggerApp = async (config: LogOptions | object = {}) => { 48 + const options = parseLogOptions(config); 49 + const streams: LogLevelStreamEntry[] = [buildDestinationStream(options)]; 50 + const file = await buildDestinationFile(options); 51 + if(file !== undefined) { 52 + streams.push(file); 53 + } 54 + return buildLogger('debug' as LogLevel, streams); 55 + }
+35
src/pretty.ts
··· 1 + import {PrettyOptions} from "pino-pretty"; 2 + import {CWD} from "./util.js"; 3 + 4 + export const prettyOptsFactory = (opts: PrettyOptions = {}): PrettyOptions => { 5 + return { 6 + messageFormat: (log, messageKey, levelLabel, {colors}) => { 7 + const labels: string[] = log.labels as string[] ?? []; 8 + const leaf = log.leaf as string | undefined; 9 + const nodes = labels; 10 + if (leaf !== null && leaf !== undefined && !nodes.includes(leaf)) { 11 + nodes.push(leaf); 12 + } 13 + const labelContent = nodes.length === 0 ? '' : `${nodes.map((x: string) => colors.blackBright(`[${x}]`)).join(' ')} `; 14 + const msg = log[messageKey]; 15 + const stackTrace = log.err !== undefined ? `\n${(log.err as any).stack.replace(CWD, 'CWD')}` : ''; 16 + return `${labelContent}${msg}${stackTrace}`; 17 + }, 18 + hideObject: false, 19 + ignore: 'pid,hostname,labels,err', 20 + translateTime: 'SYS:standard', 21 + customLevels: { 22 + verbose: 25, 23 + log: 21, 24 + }, 25 + customColors: 'verbose:magenta,log:greenBright', 26 + colorizeObjects: true, 27 + // @ts-ignore 28 + useOnlyCustomProps: false, 29 + ...opts 30 + } 31 + } 32 + export const prettyConsole: PrettyOptions = prettyOptsFactory() 33 + export const prettyFile: PrettyOptions = prettyOptsFactory({ 34 + colorize: false, 35 + });
+8 -10
src/types.ts
··· 1 - import {Level, Logger, StreamEntry} from 'pino'; 1 + import {Level, Logger as PinoLogger, StreamEntry} from 'pino'; 2 2 import {ErrorWithCause} from "pony-cause"; 3 3 4 - export type AdditionalLevels = "verbose" | "log"; 5 - export type AllLevels = typeof LOGLEVELS[number]; 6 - export type LogLevel = AllLevels 7 - export const LOGLEVELS= ['fatal', 'error', 'warn', 'info', 'log', 'verbose', 'debug'] as (Level | AdditionalLevels)[]; 4 + export type LogLevel = typeof LOG_LEVELS[number]; 5 + export const LOG_LEVELS= ['silent', 'fatal', 'error', 'warn', 'info', 'log', 'verbose', 'debug'] as const; 8 6 9 7 export interface LogOptions { 10 8 /** ··· 25 23 console?: LogLevel 26 24 } 27 25 28 - export const asLogOptions = (obj: object = {}): obj is LogOptions => { 26 + export const isLogOptions = (obj: object = {}): obj is LogOptions => { 29 27 return Object.entries(obj).every(([key, val]) => { 30 28 const t = typeof val; 31 29 if(t !== 'string' && t !== 'boolean') { 32 30 return false; 33 31 } 34 32 if (key !== 'file') { 35 - return val === undefined || LOGLEVELS.includes(val.toLocaleLowerCase()); 33 + return val === undefined || LOG_LEVELS.includes(val.toLocaleLowerCase()); 36 34 } 37 - return val === undefined || val === false || LOGLEVELS.includes(val.toLocaleLowerCase()); 35 + return val === undefined || val === false || LOG_LEVELS.includes(val.toLocaleLowerCase()); 38 36 }); 39 37 } 40 38 41 - export type LabelledLogger = Logger<LogLevel> & { 39 + export type Logger = PinoLogger<LogLevel> & { 42 40 labels: any[] 43 41 addLabel: (value: any) => void 44 42 } 45 43 46 - export type AllLevelStreamEntry = StreamEntry<AllLevels> 44 + export type LogLevelStreamEntry = StreamEntry<LogLevel> 47 45 48 46 export type LogData = Record<string, any> & { 49 47 level: number
+3
src/util.ts
··· 1 1 import pathUtil from "path"; 2 2 import {accessSync, constants} from "fs"; 3 3 import {ErrorWithCause} from "pony-cause"; 4 + import process from "process"; 4 5 5 6 export const fileOrDirectoryIsWriteable = (location: string) => { 6 7 const pathInfo = pathUtil.parse(location); ··· 35 36 export function sleep(ms: number) { 36 37 return new Promise(resolve => setTimeout(resolve, ms)); 37 38 } 39 + 40 + export const CWD = process.cwd();
+36 -30
tests/index.test.ts
··· 1 1 import {describe} from "mocha"; 2 - import {buildParsedLogOptions, LabelledLogger, loggers} from '../src/index.js'; 3 - import {buildPinoConsoleStream, buildPinoFileStream, buildPinoLogger, createChildLogger} from "../src/funcs.js"; 2 + import {parseLogOptions, Logger, childLogger} from '../src/index.js'; 4 3 import {PassThrough, Transform} from "node:stream"; 5 4 import chai, {expect} from "chai"; 6 5 import {pEvent} from 'p-event'; 7 6 import {sleep} from "../src/util.js"; 8 - import {LogData, LOGLEVELS} from "../src/types.js"; 7 + import {LogData, LOG_LEVELS} from "../src/types.js"; 9 8 import withLocalTmpDir from 'with-local-tmp-dir'; 10 9 import {readdirSync,} from 'node:fs'; 10 + import {buildDestinationStream, buildDestinationFile} from "../src/destinations.js"; 11 + import {buildLogger} from "../src/loggers.js"; 11 12 12 13 13 - const testConsoleLogger = (config?: object): [LabelledLogger, Transform, Transform] => { 14 - const opts = buildParsedLogOptions(config); 14 + const testConsoleLogger = (config?: object): [Logger, Transform, Transform] => { 15 + const opts = parseLogOptions(config); 15 16 const testStream = new PassThrough(); 16 17 const rawStream = new PassThrough(); 17 - const logger = buildPinoLogger('debug', [ 18 - buildPinoConsoleStream( 18 + const logger = buildLogger('debug', [ 19 + buildDestinationStream( 19 20 { 20 21 stream: testStream, 21 22 colorize: false, ··· 31 32 } 32 33 33 34 const testFileLogger = async (config?: object) => { 34 - const streamEntry = await buildPinoFileStream( 35 + const streamEntry = await buildDestinationFile( 35 36 { 36 37 path: '.', 37 - ...buildParsedLogOptions(config) 38 + ...parseLogOptions(config) 38 39 } 39 40 ); 40 - return buildPinoLogger('debug', [ 41 + return buildLogger('debug', [ 41 42 streamEntry 42 43 ]); 43 44 }; ··· 45 46 describe('Config Parsing', function () { 46 47 47 48 it('does not throw when no arg is given', function () { 48 - expect(() => buildParsedLogOptions()).to.not.throw; 49 + expect(() => parseLogOptions()).to.not.throw; 49 50 }) 50 51 51 52 it('does not throw when a valid level is given', function () { 52 - for (const level of LOGLEVELS) { 53 - expect(() => buildParsedLogOptions({level})).to.not.throw; 53 + for (const level of LOG_LEVELS) { 54 + expect(() => parseLogOptions({level})).to.not.throw; 54 55 } 55 56 }) 56 57 57 58 it('throws when an invalid level is given', function () { 58 - expect(() => buildParsedLogOptions({level: 'nah'})).to.throw; 59 - expect(() => buildParsedLogOptions({file: 'nah'})).to.throw; 60 - expect(() => buildParsedLogOptions({console: 'nah'})).to.throw; 59 + // @ts-expect-error 60 + expect(() => parseLogOptions({level: 'nah'})).to.throw; 61 + // @ts-expect-error 62 + expect(() => parseLogOptions({file: 'nah'})).to.throw; 63 + // @ts-expect-error 64 + expect(() => parseLogOptions({console: 'nah'})).to.throw; 61 65 }) 62 66 63 67 it('throws when an option is not a string/boolean', function () { 64 - expect(() => buildParsedLogOptions({console: {level: 'info'}})).to.throw; 68 + // @ts-expect-error 69 + expect(() => parseLogOptions({console: {level: 'info'}})).to.throw; 65 70 }) 66 71 67 72 it('throws when file option is not a string/false', function () { 68 - expect(() => buildParsedLogOptions({file: true})).to.throw; 73 + // @ts-expect-error 74 + expect(() => parseLogOptions({file: true})).to.throw; 69 75 }) 70 76 71 77 it(`defaults to 'info' level except console`, function () { 72 - const defaultConfig = buildParsedLogOptions(); 78 + const defaultConfig = parseLogOptions(); 73 79 expect(defaultConfig.level).eq('info') 74 80 expect(defaultConfig.file).eq('info') 75 81 }); 76 82 77 83 it(`defaults to 'debug' level for console`, function () { 78 - const defaultConfig = buildParsedLogOptions(); 84 + const defaultConfig = parseLogOptions(); 79 85 expect(defaultConfig.console).eq('debug') 80 86 }); 81 87 82 88 it(`uses level for option when given`, function () { 83 - const config = buildParsedLogOptions({ 89 + const config = parseLogOptions({ 84 90 file: 'error', 85 91 console: 'warn', 86 92 level: 'debug' ··· 144 150 describe('Arguments', function() { 145 151 it('has no labels when none are provided', function() { 146 152 const [logger] = testConsoleLogger(); 147 - const child = createChildLogger(logger); 153 + const child = childLogger(logger); 148 154 expect(child.labels.length).eq(0); 149 155 }); 150 156 151 157 it('has labels when provided as string', function() { 152 158 const [logger] = testConsoleLogger(); 153 - const child = createChildLogger(logger, 'test'); 159 + const child = childLogger(logger, 'test'); 154 160 expect(child.labels.length).eq(1); 155 161 }); 156 162 157 163 it('has labels when provided as array', function() { 158 164 const [logger] = testConsoleLogger(); 159 - const child = createChildLogger(logger, ['test','test2']); 165 + const child = childLogger(logger, ['test','test2']); 160 166 expect(child.labels.length).eq(2); 161 167 }); 162 168 }); ··· 166 172 const [logger, testStream, rawStream] = testConsoleLogger(); 167 173 const formattedBuff = pEvent(testStream, 'data'); 168 174 const rawBuff = pEvent(rawStream, 'data'); 169 - const child = createChildLogger(logger, 'Test'); 175 + const child = childLogger(logger, 'Test'); 170 176 child.debug('log something'); 171 177 await sleep(10); 172 178 const formatted = (await formattedBuff).toString(); ··· 181 187 const [logger, testStream, rawStream] = testConsoleLogger(); 182 188 const formattedBuff = pEvent(testStream, 'data'); 183 189 const rawBuff = pEvent(rawStream, 'data'); 184 - const child = createChildLogger(logger, ['Test1', 'Test2']); 190 + const child = childLogger(logger, ['Test1', 'Test2']); 185 191 child.debug('log something'); 186 192 await sleep(10); 187 193 const formatted = (await formattedBuff).toString(); ··· 197 203 const [logger, testStream, rawStream] = testConsoleLogger(); 198 204 const formattedBuff = pEvent(testStream, 'data'); 199 205 const rawBuff = pEvent(rawStream, 'data'); 200 - const child = createChildLogger(logger, ['Test1', 'Test2']); 201 - const child2 = createChildLogger(child, ['Test3', 'Test4']); 202 - const child3 = createChildLogger(child2, ['Test5']); 206 + const child = childLogger(logger, ['Test1', 'Test2']); 207 + const child2 = childLogger(child, ['Test3', 'Test4']); 208 + const child3 = childLogger(child2, ['Test5']); 203 209 child3.debug('log something'); 204 210 await sleep(10); 205 211 const formatted = (await formattedBuff).toString(); ··· 220 226 const rawBuff = pEvent(rawStream, 'data'); 221 227 222 228 logger.addLabel('Parent'); 223 - const child = createChildLogger(logger, ['Test1']); 229 + const child = childLogger(logger, ['Test1']); 224 230 logger.debug('log something'); 225 231 await sleep(10); 226 232 const formatted = (await formattedBuff).toString();
+6
tsconfig.build.json
··· 1 + { 2 + "extends": "./tsconfig.json", 3 + "compilerOptions": { 4 + "noEmit": false 5 + } 6 + }
+2 -1
tsconfig.json
··· 11 11 "forceConsistentCasingInFileNames": true, 12 12 "allowSyntheticDefaultImports": true, 13 13 "useDefineForClassFields": true, 14 - "isolatedModules": true 14 + "isolatedModules": true, 15 + "noEmit": true 15 16 }, 16 17 "ts-node": { 17 18 "esm": true