diff --git a/eslint.config.js b/eslint.config.js index 5212dc93..e66d9015 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,3 +1,5 @@ 'use strict' -module.exports = require('neostandard')({}) +module.exports = require('neostandard')({ + ts: true +}) diff --git a/index.d.ts b/index.d.ts index d4aae86f..dde8cb24 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,23 +1,18 @@ -// Type definitions for pino-pretty 7.0 // Project: https://github.com/pinojs/pino-pretty#readme // Definitions by: Adam Vigneaux // tearwyx -// Minimum TypeScript Version: 3.0 /// -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; - -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, @@ -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 @@ -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. * @@ -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. * @@ -216,19 +211,17 @@ declare namespace PinoPretty { useOnlyCustomProps?: boolean; } - function build(options: PrettyOptions): PrettyStream; + export function build (options?: PrettyOptions): PrettyStream - 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; + 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, messageKey: string, levelLabel: string, extras: Pick) => string + 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 diff --git a/package.json b/package.json index e2020271..af8d2763 100644 --- a/package.json +++ b/package.json @@ -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 .", "test:watch": "borp -w --reporter gh", "test:report": "c8 --reporter html borp" }, @@ -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" } } diff --git a/test/types/exports.tst.ts b/test/types/exports.tst.ts new file mode 100644 index 00000000..14073501 --- /dev/null +++ b/test/types/exports.tst.ts @@ -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() + expect(PinoPrettyNamed(options)).type.toBe() + expect(PinoPrettyStar.PinoPretty(options)).type.toBe() + expect(PinoPrettyCjsImport.PinoPretty(options)).type.toBe() +}) diff --git a/test/types/pino-pretty.test-d.ts b/test/types/pino-pretty.test-d.ts deleted file mode 100644 index 8649edc3..00000000 --- a/test/types/pino-pretty.test-d.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { expectType } from "tsd"; - -import pretty from "../../"; -import PinoPretty, { - PinoPretty as PinoPrettyNamed, - PrettyOptions, - colorizerFactory, - prettyFactory -} from "../../"; -import PinoPrettyDefault from "../../"; -import * as PinoPrettyStar from "../../"; -import PinoPrettyCjsImport = require("../../"); -import PrettyStream = PinoPretty.PrettyStream; -const PinoPrettyCjs = require("../../"); - -const options: PinoPretty.PrettyOptions = { - colorize: true, - crlf: false, - errorLikeObjectKeys: ["err", "error"], - errorProps: "", - hideObject: true, - levelKey: "level", - levelLabel: "foo", - messageFormat: false, - ignore: "", - levelFirst: false, - messageKey: "msg", - timestampKey: "timestamp", - minimumLevel: "trace", - translateTime: "UTC:h:MM:ss TT Z", - singleLine: false, - customPrettifiers: { - key: (value) => { - return value.toString().toUpperCase(); - }, - level: (level, levelKey, log, { label, labelColorized, colors }) => { - return level.toString(); - }, - foo: (value, key, log, { colors }) => { - return value.toString(); - } - }, - customLevels: 'verbose:5', - customColors: 'default:white,verbose:gray', - sync: false, - destination: 2, - append: true, - mkdir: true, - useOnlyCustomProps: false, -}; - -expectType(pretty()); // #326 -expectType(pretty(options)); -expectType(PinoPrettyNamed(options)); -expectType(PinoPrettyDefault(options)); -expectType(PinoPrettyStar.PinoPretty(options)); -expectType(PinoPrettyCjsImport.PinoPretty(options)); -expectType(PinoPrettyCjs(options)); diff --git a/test/types/pino-pretty.tst.ts b/test/types/pino-pretty.tst.ts new file mode 100644 index 00000000..8f1e591f --- /dev/null +++ b/test/types/pino-pretty.tst.ts @@ -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() + expect(pretty(options)).type.toBe() +}) + +test('build', () => { + expect(build()).type.toBe() + expect(build(options)).type.toBe() +}) + +test('PinoPretty', () => { + expect(PinoPretty()).type.toBe() + expect(PinoPretty(options)).type.toBe() +}) + +test('PrettyStream', () => { + const stream = pretty() + pino(stream) + + expect().type.toBeAssignableTo() +}) + +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() + expect(colorizer.greyMessage(input)).type.toBe() + + let level: string | number | undefined + expect(colorizer(level)).type.toBe() + + let customLevels: { [level: number]: string } | undefined + expect(colorizer(undefined, { customLevels })).type.toBe() + + let customLevelNames: { [name: string]: number } | undefined + expect(colorizer(undefined, { customLevelNames })).type.toBe() +}) + +test('isColorSupported', () => { + expect(isColorSupported).type.toBe() +}) + +test('PrettyOptions', () => { + expect().type.toBeAssignableFrom({ colorize: true }) + expect().type.toBeAssignableFrom({ colorizeObjects: true }) + expect().type.toBeAssignableFrom({ crlf: false }) + expect().type.toBeAssignableFrom({ errorLikeObjectKeys: ['err', 'error'] }) + expect().type.toBeAssignableFrom({ errorProps: '' }) + expect().type.toBeAssignableFrom({ levelFirst: false }) + expect().type.toBeAssignableFrom({ messageKey: 'msg' }) + expect().type.toBeAssignableFrom({ levelKey: 'level' }) + expect().type.toBeAssignableFrom({ messageFormat: false as const }) + expect().type.toBeAssignableFrom({ messageFormat: '{levelLabel} - {pid} - url:{req.url}' }) + + const messageFormat: MessageFormatFunc = (log, messageKey, levelLabel, { colors }) => { + expect(log).type.toBe>() + expect(messageKey).type.toBe() + expect(levelLabel).type.toBe() + expect(colors).type.toBe() + + return '' + } + + expect().type.toBeAssignableFrom({ messageFormat }) + expect().type.toBeAssignableFrom({ timestampKey: 'time' }) + expect().type.toBeAssignableFrom({ translateTime: false }) + expect().type.toBeAssignableFrom({ translateTime: 'SYS:standard' }) + expect().type.toBeAssignableFrom({ ignore: 'pid,hostname' }) + expect().type.toBeAssignableFrom({ include: 'level,time' }) + expect().type.toBeAssignableFrom({ hideObject: false }) + expect().type.toBeAssignableFrom({ singleLine: false }) + expect().type.toBeAssignableFrom({ customColors: 'err:red,info:blue' }) + expect().type.toBeAssignableFrom({ customColors: { info: 'white', some_level: 'red' } }) + expect().type.toBeAssignableFrom({ customLevels: 'err:99,info:1' }) + expect().type.toBeAssignableFrom({ customLevels: { info: 10, some_level: 40 } }) + expect().type.toBeAssignableFrom({ levelLabel: 'levelLabel' }) + expect().type.toBeAssignableFrom<{ minimumLevel: pino.Level }>() + expect().type.toBeAssignableFrom({ useOnlyCustomProps: true }) + expect().type.toBeAssignableFrom({ destination: '1' }) + expect().type.toBeAssignableFrom({ destination: 1 }) + expect().type.toBeAssignableFrom<{ destination: pino.DestinationStream }>() + expect().type.toBeAssignableFrom<{ destination: NodeJS.WritableStream }>() + + expect().type.toBeAssignableFrom({ sync: false }) + expect().type.toBeAssignableFrom({ append: true }) + expect().type.toBeAssignableFrom({ mkdir: true }) + + const levelPrettifier: Prettifier = (input, key, log, { colors, label, labelColorized }) => { + expect(input).type.toBe() + expect(key).type.toBe() + expect(log).type.toBe() + expect(colors).type.toBe() + expect(label).type.toBe() + expect(labelColorized).type.toBe() + + return input.toString() + } + + const customPrettifiers: Record = { + time: timestamp => `🕰 ${timestamp}`, + level: logLevel => `LEVEL: ${logLevel}`, + name: (name, _key, _log, { colors }) => `${colors.blue(name.toString())}`, + } + + expect().type.toBeAssignableFrom({ customPrettifiers: { level: levelPrettifier } }) + expect().type.toBeAssignableFrom({ customPrettifiers }) +}) diff --git a/test/types/tsconfig.json b/test/types/tsconfig.json new file mode 100644 index 00000000..f1f0192b --- /dev/null +++ b/test/types/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "fastify-tsconfig", + "compilerOptions": { + "noEmit": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "types": [] + } +} diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 8a9ab13b..00000000 --- a/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "compilerOptions": { - "target": "es6", - "lib": [ "es2015" ], - "module": "commonjs", - "noEmit": true, - "strict": true, - "esModuleInterop": true - }, - "include": [ - "./test/types/pino-pretty.test.d.ts", - "./index.d.ts" - ] -}