Skip to content

Commit

Permalink
Improve types (#946)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
Co-authored-by: Szymon Marczak <36894700+szmarczak@users.noreply.github.com>
  • Loading branch information
3 people committed Dec 1, 2019
1 parent f008bc9 commit 71b8452
Show file tree
Hide file tree
Showing 33 changed files with 373 additions and 220 deletions.
4 changes: 0 additions & 4 deletions package.json
Expand Up @@ -118,10 +118,6 @@
"extensions": [
"ts"
],
"rules": {
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/promise-function-async": "off"
},
"ignores": [
"documentation/examples/*"
]
Expand Down
2 changes: 1 addition & 1 deletion readme.md
Expand Up @@ -1312,7 +1312,7 @@ test('retry function gets iteration count', withServer, async (t, server, got) =
retry: {
calculateDelay: ({attemptCount}) => {
t.true(is.number(attemptCount));
return attemptCount < 2;
return attemptCount < 2 ? 1 : 0;
}
}
});
Expand Down
11 changes: 5 additions & 6 deletions source/as-promise.ts
Expand Up @@ -7,7 +7,7 @@ import {normalizeArguments, mergeOptions} from './normalize-arguments';
import requestAsEventEmitter, {proxyEvents} from './request-as-event-emitter';
import {CancelableRequest, GeneralError, NormalizedOptions, Response} from './utils/types';

