From 6a45a1d60ed66fe51cf7c0922f7de2b02abd034c Mon Sep 17 00:00:00 2001 From: Dimitri Benin Date: Sun, 6 Jan 2019 20:02:44 +0100 Subject: [PATCH] [request-stats] Add types --- types/request-stats/index.d.ts | 190 +++++++++++++++++++++ types/request-stats/request-stats-tests.ts | 52 ++++++ types/request-stats/tsconfig.json | 23 +++ types/request-stats/tslint.json | 1 + 4 files changed, 266 insertions(+) create mode 100644 types/request-stats/index.d.ts create mode 100644 types/request-stats/request-stats-tests.ts create mode 100644 types/request-stats/tsconfig.json create mode 100644 types/request-stats/tslint.json diff --git a/types/request-stats/index.d.ts b/types/request-stats/index.d.ts new file mode 100644 index 0000000000..3f1afa19d4 --- /dev/null +++ b/types/request-stats/index.d.ts @@ -0,0 +1,190 @@ +// Type definitions for request-stats 3.0 +// Project: https://github.com/watson/request-stats +// Definitions by: BendingBender +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// +import { + Server as HttpServer, + IncomingMessage, + ServerResponse, + IncomingHttpHeaders, + OutgoingHttpHeaders, +} from 'http'; +import { Server as HttpsServer } from 'https'; +import { EventEmitter } from 'events'; + +export = requestStats; + +/** + * Attach request-stats to a HTTP server. + * If no callback is provided, you can later attach a listener on the "complete" event. + * + * @param server Initialize request-stats with an instance a HTTP server. + * @param statsCallback A callback which will be called for each completed HTTP request with a stats object. + */ +declare function requestStats( + server: HttpServer | HttpsServer, + statsCallback?: requestStats.StatsCallback +): requestStats.StatsEmitter; + +/** + * Attach request-stats to a single HTTP request. + * If no callback is provided, you can later attach a listener on the "complete" event. + * + * @param req An instance of a HTTP request. + * @param res An instance of a HTTP response. + * @param statsCallback A callback which will be called with a stats object when the HTTP request completes. + */ +declare function requestStats( + req: IncomingMessage, + res: ServerResponse, + statsCallback?: requestStats.StatsCallback +): requestStats.StatsEmitter; + +declare namespace requestStats { + type StatsCallback = (stats: Stats) => void; + + interface Stats { + /** + * `true` if the connection was closed correctly and `false` otherwise + */ + ok: boolean; + + /** + * The milliseconds it took to serve the request + */ + time: number; + + req: { + /** + * Number of bytes sent by the client + */ + bytes: number; + /** + * The headers sent by the client + */ + headers: IncomingHttpHeaders; + /** + * The HTTP method used by the client + */ + method: string; + /** + * The path part of the request URL + */ + path: string; + /** + * The remote ip + */ + ip: string; + /** + * The original `http.IncomingMessage` object + */ + raw: IncomingMessage; + }; + res: { + /** + * Number of bytes sent back to the client + */ + bytes: number; + /** + * The headers sent back to the client + */ + headers: OutgoingHttpHeaders; + /** + * The HTTP status code returned to the client + */ + status: number; + /** + * The original `http.ServerResponse` object + */ + raw: ServerResponse; + }; + } + + interface Request { + /** + * Returns a progress object if called while a HTTP request is in progress. + * If called multiple times, the returned progress object will contain the delta of the previous + * call to `.progress()`. + */ + progress(): Progress; + } + + interface Progress { + /** + * `false` if the request is still in progress + */ + completed: boolean; + /** + * The total time the reuqest have been in progress + */ + time: number; + /** + * The time since previous call to `.progress()` + */ + timeDelta: number; + req: { + /** + * Total bytes received + */ + bytes: number; + /** + * Bytes received since previous call to `.progress()` + */ + bytesDelta: number; + /** + * Bytes per second calculated since previous call to `.progress()` + */ + speed: number; + /** + * If the request contains a Content-Size header + */ + bytesLeft: number; + /** + * If the request contains a Content-Size header + */ + timeLeft: number; + }; + res: { + /** + * Total bytes send back to the client + */ + bytes: number; + /** + * Bytes sent back to the client since previous call to `.progress()` + */ + bytesDelta: number; + /** + * Bytes per second calculated since previous call to `.progress()` + */ + speed: number; + }; + } + + interface StatsEmitter extends EventEmitter { + addListener(event: 'complete', listener: StatsCallback): this; + addListener(event: 'request', listener: (req: Request) => void): this; + on(event: 'complete', listener: StatsCallback): this; + on(event: 'request', listener: (req: Request) => void): this; + once(event: 'complete', listener: StatsCallback): this; + once(event: 'request', listener: (req: Request) => void): this; + removeListener(event: 'complete', listener: StatsCallback): this; + removeListener(event: 'request', listener: (req: Request) => void): this; + off(event: 'complete', listener: StatsCallback): this; + off(event: 'request', listener: (req: Request) => void): this; + removeAllListeners(event?: 'complete' | 'request'): this; + listeners(event: 'complete'): StatsCallback[]; + listeners(event: 'request'): Array<(req: Request) => void>; + rawListeners(event: 'complete'): StatsCallback[]; + rawListeners(event: 'request'): Array<(req: Request) => void>; + emit(event: 'complete', stats: Stats): boolean; + emit(event: 'request', req: Request): boolean; + listenerCount(type: 'complete' | 'request'): number; + prependListener(event: 'complete', listener: StatsCallback): this; + prependListener(event: 'request', listener: (req: Request) => void): this; + prependOnceListener(event: 'complete', listener: StatsCallback): this; + prependOnceListener(event: 'request', listener: (req: Request) => void): this; + eventNames(): Array<'complete' | 'request'>; + } +} diff --git a/types/request-stats/request-stats-tests.ts b/types/request-stats/request-stats-tests.ts new file mode 100644 index 0000000000..7c73596ad1 --- /dev/null +++ b/types/request-stats/request-stats-tests.ts @@ -0,0 +1,52 @@ +import requestStats = require('request-stats'); +import * as http from 'http'; + +const server = http.createServer((req, res) => { + requestStats(req, res); // $ExpectType StatsEmitter + requestStats(req, res, stats => { + stats; // $ExpectType Stats + }); +}); + +const stats = requestStats(server); +stats; // $ExpectType StatsEmitter +// $ExpectType StatsEmitter +requestStats(server, stats => { + stats; // $ExpectType Stats + + stats.ok; // $ExpectType boolean + stats.time; // $ExpectType number + stats.req.bytes; // $ExpectType number + stats.req.headers; // $ExpectType IncomingHttpHeaders + stats.req.method; // $ExpectType string + stats.req.path; // $ExpectType string + stats.req.ip; // $ExpectType string + stats.req.raw; // $ExpectType IncomingMessage + stats.res.bytes; // $ExpectType number + stats.res.headers; // $ExpectType OutgoingHttpHeaders + stats.res.status; // $ExpectType number + stats.res.raw; // $ExpectType ServerResponse +}); + +stats.on('complete', stats => { + stats; // $ExpectType Stats +}); + +stats.on('request', req => { + req; // $ExpectType Request + + const progress = req.progress(); + progress; // $ExpectType Progress + + progress.completed; // $ExpectType boolean + progress.time; // $ExpectType number + progress.timeDelta; // $ExpectType number + progress.req.bytes; // $ExpectType number + progress.req.bytesDelta; // $ExpectType number + progress.req.speed; // $ExpectType number + progress.req.bytesLeft; // $ExpectType number + progress.req.timeLeft; // $ExpectType number + progress.res.bytes; // $ExpectType number + progress.res.bytesDelta; // $ExpectType number + progress.res.speed; // $ExpectType number +}); diff --git a/types/request-stats/tsconfig.json b/types/request-stats/tsconfig.json new file mode 100644 index 0000000000..77f283fcb4 --- /dev/null +++ b/types/request-stats/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "request-stats-tests.ts" + ] +} diff --git a/types/request-stats/tslint.json b/types/request-stats/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/request-stats/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }