Skip to content

Commit

Permalink
feat(typings): Using strict-mode TypeScript
Browse files Browse the repository at this point in the history
  • Loading branch information
grantila committed Dec 15, 2018
1 parent 7702c14 commit a51f3a1
Show file tree
Hide file tree
Showing 14 changed files with 193 additions and 124 deletions.
1 change: 1 addition & 0 deletions externs/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module 'to-arraybuffer';
34 changes: 21 additions & 13 deletions lib/body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ import { tap } from 'already'
import { IBody, BodyTypes, StorageBodyTypes } from './core'


function makeUnknownDataError( )
{
return new Error( "Unknown body data" );
}

function throwUnknownData( ): never
{
throw new Error( "Unknown body data" );
throw makeUnknownDataError( );
}

function throwIntegrityMismatch( ): never
Expand Down Expand Up @@ -42,11 +47,12 @@ const emptyBuffer = new ArrayBuffer( 0 );

export class Body implements IBody
{
private _body: StorageBodyTypes;
protected _length: number;
private _body?: StorageBodyTypes | null;
protected _length: number | null;
private _used: boolean;
protected _mime?: string;
private _integrity?: string;
// @ts-ignore
readonly bodyUsed: boolean;

constructor( )
Expand Down Expand Up @@ -102,10 +108,10 @@ export class Body implements IBody
}

protected setBody(
body: BodyTypes | IBody,
mime?: string,
integrity?: string,
length: number = null
body: BodyTypes | IBody | null,
mime?: string | null,
integrity?: string | null,
length: number | null = null
)
: void
{
Expand All @@ -121,8 +127,10 @@ export class Body implements IBody
}
else if ( typeof body === 'string' )
this._body = Buffer.from( body );
else
else if ( body != null )
this._body = < StorageBodyTypes >body;
else
this._body = body;

if ( Buffer.isBuffer( this._body ) )
this._length = ( < Buffer >this._body ).length;
Expand Down Expand Up @@ -162,7 +170,7 @@ export class Body implements IBody
);

else
throwUnknownData( );
throw makeUnknownDataError( );
}

private async blob( ): Promise< never >
Expand Down Expand Up @@ -199,7 +207,7 @@ export class Body implements IBody
) )
.then( buffer => JSON.parse( buffer.toString( ) ) );
else
throwUnknownData( );
throw makeUnknownDataError( );
}

async text( allowIncomplete = false ): Promise< string >
Expand All @@ -224,7 +232,7 @@ export class Body implements IBody
) )
.then( buffer => buffer.toString( ) );
else
return throwUnknownData( );
throw makeUnknownDataError( );
}

async readable( ): Promise< NodeJS.ReadableStream >
Expand All @@ -248,7 +256,7 @@ export class Body implements IBody
return stream;
} );
else
throwUnknownData( );
throw makeUnknownDataError( );
}
}

Expand All @@ -275,7 +283,7 @@ export class StreamBody extends Body

