Add types for centra and phin (#33887)

This commit is contained in:
Tony Wooster
2019-03-14 12:35:18 -07:00
committed by Wesley Wigham
parent 1c11579652
commit beddc9f5a9
8 changed files with 449 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
import centra = require('centra');
import { URL } from 'url';
function typeTests() {
// Test chaining
centra('http://google.com')
.query('param', 'value')
.path('mail')
.body({ a: 1, b: 2 })
.header({ a: 'b' })
.header('a', 'b')
.timeout(123)
.stream()
.compress()
.option('host', '123')
.option('port', 123)
.send().then(resp => {
resp.json().then((s: string) => s);
resp.text().then((s: string) => s);
resp.statusCode;
resp.coreRes;
resp.headers['asdf'];
resp.body.buffer.byteLength;
});
centra(new URL('google.com'))
.query('page', '2');
}
async function functionalTests() {
await centra('http://example.com').send().then(async r => {
if (r.statusCode !== 200) {
throw new Error('Bad status code');
}
r.text().then(t => t);
});
await centra(new URL('https://jsonplaceholder.typicode.com/todos'))
.query('userId', 1)
.timeout(1000)
.compress()
.send()
.then(r => {
r.json().then((todos: any[]) => {
if (!todos.every(t => t.userId === 1)) {
throw new Error('Query params did not work');
}
});
});
}
functionalTests();
+54
View File
@@ -0,0 +1,54 @@
// Type definitions for centra 2.2
// Project: https://github.com/ethanent/centra
// Definitions by: Tony Wooster <https://github.com/twooster>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.1
/// <reference types="node" />
import { RequestOptions, IncomingMessage } from 'http';
import { URL } from 'url';
interface CentraFactory {
(url: URL | string, method?: string): Centra.Request;
}
declare const Centra: CentraFactory;
declare namespace Centra {
interface Response {
coreRes: IncomingMessage;
headers: IncomingMessage['headers'];
statusCode: IncomingMessage['statusCode'];
body: Buffer;
json(): Promise<any>;
text(): Promise<string>;
}
interface Request {
url: URL;
method: string;
data: string | Buffer | null;
sendDataAs: 'form' | 'json' | 'buffer' | null;
reqHeaders: { [k: string]: string };
streamEnabled: boolean;
compressionEnabled: boolean;
timeoutTime: number | null;
coreOptions: RequestOptions;
query(key: string, value: any): this;
query(params: { [k: string]: any }): this;
path(relativePath: string): this;
body(data: any, sendAs?: 'json' | 'buffer' | 'form'): this;
header(key: string, value: string): this;
header(headers: { [k: string]: string }): this;
timeout(timeMs: number): this;
option<T extends keyof RequestOptions>(key: T, value: RequestOptions[T]): this;
stream(): this;
compress(): this;
send(): Promise<Response>;
}
}
export = Centra;
+23
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",
"centra-tests.ts"
]
}
+1
View File
@@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }
+123
View File
@@ -0,0 +1,123 @@
// Type definitions for phin 3.3
// Project: https://github.com/ethanent/phin
// Definitions by: Tony Wooster <https://github.com/twooster>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 3.0
/// <reference types="node" />
import { ClientRequestArgs, IncomingMessage } from 'http';
import { URL } from 'url';
import { Response as CentraResponse } from 'centra';
type Options = Phin.Options;
type BufferResponse = Phin.BufferResponse;
type StreamResponse = Phin.StreamResponse;
type JsonResponse = Phin.JsonResponse;
type DefaultOpts = Phin.DefaultOpts;
type BatchResponse = JsonResponse | BufferResponse;
type AnyResponse = BatchResponse | StreamResponse;
interface PhinFactory {
(optsOrUrl: (Options & { parse?: 'none', stream?: false }) | string): Promise<BufferResponse>;
(optsOrUrl: Options & { parse: 'json', stream?: false }): Promise<JsonResponse>;
(optsOrUrl: Options & { stream: true }): Promise<StreamResponse>;
(optsOrUrl: Options): Promise<AnyResponse>;
promisified(optsOrUrl: (Options & { parse?: 'none', stream?: false }) | string): Promise<BufferResponse>;
promisified(optsOrUrl: Options & { parse: 'json', stream?: false }): Promise<JsonResponse>;
promisified(optsOrUrl: Options & { stream: true }): Promise<StreamResponse>;
promisified(optsOrUrl: Options): Promise<AnyResponse>;
unpromisified(optsOrUrl: (Options & { parse?: 'none', stream?: false }) | string, cb: (err: unknown, resp: BufferResponse) => unknown): void;
unpromisified(optsOrUrl: Options & { parse: 'json', stream?: false }, cb: (err: unknown, resp: JsonResponse) => unknown): void;
unpromisified(optsOrUrl: Options & { stream: true }, cb: (err: unknown, resp: StreamResponse) => unknown): void;
unpromisified(optsOrUrl: Options, cb: (err: unknown, resp: AnyResponse) => unknown): void;
defaults(defaultOpts: DefaultOpts & { parse: 'json', stream?: false }):
{
(optsOrUrl: Options & { stream: true }): Promise<StreamResponse>
(optsOrUrl: Options & { parse: 'none', stream?: false }): Promise<BufferResponse>
(optsOrUrl: (Options & { parse?: 'json', stream?: false }) | string): Promise<JsonResponse>
(optsOrUrl: Options): Promise<AnyResponse>
};
defaults(defaultOpts: DefaultOpts & { parse?: 'none', stream?: false }):
{
(optsOrUrl: Options & { stream: true }): Promise<StreamResponse>
(optsOrUrl: Options & { parse: 'json', stream?: false }): Promise<JsonResponse>
(optsOrUrl: (Options & { parse?: 'none', stream?: false }) | string): Promise<BufferResponse>
(optsOrUrl: Options): Promise<AnyResponse>
};
defaults(defaultOpts: DefaultOpts & { parse: 'json', stream: true }):
{
(optsOrUrl: Options & { parse: 'none', stream: false }): Promise<BufferResponse>
(optsOrUrl: Options & { parse?: 'json', stream: false }): Promise<JsonResponse>
(optsOrUrl: (Options & { stream?: true }) | string): Promise<StreamResponse>
(optsOrUrl: Options | string): Promise<AnyResponse>
};
defaults(defaultOpts: DefaultOpts & { parse?: 'none', stream: true }):
{
(opts: Options & { parse: 'json', stream: false }): Promise<JsonResponse>
(opts: Options & { parse?: 'none', stream: false }): Promise<BufferResponse>
(opts: (Options & { stream?: true }) | string): Promise<StreamResponse>
(opts: Options): Promise<AnyResponse>
};
defaults(defaultOpts: DefaultOpts):
{
(optsOrUrl: Options & { stream: true }): Promise<StreamResponse>
(optsOrUrl: Options & { parse: 'json', stream: false }): Promise<JsonResponse>
(optsOrUrl: Options & { parse: 'none', stream: false }): Promise<BufferResponse>
(optsOrUrl: Options | string): Promise<AnyResponse>
};
}
declare const Phin: PhinFactory;
declare namespace Phin {
interface DefaultOpts {
url?: string;
method?: string;
data?: any;
form?: { [k: string]: string };
headers?: { [k: string]: string };
core?: ClientRequestArgs;
parse?: 'none' | 'json';
followRedirects?: boolean;
compression?: boolean;
timeout?: number | null;
hostname?: string;
port?: number;
path?: string;
stream?: boolean;
}
interface Options extends DefaultOpts {
url: string;
}
interface BatchOptions extends Options {
stream: false;
}
interface StreamOptions extends Options {
stream: true;
}
interface StreamResponse extends IncomingMessage {
stream: StreamResponse;
}
interface BufferResponse extends IncomingMessage {
body: Buffer;
}
interface JsonResponse extends IncomingMessage {
body: any;
}
}
export = Phin;
+172
View File
@@ -0,0 +1,172 @@
import phin = require('phin');
export function typeTests() {
function testParseNoneStreamFalse(o: { url: string, parse?: 'none', stream?: false } | string) {
phin(o); // $ExpectType Promise<BufferResponse>
}
function testParseJsonStreamFalse(o: { url: string, parse: 'json', stream?: false }) {
phin(o); // $ExpectType Promise<JsonResponse>
}
function testStreamTrue(o: { url: string, parse?: 'json' | 'none', stream: true }) {
phin(o); // $ExpectType Promise<StreamResponse>
}
function testCallbackParseNoneStreamFalse(o: { url: string, parse?: 'none', stream?: false } | string) {
phin.unpromisified(o, (_err, r) => {
r; // $ExpectType BufferResponse
});
}
function testCallbackParseJsonStreamFalse(o: { url: string, parse: 'json', stream?: false }) {
phin.unpromisified(o, (_err, r) => {
r; // $ExpectType JsonResponse
});
}
function testCallbackStreamTrue(o: { url: string, parse?: 'json' | 'none', stream: true }) {
phin.unpromisified(o, (_err, r) => {
r; // $ExpectType StreamResponse
});
}
function testCallbackAny(o: { url: string, parse?: 'json' | 'none', stream?: boolean }) {
phin.unpromisified(o, (_err, r) => {
r; // $ExpectType AnyResponse
});
}
function testDefaultsParseNoneStreamFalse(d: { parse?: 'none', stream?: false }) {
const p = phin.defaults(d);
return {
testSame(o: phin.Options & { parse?: 'none', stream?: false } | string) {
p(o); // $ExpectType Promise<BufferResponse>
},
testJson(o: phin.Options & { parse: 'json', stream?: false }) {
p(o); // $ExpectType Promise<JsonResponse>
},
testStream(o: phin.Options & { stream: true }) {
p(o); // $ExpectType Promise<StreamResponse>
},
testOthers(o: phin.Options) {
p(o); // $ExpectType Promise<AnyResponse>
}
};
}
function testDefaultsParseJsonStreamFalse(d: { parse: 'json', stream?: false }) {
const p = phin.defaults(d);
return {
testSame(o: phin.Options & { parse: 'none', stream?: false }) {
p(o); // $ExpectType Promise<BufferResponse>
},
testJson(o: phin.Options & { parse?: 'json', stream?: false } | string) {
p(o); // $ExpectType Promise<JsonResponse>
},
testStream(o: phin.Options & { stream: true }) {
p(o); // $ExpectType Promise<StreamResponse>
},
testOthers(o: phin.Options) {
p(o); // $ExpectType Promise<AnyResponse>
}
};
}
function testDefaultsParseJsonStreamTrue(d: { parse: 'json', stream: true }) {
const p = phin.defaults(d);
return {
testSame(o: phin.Options & { parse: 'none', stream: false }) {
p(o); // $ExpectType Promise<BufferResponse>
},
testJson(o: phin.Options & { parse?: 'json', stream: false }) {
p(o); // $ExpectType Promise<JsonResponse>
},
testStream(o: phin.Options & { stream?: true } | string) {
p(o); // $ExpectType Promise<StreamResponse>
},
testOthers(o: phin.Options) {
p(o); // $ExpectType Promise<AnyResponse>
}
};
}
function testDefaultsParseNoneStreamTrue(d: { parse?: 'none', stream: true }) {
const p = phin.defaults(d);
return {
testSame(o: phin.Options & { parse?: 'none', stream: false }) {
p(o); // $ExpectType Promise<BufferResponse>
},
testJson(o: phin.Options & { parse: 'json', stream: false }) {
p(o); // $ExpectType Promise<JsonResponse>
},
testStream(o: phin.Options & { stream?: true } | string) {
p(o); // $ExpectType Promise<StreamResponse>
},
testOthers(o: phin.Options) {
p(o); // $ExpectType Promise<AnyResponse>
}
};
}
function testDefaultsAny(d: { parse?: 'none' | 'json', stream?: boolean }) {
const p = phin.defaults(d);
return {
testSame(o: phin.Options & { parse: 'none', stream: false }) {
p(o); // $ExpectType Promise<BufferResponse>
},
testJson(o: phin.Options & { parse: 'json', stream: false }) {
p(o); // $ExpectType Promise<JsonResponse>
},
testStream(o: phin.Options & { stream: true }) {
p(o); // $ExpectType Promise<StreamResponse>
},
testOthers(o: phin.Options | string) {
p(o); // $ExpectType Promise<AnyResponse>
}
};
}
}
async function functionalTests() {
await phin('http://example.com').then(r => {
if (!Buffer.isBuffer(r.body)) { throw new Error('Not a buffer?'); }
});
await phin('http://placekitten.com/50/50').then(r => {
if (r.headers['content-type'] !== 'image/jpeg') {
throw new Error('expected a jpeg');
}
});
await phin({ url: 'https://jsonplaceholder.typicode.com/todos/1', parse: 'json' }).then(r => {
if (typeof r.body === 'string') {
throw new Error('Did not parse json');
}
if (typeof r.body.userId !== 'number') {
throw new Error('Did not get userId');
}
});
await phin({ url: 'https://jsonplaceholder.typicode.com/todos/1', stream: true }).then(r => {
r.on('end', () => {});
});
}
functionalTests();
+23
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",
"phin-tests.ts"
]
}
+1
View File
@@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }