From dd7f874011d3f01ebd5692d40196397743f5e89b Mon Sep 17 00:00:00 2001 From: mtraynham Date: Sun, 29 Oct 2017 23:54:10 -0400 Subject: [PATCH] Add type definitions for x-ray (x-ray-crawler & http-context) --- types/http-context/http-context-tests.ts | 73 ++++++++++++++ types/http-context/index.d.ts | 101 +++++++++++++++++++ types/http-context/tsconfig.json | 23 +++++ types/http-context/tslint.json | 1 + types/x-ray-crawler/index.d.ts | 38 +++++++ types/x-ray-crawler/tsconfig.json | 23 +++++ types/x-ray-crawler/tslint.json | 1 + types/x-ray-crawler/x-ray-crawler-tests.ts | 52 ++++++++++ types/x-ray/index.d.ts | 62 ++++++++++++ types/x-ray/tsconfig.json | 23 +++++ types/x-ray/tslint.json | 1 + types/x-ray/x-ray-tests.ts | 112 +++++++++++++++++++++ 12 files changed, 510 insertions(+) create mode 100644 types/http-context/http-context-tests.ts create mode 100644 types/http-context/index.d.ts create mode 100644 types/http-context/tsconfig.json create mode 100644 types/http-context/tslint.json create mode 100644 types/x-ray-crawler/index.d.ts create mode 100644 types/x-ray-crawler/tsconfig.json create mode 100644 types/x-ray-crawler/tslint.json create mode 100644 types/x-ray-crawler/x-ray-crawler-tests.ts create mode 100644 types/x-ray/index.d.ts create mode 100644 types/x-ray/tsconfig.json create mode 100644 types/x-ray/tslint.json create mode 100644 types/x-ray/x-ray-tests.ts diff --git a/types/http-context/http-context-tests.ts b/types/http-context/http-context-tests.ts new file mode 100644 index 0000000000..1542f50e1e --- /dev/null +++ b/types/http-context/http-context-tests.ts @@ -0,0 +1,73 @@ +import http = require('http'); +import httpContext = require('http-context'); + +const context: httpContext.Context = httpContext(); +const request: httpContext.Request = context.request; +const response: httpContext.Response = context.response; + +let header: http.IncomingHttpHeaders = context.header; +header = context.headers; +header = request.header; +header = request.headers; +const headerString: string | string[] = header['Content-Type']; + +let url: string = context.url; +url = request.url; +context.accepts('html'); + +let href: string = context.href; +href = request.href; + +let method: string = context.method; +method = request.method; + +let path: string = context.path; +path = request.path; + +let query: {[param: string]: string | string[]} = context.query; +query = request.query; +const querySearch: string | string[] = query['search']; + +let queryString: string = context.querystring; +queryString = request.querystring; + +let search: string = context.search; +search = request.search; + +let host: string = context.host; +host = request.host; + +let hostname: string = context.hostname; +hostname = request.hostname; + +let fresh: boolean = context.fresh; +fresh = request.fresh; + +let idempotent: boolean = context.idempotent; +idempotent = request.idempotent; + +let protocol: string = context.protocol; +protocol = request.protocol; + +let secure: boolean = context.secure; +secure = request.secure; + +let subdomains: string[] = context.subdomains; +subdomains = request.subdomains; + +let accepts: string[] | string | false = context.accepts('text/html'); +accepts = request.accepts('text/html'); +accepts = request.accepts('text/html', 'text/txt'); +accepts = request.accepts(['text/html', 'text/txt']); + +let status: number = context.status; +status = response.status; + +let message: string = context.message; +message = response.message; + +let body: any = context.body; +body = response.body; + +let length: number = context.length; +length = response.length; diff --git a/types/http-context/index.d.ts b/types/http-context/index.d.ts new file mode 100644 index 0000000000..30aae4c99b --- /dev/null +++ b/types/http-context/index.d.ts @@ -0,0 +1,101 @@ +// Type definitions for http-context 1.1 +// Project: https://github.com/lapwinglabs/http-context#readme +// Definitions by: Matt Traynham +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// + +import accepts = require('accepts'); +import http = require('http'); + +export = HttpContext; + +declare function HttpContext(): HttpContext.Context; + +declare namespace HttpContext { + interface RequestJSON { + method: string; + url: string; + header: http.IncomingHttpHeaders; + } + + interface RequestDelegate { + header: http.IncomingHttpHeaders; + headers: http.IncomingHttpHeaders; + url: string; + href: string; + method: string; + path: string; + query: {[param: string]: string | string[]}; + querystring: string; + search: string; + host: string; + hostname: string; + fresh: boolean; + idempotent: boolean; + protocol: string; + secure: boolean; + subdomains: string[]; + accepts(types: string[]): string[] | string | false; + accepts(...types: string[]): string[] | string | false; + acceptsCharsets(charsets: string[]): string | false; + acceptsCharsets(...charsets: string[]): string | false; + acceptsEncodings(encodings: string[]): string | false; + acceptsEncodings(...encodings: string[]): string | false; + acceptsLanguages(languages: string[]): string | false; + acceptsLanguages(...languages: string[]): string | false; + is(types: string[]): string | false; + is(...types: string[]): string | false; + get(field: string): string; + } + + interface Request extends RequestDelegate { + request: http.IncomingMessage; + charset: string; + length: number; + type: string; + accept: accepts.Accepts; + inspect(): RequestJSON; + toJSON(): RequestJSON; + } + + interface ResponseJSON { + status: number; + message: string; + header: http.OutgoingHttpHeaders; + } + + interface ResponseDelegate { + status: number; + message: string; + body: any; + length: number; + headerSent: boolean; + type: string; + lastModified: string | Date; + etag: string; + writable: boolean; + vary(field: string): void; + redirect(url: string, alt: string): void; + attachment(filename: string): void; + set(field: string, val: string): void; + append(field: string, val: string[]): void; + append(field: string, ...val: string[]): void; + remove(field: string): void; + } + + interface Response extends ResponseDelegate { + response: http.OutgoingMessage; + header: http.OutgoingHttpHeaders; + is(types: string[]): string | false; + is(...types: string[]): string | false; + get(field: string): string; + inspect(): ResponseJSON; + toJSON(): ResponseJSON; + } + + interface Context extends RequestDelegate, ResponseDelegate { + request: Request; + response: Response; + } +} diff --git a/types/http-context/tsconfig.json b/types/http-context/tsconfig.json new file mode 100644 index 0000000000..51422e3199 --- /dev/null +++ b/types/http-context/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", + "http-context-tests.ts" + ] +} diff --git a/types/http-context/tslint.json b/types/http-context/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/http-context/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } diff --git a/types/x-ray-crawler/index.d.ts b/types/x-ray-crawler/index.d.ts new file mode 100644 index 0000000000..7696ecf903 --- /dev/null +++ b/types/x-ray-crawler/index.d.ts @@ -0,0 +1,38 @@ +// Type definitions for x-ray-crawler 2.0 +// Project: https://github.com/lapwinglabs/x-ray-crawler#readme +// Definitions by: Matt Traynham +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +import HttpContext = require('http-context'); + +export = XRayCrawler; + +declare function XRayCrawler(driver?: XRayCrawler.Driver): XRayCrawler.Instance; + +declare namespace XRayCrawler { + type Callback = (err: Error, obj: T) => void; + type Driver = (context: HttpContext.Context, callback: Callback) => void; + type RequestHook = (request: HttpContext.Request) => void; + type ResponseHook = (response: HttpContext.Response) => void; + type RandomDelay = () => number; + + interface Instance { + (url: string, callback: Callback): void; + driver(): Driver; + driver(driver: Driver): this; + throttle(): number; + throttle(requests: string | number, rate: string | number): this; + delay(): RandomDelay; + delay(from: string | number, to?: string | number): this; + timeout(): number; + timeout(n: string | number): this; + concurrency(): number; + concurrency(n: number): this; + request(): RequestHook; + request(fn: RequestHook): this; + response(): ResponseHook; + response(fn: ResponseHook): this; + limit(): number; + limit(n: number): this; + } +} diff --git a/types/x-ray-crawler/tsconfig.json b/types/x-ray-crawler/tsconfig.json new file mode 100644 index 0000000000..3b3a573f0a --- /dev/null +++ b/types/x-ray-crawler/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", + "x-ray-crawler-tests.ts" + ] +} diff --git a/types/x-ray-crawler/tslint.json b/types/x-ray-crawler/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/x-ray-crawler/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } diff --git a/types/x-ray-crawler/x-ray-crawler-tests.ts b/types/x-ray-crawler/x-ray-crawler-tests.ts new file mode 100644 index 0000000000..697ddd5dbb --- /dev/null +++ b/types/x-ray-crawler/x-ray-crawler-tests.ts @@ -0,0 +1,52 @@ +import HttpContext = require('http-context'); +import XRayCrawler = require('x-ray-crawler'); + +const xRayCrawler: XRayCrawler.Instance = XRayCrawler(); + +const driver: XRayCrawler.Driver = xRayCrawler.driver(); +xRayCrawler.driver(driver); + +const throttle: number = xRayCrawler.throttle(); +xRayCrawler.throttle(5, 4); +xRayCrawler.throttle(5, '4ms'); + +const randomDelay: XRayCrawler.RandomDelay = xRayCrawler.delay(); +const delay: number = randomDelay(); +xRayCrawler.delay(0, 2); +xRayCrawler.delay(0); +xRayCrawler.delay('0s', '5s'); + +const timeout: number = xRayCrawler.timeout(); +xRayCrawler.timeout(timeout); +xRayCrawler.timeout('5s'); + +const concurrency: number = xRayCrawler.concurrency(); +xRayCrawler.concurrency(5); + +const requestHook: XRayCrawler.RequestHook = xRayCrawler.request(); +xRayCrawler.request(requestHook); +xRayCrawler.request((request: HttpContext.Request) => { + console.log(request); +}); + +const responseHook: XRayCrawler.ResponseHook = xRayCrawler.response(); +xRayCrawler.response(responseHook); +xRayCrawler.response((response: HttpContext.Response) => { + console.log(response); +}); + +const limit: number = xRayCrawler.limit(); +xRayCrawler.limit(limit); + +const xRayCrawler2: XRayCrawler.Instance = XRayCrawler() + .throttle(5, '10s') + .delay('5s', '10s') + .timeout('20s') + .concurrency(4) + .request((request: HttpContext.Request) => { + console.log(request); + }) + .response((response: HttpContext.Response) => { + console.log(response); + }) + .limit(10); diff --git a/types/x-ray/index.d.ts b/types/x-ray/index.d.ts new file mode 100644 index 0000000000..782fa8bdaf --- /dev/null +++ b/types/x-ray/index.d.ts @@ -0,0 +1,62 @@ +// Type definitions for x-ray 2.3 +// Project: https://github.com/lapwinglabs/x-ray#readme +// Definitions by: Matt Traynham +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// + +import Bluebird = require('bluebird'); +import XRayCrawler = require('x-ray-crawler'); + +export = XRay; + +declare function XRay(options?: XRay.Options): XRay.Instance; + +declare namespace XRay { + type Filter = (value: any, ...args: string[]) => any; + interface Options { + filters: {[key: string]: Filter}; + } + type Callback = (err: Error, data: any) => void; + + // circularly references itself + // https://stackoverflow.com/a/41826582 + type ScalarSelector = + string | + InstanceInvocation | + {[key: string]: Selector}; + interface SelectorArray extends Array { + [index: number]: ScalarSelector | SelectorArray; + } + type Selector = ScalarSelector | SelectorArray; + + interface Instance extends XRayCrawler.Instance { + ( + source: string, + selector: Selector + ): InstanceInvocation; + ( + source: string, + context: string, + selector: Selector + ): InstanceInvocation; + ( + context: string, + selector: Selector + ): InstanceInvocation; + ( + selector: Selector + ): InstanceInvocation; + } + + interface InstanceInvocation { + (callback: Callback): void; + (source: string, callback: Callback): void; + abort(): this; + paginate(selector: Selector): this; + limit(n: number): this; + stream(): NodeJS.ReadStream; + then(fn?: (value: any) => U | PromiseLike): Bluebird; + write(path?: string): (err: NodeJS.ErrnoException) => void; + } +} diff --git a/types/x-ray/tsconfig.json b/types/x-ray/tsconfig.json new file mode 100644 index 0000000000..7dc474842a --- /dev/null +++ b/types/x-ray/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", + "x-ray-tests.ts" + ] +} diff --git a/types/x-ray/tslint.json b/types/x-ray/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/x-ray/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } diff --git a/types/x-ray/x-ray-tests.ts b/types/x-ray/x-ray-tests.ts new file mode 100644 index 0000000000..8bc056b2f6 --- /dev/null +++ b/types/x-ray/x-ray-tests.ts @@ -0,0 +1,112 @@ +import express = require('express'); +import XRay = require('x-ray'); + +const x: XRay.Instance = XRay(); + +// README Examples +x('https://blog.ycombinator.com/', '.post', [{ + title: 'h1 a', + link: '.article-title@href' + }]) + .paginate('.nav-previous a@href') + .limit(3) + .write('results.json'); + +x('http://google.com', 'title')((err: Error, title: string) => { + console.log(title); // Google +}); + +const fn: XRay.Callback = (err: Error, data: any) => { + console.log(data); +}; +x('http://reddit.com', '.content')(fn); +x('http://techcrunch.com', 'img.logo@src')(fn); +x('http://news.ycombinator.com', 'body@html')(fn); + +const html = '