export class DataBody extends Body
{
constructor( data: Buffer | string )
constructor( data: Buffer | string | null )
{
super( );

Expand Down
57 changes: 35 additions & 22 deletions lib/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { version } from './generated/version'
import { fetch } from './fetch'
import { CookieJar } from './cookie-jar'
import { setGotGoaway } from './utils'
import { RawHeaders } from './headers'

const {
HTTP2_HEADER_PATH,
Expand Down Expand Up @@ -85,15 +86,21 @@ export class Context
private _userAgent: string;
private _accept: string;
private _cookieJar: CookieJar;
private _pushHandler: PushHandler;
private _decoders: ReadonlyArray< Decoder >;
private _sessionOptions: SecureClientSessionOptions;
private _pushHandler?: PushHandler;

constructor( opts?: Partial< ContextOptions > )
{
this._h2sessions = new Map( );
this._h2staleSessions = new Map( );

this._userAgent = '';
this._accept = '';
this._cookieJar = < CookieJar >< any >void 0;
this._decoders = [ ];
this._sessionOptions = { };

this.setup( opts );
}

Expand All @@ -107,17 +114,17 @@ export class Context
'overwriteUserAgent' in opts &&
opts.overwriteUserAgent
)
? opts.userAgent
? ( opts.userAgent || '' )
: 'userAgent' in opts
? opts.userAgent + " " + defaultUserAgent
: defaultUserAgent;

this._accept = 'accept' in opts
? opts.accept
? ( opts.accept || defaultAccept )
: defaultAccept;

this._cookieJar = 'cookieJar' in opts
? opts.cookieJar
? ( opts.cookieJar || new CookieJar( ) )
: new CookieJar( );

this._decoders = 'decoders' in opts
Expand Down Expand Up @@ -164,19 +171,20 @@ export class Context
);
pushedStream.once( 'error', reject );

pushedStream.once( 'push', guard( responseHeaders =>
{
const response = new H2StreamResponse(
this._decoders,
path,
pushedStream,
responseHeaders,
false,
null
);

resolve( response );
} ) );
pushedStream.once( 'push', guard(
( responseHeaders: IncomingHttp2Headers ) =>
{
const response = new H2StreamResponse(
this._decoders,
path,
pushedStream,
responseHeaders,
false
);

resolve( response );
}
) );
} );

futureResponse
Expand All @@ -198,7 +206,7 @@ export class Context
? new Error( `Unknown connection error (${event}): ${origin}` )
: new Error( `Connection closed` );

let session: ClientHttp2Session;
let session: ClientHttp2Session = < ClientHttp2Session >< any >void 0;

// TODO: #8
const aGuard = asyncGuard( console.error.bind( console ) );
Expand Down Expand Up @@ -273,7 +281,7 @@ export class Context
this._h2sessions.set( origin, sessionItem );
}

