Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

module.exports = require('neostandard')({})
module.exports = require('neostandard')({
ts: true
})
45 changes: 19 additions & 26 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
// Type definitions for pino-pretty 7.0
// Project: https://github.com/pinojs/pino-pretty#readme
// Definitions by: Adam Vigneaux <https://github.com/AdamVig>
// tearwyx <https://github.com/tearwyx>
// Minimum TypeScript Version: 3.0

/// <reference types="node" />

import { Transform } from 'node:stream';
import { OnUnknown } from 'pino-abstract-transport';
import { Transform } from 'node:stream'
import { OnUnknown } from 'pino-abstract-transport'
// @ts-ignore fall back to any if pino is not available, i.e. when running pino tests
import { DestinationStream, Level } from 'pino';
import * as Colorette from "colorette";
import { DestinationStream, Level } from 'pino'
import * as Colorette from 'colorette'

type LogDescriptor = Record<string, unknown>;
Copy link
Copy Markdown
Contributor Author

@mrazauskas mrazauskas Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LogDescriptor was used only once, so I moved it inline. Otherwise it should be exported, but would that be useful?


declare function PinoPretty(options?: PinoPretty.PrettyOptions): PinoPretty.PrettyStream;
declare function PinoPretty (options?: PinoPretty.PrettyOptions): PinoPretty.PrettyStream
declare namespace PinoPretty {

function colorizerFactory(
export function colorizerFactory (
useColors?: boolean,
customColors?: [number, string][],
useOnlyCustomProps?: boolean,
Expand All @@ -33,9 +28,9 @@ declare namespace PinoPretty {
greyMessage: (input: string | number) => string,
}

function prettyFactory(options: PrettyOptions): (inputData: any) => string
export function prettyFactory (options: PrettyOptions): (inputData: any) => string

interface PrettyOptions {
export interface PrettyOptions {
/**
* Hide objects from output (but not error object).
* @default false
Expand Down Expand Up @@ -197,7 +192,7 @@ declare namespace PinoPretty {
*
* Not required when used with pino >= 8.21.0
*/
customLevels?: string|object;
customLevels?: string | object;
/**
* Change the level colors to an user custom preset.
*
Expand All @@ -207,7 +202,7 @@ declare namespace PinoPretty {
* @example ( CSV ) customColors: 'info:white,some_level:red'
* @example ( Object ) customColors: { info: 'white', some_level: 'red' }
*/
customColors?: string|object;
customColors?: string | object;
/**
* Only use custom levels and colors (if provided); else fallback to default levels and colors.
*
Expand All @@ -216,19 +211,17 @@ declare namespace PinoPretty {
useOnlyCustomProps?: boolean;
}

function build(options: PrettyOptions): PrettyStream;
export function build (options?: PrettyOptions): PrettyStream
Copy link
Copy Markdown
Contributor Author

@mrazauskas mrazauskas Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like here options must be optional. Same as #327


type Prettifier = (inputData: string | object, key: string, log: object, extras: PrettifierExtras) => string;
type PrettifierExtras = {colors: Colorette.Colorette, label: string, labelColorized: string};
type MessageFormatFunc = (log: LogDescriptor, messageKey: string, levelLabel: string, extras: PrettifierExtras) => string;
type PrettyStream = Transform & OnUnknown;
type ColorizerFactory = typeof colorizerFactory;
type PrettyFactory = typeof prettyFactory;
type Build = typeof build;
Comment on lines -225 to -227
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These three types are not used and not exported. Can be removed. ESLint detected that.

type PrettifierExtras = { colors: Colorette.Colorette, label: string, labelColorized: string }
export type Prettifier = (inputData: string | object, key: string, log: object, extras: PrettifierExtras) => string
export type MessageFormatFunc = (log: Record<string, unknown>, messageKey: string, levelLabel: string, extras: Pick<PrettifierExtras, 'colors'>) => string
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Signature is updated to align with behaviour:

const msg = messageFormat(log, messageKey, levelLabel, { colors: colorizer.colors })

export type PrettyStream = Transform & OnUnknown

// @ts-ignore
export const isColorSupported = Colorette.isColorSupported;
export { build, PinoPretty, PrettyOptions, PrettyStream, colorizerFactory, prettyFactory };
export const isColorSupported = Colorette.isColorSupported

export { PinoPretty }
}

export = PinoPretty;
export = PinoPretty
10 changes: 4 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
"pino-pretty": "./bin.js"
},
"scripts": {
"ci": "eslint && borp --check-coverage && npm run test-types",
"ci": "eslint && borp --check-coverage && npm run test:types",
"lint": "eslint",
"lint:fix": "eslint --fix",
"test": "borp",
"test-types": "tsc && tsd && attw --pack .",
"test:types": "tstyche && attw --pack .",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to run tsc, because TSTyche does check .d.ts files as well.

"test:watch": "borp -w --reporter gh",
"test:report": "c8 --reporter html borp"
},
Expand Down Expand Up @@ -53,14 +53,12 @@
"borp": "^1.0.0",
"eslint": "^9.39.1",
"fastbench": "^1.0.1",
"fastify-tsconfig": "^3.0.0",
"neostandard": "^0.12.2",
"pino": "^10.1.0",
"rimraf": "^6.1.2",
"semver": "^7.6.0",
"tsd": "^0.33.0",
"tstyche": "^6.2.0",
"typescript": "^5.9.3"
},
"tsd": {
"directory": "./test/types"
}
}
15 changes: 15 additions & 0 deletions test/types/exports.tst.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { expect, test } from 'tstyche'

import type PinoPretty from '../../index.js'
import PinoPrettyDefault, { PinoPretty as PinoPrettyNamed } from '../../index.js'
import * as PinoPrettyStar from '../../index.js'
import PinoPrettyCjsImport = require('../../index.js')

declare const options: PinoPretty.PrettyOptions

test('exports', () => {
expect(PinoPrettyDefault(options)).type.toBe<PinoPretty.PrettyStream>()
expect(PinoPrettyNamed(options)).type.toBe<PinoPretty.PrettyStream>()
expect(PinoPrettyStar.PinoPretty(options)).type.toBe<PinoPretty.PrettyStream>()
expect(PinoPrettyCjsImport.PinoPretty(options)).type.toBe<PinoPretty.PrettyStream>()
})
58 changes: 0 additions & 58 deletions test/types/pino-pretty.test-d.ts

This file was deleted.

140 changes: 140 additions & 0 deletions test/types/pino-pretty.tst.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { expect, test } from 'tstyche'

import colorette from 'colorette'
import pino from 'pino'
import pretty, {
build,
colorizerFactory,
isColorSupported,
MessageFormatFunc,
PinoPretty,
Prettifier,
prettyFactory,
PrettyOptions,
PrettyStream
} from '../../index.js'

declare const options: PrettyOptions

test('default export', () => {
expect(pretty()).type.toBe<PrettyStream>()
expect(pretty(options)).type.toBe<PrettyStream>()
})

test('build', () => {
expect(build()).type.toBe<PrettyStream>()
expect(build(options)).type.toBe<PrettyStream>()
})

test('PinoPretty', () => {
expect(PinoPretty()).type.toBe<PrettyStream>()
expect(PinoPretty(options)).type.toBe<PrettyStream>()
})

test('PrettyStream', () => {
const stream = pretty()
pino(stream)

expect<PrettyStream>().type.toBeAssignableTo<pino.DestinationStream>()
})

test('prettyFactory', () => {
expect(prettyFactory(options)).type.toBe<(inputData: any) => string>()
expect(prettyFactory).type.not.toBeCallableWith()
})

test('colorizerFactory', () => {
const colorizer = colorizerFactory()

let useColors: boolean | undefined
expect(colorizerFactory(useColors)).type.toBe(colorizer)

let customColors: [number, string][] | undefined
expect(colorizerFactory(undefined, customColors)).type.toBe(colorizer)

let useOnlyCustomProps: boolean | undefined
expect(colorizerFactory(undefined, undefined, useOnlyCustomProps)).type.toBe(colorizer)

const input: string | number = ''
expect(colorizer.message(input)).type.toBe<string>()
expect(colorizer.greyMessage(input)).type.toBe<string>()

let level: string | number | undefined
expect(colorizer(level)).type.toBe<string>()

let customLevels: { [level: number]: string } | undefined
expect(colorizer(undefined, { customLevels })).type.toBe<string>()

let customLevelNames: { [name: string]: number } | undefined
expect(colorizer(undefined, { customLevelNames })).type.toBe<string>()
})

test('isColorSupported', () => {
expect(isColorSupported).type.toBe<boolean>()
})

test('PrettyOptions', () => {
expect<PrettyOptions>().type.toBeAssignableFrom({ colorize: true })
expect<PrettyOptions>().type.toBeAssignableFrom({ colorizeObjects: true })
expect<PrettyOptions>().type.toBeAssignableFrom({ crlf: false })
expect<PrettyOptions>().type.toBeAssignableFrom({ errorLikeObjectKeys: ['err', 'error'] })
expect<PrettyOptions>().type.toBeAssignableFrom({ errorProps: '' })
expect<PrettyOptions>().type.toBeAssignableFrom({ levelFirst: false })
expect<PrettyOptions>().type.toBeAssignableFrom({ messageKey: 'msg' })
expect<PrettyOptions>().type.toBeAssignableFrom({ levelKey: 'level' })
expect<PrettyOptions>().type.toBeAssignableFrom({ messageFormat: false as const })
expect<PrettyOptions>().type.toBeAssignableFrom({ messageFormat: '{levelLabel} - {pid} - url:{req.url}' })

const messageFormat: MessageFormatFunc = (log, messageKey, levelLabel, { colors }) => {
expect(log).type.toBe<Record<string, unknown>>()
expect(messageKey).type.toBe<string>()
expect(levelLabel).type.toBe<string>()
expect(colors).type.toBe<colorette.Colorette>()

return ''
}

expect<PrettyOptions>().type.toBeAssignableFrom({ messageFormat })
expect<PrettyOptions>().type.toBeAssignableFrom({ timestampKey: 'time' })
expect<PrettyOptions>().type.toBeAssignableFrom({ translateTime: false })
expect<PrettyOptions>().type.toBeAssignableFrom({ translateTime: 'SYS:standard' })
expect<PrettyOptions>().type.toBeAssignableFrom({ ignore: 'pid,hostname' })
expect<PrettyOptions>().type.toBeAssignableFrom({ include: 'level,time' })
expect<PrettyOptions>().type.toBeAssignableFrom({ hideObject: false })
expect<PrettyOptions>().type.toBeAssignableFrom({ singleLine: false })
expect<PrettyOptions>().type.toBeAssignableFrom({ customColors: 'err:red,info:blue' })
expect<PrettyOptions>().type.toBeAssignableFrom({ customColors: { info: 'white', some_level: 'red' } })
expect<PrettyOptions>().type.toBeAssignableFrom({ customLevels: 'err:99,info:1' })
expect<PrettyOptions>().type.toBeAssignableFrom({ customLevels: { info: 10, some_level: 40 } })
expect<PrettyOptions>().type.toBeAssignableFrom({ levelLabel: 'levelLabel' })
expect<PrettyOptions>().type.toBeAssignableFrom<{ minimumLevel: pino.Level }>()
expect<PrettyOptions>().type.toBeAssignableFrom({ useOnlyCustomProps: true })
expect<PrettyOptions>().type.toBeAssignableFrom({ destination: '1' })
expect<PrettyOptions>().type.toBeAssignableFrom({ destination: 1 })
expect<PrettyOptions>().type.toBeAssignableFrom<{ destination: pino.DestinationStream }>()
expect<PrettyOptions>().type.toBeAssignableFrom<{ destination: NodeJS.WritableStream }>()

expect<PrettyOptions>().type.toBeAssignableFrom({ sync: false })
expect<PrettyOptions>().type.toBeAssignableFrom({ append: true })
expect<PrettyOptions>().type.toBeAssignableFrom({ mkdir: true })

const levelPrettifier: Prettifier = (input, key, log, { colors, label, labelColorized }) => {
expect(input).type.toBe<string | object>()
expect(key).type.toBe<string>()
expect(log).type.toBe<object>()
expect(colors).type.toBe<colorette.Colorette>()
expect(label).type.toBe<string>()
expect(labelColorized).type.toBe<string>()

return input.toString()
}

const customPrettifiers: Record<string, Prettifier> = {
time: timestamp => `🕰 ${timestamp}`,
level: logLevel => `LEVEL: ${logLevel}`,
name: (name, _key, _log, { colors }) => `${colors.blue(name.toString())}`,
}

expect<PrettyOptions>().type.toBeAssignableFrom({ customPrettifiers: { level: levelPrettifier } })
expect<PrettyOptions>().type.toBeAssignableFrom({ customPrettifiers })
})
9 changes: 9 additions & 0 deletions test/types/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "fastify-tsconfig",
"compilerOptions": {
"noEmit": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"types": []
}
}
14 changes: 0 additions & 14 deletions tsconfig.json

This file was deleted.

Loading