Skip to content

Commit

Permalink
Merge pull request codemanki#267 from pro-src/typings
Browse files Browse the repository at this point in the history
Add typescript definitions and tests
  • Loading branch information
codemanki authored Sep 28, 2019
2 parents db4af38 + 3c72e09 commit 7f71610
Show file tree
Hide file tree
Showing 5 changed files with 299 additions and 7 deletions.
16 changes: 15 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,19 @@
"VariableDeclarator": true
}
}]
}
},
"overrides": [
{
"files": ["*.ts"],
"parser": "@typescript-eslint/parser",
"extends": [
"standard",
"plugin:promise/recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"semi": [2, "always"]
}
}
]
}
95 changes: 95 additions & 0 deletions errors.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import * as rp from 'request-promise/errors';
import cloudscraper = require('.');
import http = require('http');

export interface RequestError extends rp.RequestError {
options: cloudscraper.Options;
errorType: 0;
}

export interface RequestErrorConstructor extends Error {
new(cause: any, options: cloudscraper.Options, response: http.IncomingMessage): RequestError;

(cause: any, options: cloudscraper.Options, response: http.IncomingMessage): RequestError;

prototype: RequestError;
}

export const RequestError: RequestErrorConstructor;

export interface CaptchaError extends rp.RequestError {
options: cloudscraper.Options;
errorType: 1;
}

export interface CaptchaErrorConstructor extends Error {
new(cause: any, options: cloudscraper.Options, response: http.IncomingMessage): RequestError;

(cause: any, options: cloudscraper.Options, response: http.IncomingMessage): RequestError;

prototype: CaptchaError;
}

export const CaptchaError: CaptchaErrorConstructor;

export interface CloudflareError extends rp.RequestError {
options: cloudscraper.Options;
errorType: 2 | 4;
}

export interface CloudflareErrorConstructor extends Error {
new(cause: any, options: cloudscraper.Options, response: http.IncomingMessage): RequestError;

(cause: any, options: cloudscraper.Options, response: http.IncomingMessage): RequestError;

prototype: CloudflareError;
}

export const CloudflareError: CloudflareErrorConstructor;

export interface ParserError extends rp.RequestError {
options: cloudscraper.Options;
errorType: 3;
}

export interface ParserErrorConstructor extends Error {
new(cause: any, options: cloudscraper.Options, response: http.IncomingMessage): RequestError;

(cause: any, options: cloudscraper.Options, response: http.IncomingMessage): RequestError;

prototype: ParserError;
}

export const ParserError: ParserErrorConstructor;

export interface StatusCodeError extends rp.RequestError {
options: cloudscraper.Options;
statusCode: number;
errorType: 5;
}

export interface StatusCodeErrorConstructor extends Error {
new(statusCode: number, body: any, options: cloudscraper.Options, response: http.IncomingMessage): StatusCodeError;

(statusCode: number, body: any, options: cloudscraper.Options, response: http.IncomingMessage): StatusCodeError;

prototype: StatusCodeError;
}

export const StatusCodeError: StatusCodeErrorConstructor;

export interface TransformError extends rp.RequestError {
options: cloudscraper.Options;
errorType: 6;
}

export interface TransformErrorConstructor extends Error {
new(cause: any, options: cloudscraper.Options, response: http.IncomingMessage): TransformError;

(cause: any, options: cloudscraper.Options, response: http.IncomingMessage): TransformError;

prototype: TransformError;
}

export const TransformError: TransformErrorConstructor;
89 changes: 89 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { Url } from 'url';
import http = require('http');
import https = require('https');
import Promise = require('bluebird');
import request = require('request');
import rp = require('request-promise');
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import errors = require('./errors');

declare namespace cloudscraper {
interface Cloudscraper extends rp.RequestPromise, BaseOptions {
cloudflareTimeout?: number;
realEncoding: string | null;
// Identify this request as a Cloudscraper request
cloudscraper: boolean;
}

interface Captcha {
submit(error?: Error): void;

url: string; // <- deprecated
siteKey: string;
uri: Url;
form: {
[key: string]: string;
// Secret form value
s: string;
};
}

interface Response extends request.Response {
isCloudflare?: boolean;
isHTML?: boolean;
isCaptcha?: boolean;

// JS Challenge
challenge?: string;
}

interface CaptchaResponse extends Response {
captcha: Captcha;
isCaptcha: true;
}

type Requester =
rp.RequestPromiseAPI
| request.RequestAPI<request.Request, request.CoreOptions, request.RequiredUriUrl>;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type CaptchaHandler = (options: Options, response: CaptchaResponse, body?: any) => Promise<any> | void;

interface BaseOptions {
// The default export of either request or request-promise
requester?: Requester;
// Reduce Cloudflare's timeout to cloudflareMaxTimeout if it is excessive
cloudflareMaxTimeout?: number;
// Support only this max challenges in row. If CF returns more, throw an error
challengesToSolve?: number;
// Remove Cloudflare's email protection
decodeEmails?: boolean;

onCaptcha?: CaptchaHandler;
}

interface DefaultOptions extends Required<BaseOptions>, rp.RequestPromiseOptions {
// Override the parsed timeout
cloudflareTimeout?: number;
agentOptions?: (http.AgentOptions | https.AgentOptions) & {
ciphers?: string;
};
}

interface CoreOptions extends BaseOptions, rp.RequestPromiseOptions {
cloudflareTimeout?: number;
realEncoding?: string | null;
}

interface CloudscraperAPI extends request.RequestAPI<Cloudscraper, CoreOptions, request.RequiredUriUrl> {
defaultParams: DefaultOptions;
}

type OptionsWithUri = request.UriOptions & CoreOptions;
type OptionsWithUrl = request.UrlOptions & CoreOptions;
type Options = OptionsWithUri | OptionsWithUrl;
}