Pear

'; +x(html, 'body', 'h2')((err: Error, header: string) => { + console.log(header); // => Pear +}); + +const app = express(); +app.get('/', (req: express.Request, res: express.Response) => { + const stream = x('http://google.com', 'title').stream(); + stream.pipe(res); +}); + +x('https://dribbble.com', 'li.group', [{ + title: '.dribbble-img strong', + image: '.dribbble-img [data-src]@data-src', + }]) + .paginate('.next_page@href') + .limit(3) + .then((res: Array<{title: string, image: string}>) => { + console.log(res[0]); // prints first result + }) + .catch((err: Error) => { + console.log(err); // handle error in promise + }); + +x('http://google.com', { + main: 'title', + image: x('#gbar a@href', 'title'), // follow link to google images +})(fn); + +x('http://mat.io', { + title: 'title', + items: x('.item', [{ + title: '.item-content h2', + description: '.item-content section' + }]) +})(fn); + +const x2 = XRay({ + filters: { + trim: (value: string): string => { + return typeof value === 'string' ? value.trim() : value; + }, + reverse: (value: string): string => { + return typeof value === 'string' ? value.split('').reverse().join('') : value; + }, + slice: (value: string, start: string, end: string): string => { + return typeof value === 'string' ? value.slice(+start, +end) : value; + } + } +}); +x2('http://mat.io', { + title: 'title | trim | reverse | slice:2,3' +})(fn); + +// Examples +x(html, 'h2')(console.log); + +x(html, { + title: '.title', + image: 'img@src', + tags: ['li'] +})(console.log); + +x(html, ['a'])(console.log); + +x(html, '.item', [{ + title: 'h2', + tags: x('.tags', ['li']) +}])(console.log); + +x(html, '.tags', [['li']])(console.log); + +// Tests +x({ + title: 'title@text', + image: x('#gbar a@href', 'title'), + scoped_title: x('head', 'title'), + inner: x('title', { + title: '@text' + }) +})('http://www.google.com/ncr', fn); + +x({ + list: x('body', { + first: x('a@href', 'title') + }) +})(fn);