From da139778038113b61fa8d8137b53d1015a0ac24b Mon Sep 17 00:00:00 2001 From: Igor Savin Date: Wed, 26 May 2021 15:34:30 +0300 Subject: [PATCH] Add TS types (#30) --- .eslintignore | 2 + .github/workflows/ci.yml | 2 + index.d.ts | 132 +++++++++++++++++++++++++++++++++++++ package.json | 13 +++- test/types/index.test-d.ts | 57 ++++++++++++++++ tsconfig.json | 13 ++++ 6 files changed, 217 insertions(+), 2 deletions(-) create mode 100644 .eslintignore create mode 100644 index.d.ts create mode 100644 test/types/index.test-d.ts create mode 100644 tsconfig.json diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..2abb4c2 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +index.d.ts +test/types/index.test-d.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 576fdb3..08b8e17 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,8 @@ jobs: NODE_ENV: development - name: Lint-CI run: npm run lint-ci + - name: Test-Types + run: npm run test-types - name: Test-CI run: npm run test-ci diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..56e34f0 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,132 @@ +// Type definitions for pino-std-serializers 2.4 +// Definitions by: Connor Fitzgerald +// Igor Savin +// TypeScript Version: 2.7 + +/// +import { IncomingMessage, ServerResponse } from 'http'; + +export interface SerializedError { + /** + * The name of the object's constructor. + */ + type: string; + /** + * The supplied error message. + */ + message: string; + /** + * The stack when the error was generated. + */ + stack: string; + /** + * Non-enumerable. The original Error object. This will not be included in the logged output. + * This is available for subsequent serializers to use. + */ + raw: Error; + /** + * Any other extra properties that have been attached to the object will also be present on the serialized object. + */ + [key: string]: any; + [key: number]: any; +} + +/** + * Serializes an Error object. + */ +export function err(err: Error): SerializedError; + +export interface SerializedRequest { + /** + * Defaults to `undefined`, unless there is an `id` property already attached to the `request` object or + * to the `request.info` object. Attach a synchronous function to the `request.id` that returns an + * identifier to have the value filled. + */ + id: string | undefined; + /** + * HTTP method. + */ + method: string; + /** + * Request pathname (as per req.url in core HTTP). + */ + url: string; + /** + * Reference to the `headers` object from the request (as per req.headers in core HTTP). + */ + headers: Record; + remoteAddress: string; + remotePort: number; + /** + * Non-enumerable, i.e. will not be in the output, original request object. This is available for subsequent + * serializers to use. In cases where the `request` input already has a `raw` property this will + * replace the original `request.raw` property. + */ + raw: IncomingMessage; +} + +/** + * Serializes a Request object. + */ +export function req(req: IncomingMessage): SerializedRequest; + +/** + * Used internally by Pino for general request logging. + */ +export function mapHttpRequest(req: IncomingMessage): { + req: SerializedRequest +}; + +export interface SerializedResponse { + /** + * HTTP status code. + */ + statusCode: number; + /** + * The headers to be sent in the response. + */ + headers: Record; + /** + * Non-enumerable, i.e. will not be in the output, original response object. This is available for subsequent serializers to use. + */ + raw: ServerResponse; +} + +/** + * Serializes a Response object. + */ +export function res(res: ServerResponse): SerializedResponse; + +/** + * Used internally by Pino for general response logging. + */ +export function mapHttpResponse(res: ServerResponse): { + res: SerializedResponse +}; + +export type CustomErrorSerializer = (err: SerializedError) => Record; + +/** + * A utility method for wrapping the default error serializer. + * This allows custom serializers to work with the already serialized object. + * The customSerializer accepts one parameter — the newly serialized error object — and returns the new (or updated) error object. + */ +export function wrapErrorSerializer(customSerializer: CustomErrorSerializer): (err: Error) => Record; + +export type CustomRequestSerializer = (req: SerializedRequest) => Record; + +/** + * A utility method for wrapping the default response serializer. + * This allows custom serializers to work with the already serialized object. + * The customSerializer accepts one parameter — the newly serialized response object — and returns the new (or updated) response object. + */ +export function wrapRequestSerializer(customSerializer: CustomRequestSerializer): (req: IncomingMessage) => Record; + +export type CustomResponseSerializer = (res: SerializedResponse) => Record; + +/** + * A utility method for wrapping the default request serializer. + * This allows custom serializers to work with the already serialized object. + * The customSerializer accepts one parameter — the newly serialized request object — and returns the new (or updated) request object. + */ +export function wrapResponseSerializer(customSerializer: CustomResponseSerializer): (res: ServerResponse) => Record; diff --git a/package.json b/package.json index 5cd75e6..47f2092 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,14 @@ "version": "3.2.0", "description": "A collection of standard object serializers for Pino", "main": "index.js", + "type": "commonjs", + "types": "index.d.ts", "scripts": { "lint": "standard | snazzy", "lint-ci": "standard", "test": "tap --no-cov 'test/**/*.test.js'", - "test-ci": "tap --cov --coverage-report=text 'test/**/*.test.js'" + "test-ci": "tap --cov --coverage-report=text 'test/**/*.test.js'", + "test-types": "tsc && tsd" }, "repository": { "type": "git", @@ -28,9 +31,15 @@ "test" ], "devDependencies": { + "@types/node": "^15.3.0", "pre-commit": "^1.2.2", "snazzy": "^9.0.0", "standard": "^16.0.0", - "tap": "^14.0.0" + "tap": "^14.0.0", + "tsd": "^0.15.1", + "typescript": "^4.2.4" + }, + "tsd": { + "directory": "test/types" } } diff --git a/test/types/index.test-d.ts b/test/types/index.test-d.ts new file mode 100644 index 0000000..0419828 --- /dev/null +++ b/test/types/index.test-d.ts @@ -0,0 +1,57 @@ +import {IncomingMessage, ServerResponse} from "http"; +import { + err, + req, + res, + SerializedError, + SerializedRequest, + wrapErrorSerializer, + wrapRequestSerializer, + wrapResponseSerializer, + SerializedResponse +} from '../../'; + +const customErrorSerializer = (error: SerializedError) => { + return { + myOwnError: { + data: `${error.type}-${error.message}\n\n${error.stack}`, + } + }; +}; + +const customRequestSerializer = (req: SerializedRequest) => { + const {headers, id, method, raw, remoteAddress, remotePort, url} = req; + return { + myOwnRequest: { + data: `${method}-${id}-${remoteAddress}-${remotePort}-${url}`, + headers, + raw, + } + }; +}; + +const customResponseSerializer = (res: SerializedResponse) => { + const {headers, raw, statusCode} = res; + return { + myOwnResponse: { + data: statusCode, + headers, + raw, + } + }; +}; + +const fakeError = new Error('A fake error for testing'); +const serializedError: SerializedError = err(fakeError); +const mySerializer = wrapErrorSerializer(customErrorSerializer); + +const request: IncomingMessage = {} as IncomingMessage +const serializedRequest: SerializedRequest = req(request); +const myReqSerializer = wrapRequestSerializer(customRequestSerializer); + +const response: ServerResponse = {} as ServerResponse +const myResSerializer = wrapResponseSerializer(customResponseSerializer); +const serializedResponse = res(response); + +myResSerializer(response) + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..8e0b9fa --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es6", + "lib": [ "es2015" ], + "module": "commonjs", + "noEmit": true, + "strict": true + }, + "include": [ + "./test/types/*.test-d.ts", + "./index.d.ts" + ] +}