const parseBody = (body: Response['body'], responseType: NormalizedOptions['responseType'], statusCode: Response['statusCode']) => {
const parseBody = (body: Response['body'], responseType: NormalizedOptions['responseType'], statusCode: Response['statusCode']): unknown => {
if (responseType === 'json' && is.string(body)) {
return statusCode === 204 ? '' : JSON.parse(body);
}
Expand All @@ -24,7 +24,7 @@ const parseBody = (body: Response['body'], responseType: NormalizedOptions['resp
return body;
}

throw new Error(`Failed to parse body of type '${typeof body}' as '${responseType}'`);
throw new Error(`Failed to parse body of type '${typeof body}' as '${responseType!}'`);
};

export default function asPromise<T>(options: NormalizedOptions): CancelableRequest<T> {
Expand Down Expand Up @@ -66,7 +66,7 @@ export default function asPromise<T>(options: NormalizedOptions): CancelableRequ

try {
for (const [index, hook] of options.hooks.afterResponse.entries()) {
// @ts-ignore
// @ts-ignore Promise is not assignable to CancelableRequest
// eslint-disable-next-line no-await-in-loop
response = await hook(response, async (updatedOptions: NormalizedOptions) => {
updatedOptions = normalizeArguments(mergeOptions(options, {
Expand Down Expand Up @@ -141,7 +141,7 @@ export default function asPromise<T>(options: NormalizedOptions): CancelableRequ
emitter.once('error', reject);

proxyEvents(proxy, emitter);
}) as CancelableRequest<any>;
}) as CancelableRequest<T>;

promise.on = (name: string, fn: (...args: any[]) => void) => {
proxy.on(name, fn);
Expand All @@ -154,8 +154,7 @@ export default function asPromise<T>(options: NormalizedOptions): CancelableRequ

Object.defineProperties(newPromise, Object.getOwnPropertyDescriptors(promise));

// @ts-ignore The missing properties are added above
return newPromise;
return newPromise as CancelableRequest<T>;
};

promise.json = () => {
Expand Down
10 changes: 5 additions & 5 deletions source/as-stream.ts
@@ -1,6 +1,6 @@
import duplexer3 = require('duplexer3');
import stream = require('stream');
import {IncomingMessage} from 'http';
import {IncomingMessage, ServerResponse} from 'http';
import {Duplex as DuplexStream, PassThrough as PassThroughStream} from 'stream';
import {HTTPError, ReadError} from './errors';
import requestAsEventEmitter, {proxyEvents} from './request-as-event-emitter';
Expand All @@ -14,7 +14,7 @@ export default function asStream<T>(options: NormalizedOptions): ProxyStream<T>
const input = new PassThroughStream();
const output = new PassThroughStream();
const proxy = duplexer3(input, output) as ProxyStream;
const piped = new Set<any>(); // TODO: Should be `new Set<stream.Writable>();`.
const piped = new Set<ServerResponse>();
let isFinished = false;

options.retry.calculateDelay = () => 0;
Expand Down Expand Up @@ -91,7 +91,7 @@ export default function asStream<T>(options: NormalizedOptions): ProxyStream<T>
// It's not possible to decompress already decompressed data, is it?
const isAllowed = options.decompress ? key !== 'content-encoding' : true;
if (isAllowed) {
destination.setHeader(key, value);
destination.setHeader(key, value!);
}
}

Expand All @@ -114,15 +114,15 @@ export default function asStream<T>(options: NormalizedOptions): ProxyStream<T>

pipe(destination, options);

if (Reflect.has(destination, 'setHeader')) {
if (destination instanceof ServerResponse) {
piped.add(destination);
}

return destination;
};

proxy.unpipe = stream => {
piped.delete(stream);
piped.delete(stream as ServerResponse);
return unpipe(stream);
};

Expand Down
4 changes: 2 additions & 2 deletions source/calculate-retry-delay.ts
Expand Up @@ -15,7 +15,7 @@ const calculateRetryDelay: RetryFunction = ({attemptCount, retryOptions, error})

const hasMethod = retryOptions.methods.includes(error.options.method);
const hasErrorCode = Reflect.has(error, 'code') && retryOptions.errorCodes.includes(error.code);
const hasStatusCode = isErrorWithResponse(error) && Reflect.has(error, 'response') && retryOptions.statusCodes.includes(error.response?.statusCode);
const hasStatusCode = isErrorWithResponse(error) && retryOptions.statusCodes.includes(error.response.statusCode);
if (!hasMethod || (!hasErrorCode && !hasStatusCode)) {
return 0;
}
Expand All @@ -37,7 +37,7 @@ const calculateRetryDelay: RetryFunction = ({attemptCount, retryOptions, error})
return after;
}

if (response?.statusCode === 413) {
if (response.statusCode === 413) {
return 0;
}
}
Expand Down
28 changes: 16 additions & 12 deletions source/create.ts
Expand Up @@ -6,9 +6,10 @@ import {normalizeArguments, mergeOptions} from './normalize-arguments';
import deepFreeze from './utils/deep-freeze';
import {
CancelableRequest,
Defaults,
DefaultOptions,
ExtendOptions,
HandlerFunction,
NormalizedDefaults,
NormalizedOptions,
Options,
Response,
Expand All @@ -28,7 +29,7 @@ export type GotReturn<T = unknown> = CancelableRequest<T> | ProxyStream<T>;

const getPromiseOrStream = (options: NormalizedOptions): GotReturn => options.isStream ? asStream(options) : asPromise(options);

const isGotInstance = (value: any): value is Got => (
const isGotInstance = (value: Got | ExtendOptions): value is Got => (
Reflect.has(value, 'defaults') && Reflect.has(value.defaults, 'options')
);

Expand All @@ -55,7 +56,7 @@ interface GotFunctions {

export interface Got extends Record<HTTPAlias, GotFunctions>, GotFunctions {
stream: GotStream;
defaults: NormalizedDefaults | Readonly<NormalizedDefaults>;
defaults: Defaults | Readonly<Defaults>;
GotError: typeof errors.GotError;
CacheError: typeof errors.CacheError;
RequestError: typeof errors.RequestError;
Expand Down Expand Up @@ -87,12 +88,13 @@ const aliases: readonly HTTPAlias[] = [

export const defaultHandler: HandlerFunction = (options, next) => next(options);

const create = (defaults: NormalizedDefaults & {_rawHandlers?: HandlerFunction[]}): Got => {
const create = (defaults: Defaults): Got => {
// Proxy properties from next handlers
// @ts-ignore Internal use only.
defaults._rawHandlers = defaults.handlers;
defaults.handlers = defaults.handlers.map(fn => ((options, next) => {
// This will be assigned by assigning result
let root!: GotReturn;
let root!: ReturnType<typeof next>;

const result = fn(options, newOptions => {
root = next(newOptions);
Expand All @@ -105,17 +107,17 @@ const create = (defaults: NormalizedDefaults & {_rawHandlers?: HandlerFunction[]
}

return result;
}) as HandlerFunction);
}));

// @ts-ignore Because the for loop handles it for us, as well as the other Object.defines
const got: Got = (url: URLOrOptions, options?: Options): GotReturn => {
let iteration = 0;
const iterateHandlers = (newOptions: Parameters<HandlerFunction>[0]): ReturnType<HandlerFunction> => {
const iterateHandlers = (newOptions: NormalizedOptions): GotReturn => {
return defaults.handlers[iteration++](
newOptions,
// @ts-ignore TS doesn't know that it calls `getPromiseOrStream` at the end
iteration === defaults.handlers.length ? getPromiseOrStream : iterateHandlers
);
) as GotReturn;
};

/* eslint-disable @typescript-eslint/return-await */
Expand All @@ -134,13 +136,15 @@ const create = (defaults: NormalizedDefaults & {_rawHandlers?: HandlerFunction[]

got.extend = (...instancesOrOptions) => {
const optionsArray: Options[] = [defaults.options];
let handlers: HandlerFunction[] = [...defaults._rawHandlers!];
// @ts-ignore Internal use only.
let handlers: HandlerFunction[] = [...defaults._rawHandlers];
let mutableDefaults: boolean | undefined;

for (const value of instancesOrOptions) {
if (isGotInstance(value)) {
optionsArray.push(value.defaults.options);
handlers.push(...value.defaults._rawHandlers!);
// @ts-ignore Internal use only.
handlers.push(...value.defaults._rawHandlers);
mutableDefaults = value.defaults.mutableDefaults;
} else {
optionsArray.push(value);
Expand All @@ -160,7 +164,7 @@ const create = (defaults: NormalizedDefaults & {_rawHandlers?: HandlerFunction[]
}

return create({
options: mergeOptions(...optionsArray),
options: mergeOptions(...optionsArray) as DefaultOptions,
handlers,
mutableDefaults: Boolean(mutableDefaults)
});
Expand All @@ -170,7 +174,7 @@ const create = (defaults: NormalizedDefaults & {_rawHandlers?: HandlerFunction[]
got.stream = (url, options) => got(url, {...options, isStream: true});

for (const method of aliases) {
// @ts-ignore
// @ts-ignore GotReturn<Response> does not equal GotReturn<T>
got[method] = (url: URLOrOptions, options?: Options): GotReturn => got(url, {...options, method});
got.stream[method] = (url, options) => got.stream(url, {...options, method});
}
Expand Down
2 changes: 1 addition & 1 deletion source/errors.ts
Expand Up @@ -79,7 +79,7 @@ export class HTTPError extends GotError {
declare readonly response: Response;

constructor(response: Response, options: NormalizedOptions) {
super(`Response code ${response.statusCode} (${response.statusMessage ?? ''})`, {}, options);
super(`Response code ${response.statusCode} (${response.statusMessage!})`, {}, options);
this.name = 'HTTPError';

Object.defineProperty(this, 'response', {
Expand Down
2 changes: 1 addition & 1 deletion source/get-response.ts
Expand Up @@ -9,7 +9,7 @@ import {NormalizedOptions} from './utils/types';

const pipeline = promisify(stream.pipeline);

export default async (response: IncomingMessage, options: NormalizedOptions, emitter: EventEmitter) => {
export default async (response: IncomingMessage, options: NormalizedOptions, emitter: EventEmitter): Promise<void> => {
const downloadBodySize = Number(response.headers['content-length']) || undefined;
const progressStream = createProgressStream('downloadProgress', emitter, downloadBodySize);

Expand Down
4 changes: 3 additions & 1 deletion source/index.ts
Expand Up @@ -59,7 +59,9 @@ const defaults: Defaults = {
resolveBodyOnly: false,
maxRedirects: 10,
prefixUrl: '',
methodRewriting: true
methodRewriting: true,
ignoreInvalidCookies: false,
context: {}
},
handlers: [defaultHandler],
mutableDefaults: false
Expand Down

0 comments on commit 71b8452

Please sign in to comment.