// eslint-disable-next-line no-redeclare
declare const cloudscraper: cloudscraper.CloudscraperAPI;
export = cloudscraper;
86 changes: 86 additions & 0 deletions index.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { expectType } from 'tsd';
import { URL } from 'url';
import {
Options, Cloudscraper, CaptchaHandler, CoreOptions, DefaultOptions,
CaptchaResponse, Captcha
} from './index';
import Promise = require('bluebird');
import request = require('request');
import rp = require('request-promise');
import cloudscraper = require('./index');
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import errors = require('./errors');

const noop = (): void => {};

expectType<Options>({ uri: '' });
expectType<Options>({ url: '' });

expectType<Options>({ uri: '', requester: request });
expectType<Options>({ uri: '', requester: rp });

expectType<Cloudscraper>(cloudscraper({ uri: '' }));
expectType<Cloudscraper>(cloudscraper.get({ uri: '' }));
expectType<Cloudscraper>(cloudscraper.post({ uri: '' }));
expectType<Cloudscraper>(cloudscraper.put({ uri: '' }));
expectType<Cloudscraper>(cloudscraper.delete({ uri: '' }));
expectType<Cloudscraper>(cloudscraper.del({ uri: '' }));
expectType<Cloudscraper>(cloudscraper.head({ uri: '' }));
expectType<Cloudscraper>(cloudscraper.patch({ uri: '' }));

expectType<Cloudscraper>(cloudscraper(''));
expectType<Cloudscraper>(cloudscraper.get(''));
expectType<Cloudscraper>(cloudscraper.post(''));
expectType<Cloudscraper>(cloudscraper.put(''));
expectType<Cloudscraper>(cloudscraper.delete(''));
expectType<Cloudscraper>(cloudscraper.del(''));
expectType<Cloudscraper>(cloudscraper.head(''));
expectType<Cloudscraper>(cloudscraper.patch(''));

// eslint-disable-next-line promise/always-return
expectType<Promise<any>>(cloudscraper.get({ uri: '' }).then(noop));
expectType<Promise<any>>(cloudscraper.get({ uri: '' }).catch(noop));
expectType<Promise<any>>(cloudscraper.get({ uri: '' }).finally(noop));
expectType<Promise<any>>(cloudscraper.get({ uri: '' }).promise());
expectType<void>(cloudscraper.get({ uri: '' }).cancel());

expectType<CaptchaHandler>((options: Options, response: CaptchaResponse) => {
expectType<Options>(options);
expectType<CaptchaResponse>(response);

const { captcha, isCaptcha } = response;

expectType<Captcha>(captcha);
expectType<true>(isCaptcha);

expectType<Captcha>({
url: '', // <- deprecated
uri: new URL(''),
siteKey: '',
submit: captcha.submit,
form: { s: '' }
});

captcha.submit();
});

expectType<DefaultOptions>(cloudscraper.defaultParams);
expectType<DefaultOptions>({
requester: request,
cloudflareMaxTimeout: 0,
challengesToSolve: 0,
decodeEmails: false,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
onCaptcha: (options: Options, response: CaptchaResponse) => {}
});

expectType<CoreOptions>({
requester: request,
cloudflareMaxTimeout: 0,
challengesToSolve: 0,
decodeEmails: false,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
onCaptcha: (options: Options, response: CaptchaResponse) => {},
realEncoding: 'utf-8'
});
20 changes: 14 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@
"files": [
"lib/",
"index.js",
"errors.js"
"index.d.ts",
"errors.js",
"errors.d.ts"
],
"scripts": {
"test": "npm run lint && nyc --reporter=html --reporter=text mocha",
"test": "npm run lint && npm run test:typescript && nyc --reporter=html --reporter=text mocha",
"test:typescript": "tsc *.ts --noEmit && tsd",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"lint": "eslint --ext .json --ext .js ."
"lint": "eslint --ext .json --ext .js --ext .ts ."
},
"repository": {
"type": "git",
Expand All @@ -41,6 +44,9 @@
"request-promise": "^4.2.4"
},
"devDependencies": {
"@types/request-promise": "^4.1.44",
"@typescript-eslint/eslint-plugin": "^2.3.1",
"@typescript-eslint/parser": "^2.3.1",
"chai": "^4.2.0",
"chai-as-promised": "^7.1.1",
"coveralls": "^3.0.3",
Expand All @@ -55,10 +61,12 @@
"mocha": "^6.1.1",
"nyc": "^14.0.0",
"sinon": "^7.2.4",
"sinon-chai": "^3.3.0"
"sinon-chai": "^3.3.0",
"tsd": "^0.8.0",
"typescript": "^3.6.3"
},
"peerDependencies": {
"request": "^2.88.0",
"brotli": "^1.3.2"
"brotli": "^1.3.2",
"request": "^2.88.0"
}
}

0 comments on commit 7f71610

Please sign in to comment.