Add type definitions for x-ray (x-ray-crawler & http-context)

This commit is contained in:
mtraynham
2017-10-29 23:54:10 -04:00
parent a11a781688
commit dd7f874011
12 changed files with 510 additions and 0 deletions

View File

@@ -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;

101
types/http-context/index.d.ts vendored Normal file
View File

@@ -0,0 +1,101 @@
// Type definitions for http-context 1.1
// Project: https://github.com/lapwinglabs/http-context#readme
// Definitions by: Matt Traynham <https://github.com/mtraynham>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
/// <reference types="node" />
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;
}
}

View File

@@ -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"
]
}

View File

@@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }

38
types/x-ray-crawler/index.d.ts vendored Normal file
View File

@@ -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 <https://github.com/mtraynham>
// 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<T> = (err: Error, obj: T) => void;
type Driver = (context: HttpContext.Context, callback: Callback<HttpContext.Context>) => void;
type RequestHook = (request: HttpContext.Request) => void;
type ResponseHook = (response: HttpContext.Response) => void;
type RandomDelay = () => number;
interface Instance {
(url: string, callback: Callback<HttpContext.Context>): 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;
}
}

View File

@@ -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"
]
}

View File

@@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }

View File

@@ -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);

62
types/x-ray/index.d.ts vendored Normal file
View File

@@ -0,0 +1,62 @@
// Type definitions for x-ray 2.3
// Project: https://github.com/lapwinglabs/x-ray#readme
// Definitions by: Matt Traynham <https://github.com/mtraynham>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
/// <reference types="node" />
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<ScalarSelector | SelectorArray> {
[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<U>(fn?: (value: any) => U | PromiseLike<U>): Bluebird<U>;
write(path?: string): (err: NodeJS.ErrnoException) => void;
}
}

23
types/x-ray/tsconfig.json Normal file
View File

@@ -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"
]
}

1
types/x-ray/tslint.json Normal file
View File

@@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }

112
types/x-ray/x-ray-tests.ts Normal file
View File

@@ -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 = '<body><h2>Pear</h2></body>';
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);