return this._h2sessions.get( origin ).promise
return ( < SessionItem >this._h2sessions.get( origin ) ).promise
.catch( err =>
{
if ( willCreate || created )
Expand Down Expand Up @@ -332,7 +340,8 @@ export class Context
if ( !this._h2staleSessions.has( origin ) )
this._h2staleSessions.set( origin, new Set( ) );

this._h2staleSessions.get( origin ).add( sessionItem.session );
( < Set< ClientHttp2Session > >this._h2staleSessions.get( origin ) )
.add( sessionItem.session );
}

deleteActiveSession( origin: string ): SessionItem | void
Expand Down Expand Up @@ -364,7 +373,9 @@ export class Context

if ( this._h2staleSessions.has( origin ) )
{
const sessionSet = this._h2staleSessions.get( origin );
const sessionSet =
< Set< ClientHttp2Session > >
this._h2staleSessions.get( origin );
this._h2staleSessions.delete( origin );

for ( let session of sessionSet )
Expand All @@ -390,7 +401,9 @@ export class Context
}
else if ( this._h2staleSessions.has( origin ) )
{
const sessionSet = this._h2staleSessions.get( origin );
const sessionSet =
< Set< ClientHttp2Session > >
this._h2staleSessions.get( origin );
if ( sessionSet.has( session ) )
{
sessionSet.delete( session );
Expand Down
2 changes: 1 addition & 1 deletion lib/cookie-jar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export class CookieJar

constructor( jar = new ToughCookieJar( ) )
{
this.reset( jar );
this._jar = jar;
}

reset( jar = new ToughCookieJar( ) )
Expand Down
58 changes: 36 additions & 22 deletions lib/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
'use strict'

import { constants as h2constants } from 'http2'
import {
constants as h2constants,
IncomingHttpHeaders as IncomingHttp2Headers,
} from 'http2'
import { URL } from 'url'

import { delay, Finally } from 'already'
Expand Down Expand Up @@ -78,7 +81,7 @@ function ensureNotCircularRedirection( redirections: ReadonlyArray< string > )
interface FetchExtra
{
redirected: Array< string >;
timeoutAt: number;
timeoutAt?: number;
raceConditionedGoaway: Set< string >; // per origin
}

Expand Down Expand Up @@ -171,16 +174,16 @@ async function fetchImpl(
}

const timeoutAt = extra.timeoutAt || (
'timeout' in init
( 'timeout' in init && typeof init.timeout === 'number' )
// Setting the timeoutAt here at first time allows async cookie
// jar to not take part of timeout for at least the first request
// (in a potential redirect chain)
? Date.now( ) + init.timeout
: null
: void 0
);

function setupTimeout( )
: { promise: Promise< Response >; clear: Function; }
: { promise: Promise< Response >; clear: Function; } | null
{
if ( !timeoutAt )
return null;
Expand All @@ -189,7 +192,7 @@ async function fetchImpl(
if ( now >= timeoutAt )
throw timeoutError( );

let timerId;
let timerId: NodeJS.Timeout | null;

return {
clear: ( ) =>
Expand Down Expand Up @@ -221,7 +224,7 @@ async function fetchImpl(
if ( signal && signal.aborted )
throw abortError( );

const signalPromise: Promise< Response > =
const signalPromise: Promise< Response > | null =
signal
?
new Promise< Response >( ( resolve, reject ) =>
Expand All @@ -239,7 +242,7 @@ async function fetchImpl(
timeoutInfo.clear( );

if ( signal )
signal.onabort = null;
delete signal.onabort;
}

function doFetch( ): Promise< Response >
Expand Down Expand Up @@ -307,7 +310,7 @@ async function fetchImpl(
} )
);

stream.on( 'streamClosed', guard( errorCode =>
stream.on( 'streamClosed', guard( ( errorCode: number ) =>
{
// We'll get an 'error' event if there actually is an
// error, but not if we got NGHTTP2_NO_ERROR.
Expand All @@ -323,7 +326,8 @@ async function fetchImpl(
reject( new TimeoutError( "Request timed out" ) );
} ) );

stream.on( 'trailers', guard( ( _headers, flags ) =>
stream.on( 'trailers', guard(
( _headers: IncomingHttp2Headers, _flags: any ) =>
{
if ( !onTrailers )
return;
Expand Down Expand Up @@ -359,16 +363,19 @@ async function fetchImpl(
"This can't happen unless a server failure" ) );
} ) );

stream.on( 'headers', guard( ( headers, flags ) =>
{
const code = headers[ HTTP2_HEADER_STATUS ];
reject( new Error(
`Request failed with a ${code} status. ` +
"Any 1xx error is unexpected to fetch() and " +
"shouldn't happen." ) );
} ) );
stream.on( 'headers', guard(
( headers: IncomingHttp2Headers, _flags: any ) =>
{
const code = headers[ HTTP2_HEADER_STATUS ];
reject( new Error(
`Request failed with a ${code} status. ` +
"Any 1xx error is unexpected to fetch() and " +
"shouldn't happen." ) );
}
) );

stream.on( 'response', guard( headers =>
stream.on( 'response', guard(
( headers: IncomingHttp2Headers ) =>
{
if ( signal && signal.aborted )
{
Expand Down Expand Up @@ -431,6 +438,13 @@ async function fetchImpl(
`URL got redirected to ${location}, which ` +
`'fetch-h2' doesn't support for ${method}` ) );

if ( !location )
return reject(
new Error(
`URL got redirected without 'location' header`
)
);

stream.destroy( );
resolve(
fetchImpl(
Expand Down Expand Up @@ -460,8 +474,8 @@ async function fetchImpl(

return Promise.race(
[
signalPromise,
timeoutInfo && timeoutInfo.promise,
< Promise< any > >signalPromise,
< Promise< any > >( timeoutInfo && timeoutInfo.promise ),
doFetch( ),
]
.filter( promise => promise )
Expand All @@ -476,7 +490,7 @@ export function fetch(
)
: Promise< Response >
{
const timeoutAt = null;
const timeoutAt = void 0;

const raceConditionedGoaway = new Set( );
const extra = { timeoutAt, redirected: [ ], raceConditionedGoaway };
Expand Down
Loading

0 comments on commit a51f3a1

Please sign in to comment.