diff --git a/test/types/api.test-d.ts b/test/types/api.test-d.ts index c64b1315018..85d5e6723a5 100644 --- a/test/types/api.test-d.ts +++ b/test/types/api.test-d.ts @@ -1,5 +1,5 @@ import { Duplex, Readable, Writable } from 'stream' -import { expectAssignable } from 'tsd' +import { expectAssignable, expectType } from 'tsd' import { Dispatcher, request, stream, pipeline, connect, upgrade } from '../..' // request @@ -10,12 +10,22 @@ expectAssignable>(request('', { method: 'GET', // stream expectAssignable>(stream('', { method: 'GET' }, data => { expectAssignable(data) + expectType(data.opaque) + return new Writable() +})) +expectAssignable>>(stream('', { method: 'GET', opaque: { example: '' } }, data => { + expectType<{ example: string }>(data.opaque) return new Writable() })) // pipeline expectAssignable(pipeline('', { method: 'GET' }, data => { expectAssignable(data) + expectType(data.opaque) + return new Readable() +})) +expectAssignable(pipeline('', { method: 'GET', opaque: { example: '' } }, data => { + expectType<{ example: string }>(data.opaque) return new Readable() })) diff --git a/test/types/dispatcher.test-d.ts b/test/types/dispatcher.test-d.ts index 057cfe66d8f..303abd0ade7 100644 --- a/test/types/dispatcher.test-d.ts +++ b/test/types/dispatcher.test-d.ts @@ -66,6 +66,7 @@ expectAssignable(new Dispatcher()) })) expectAssignable>(dispatcher.request({ origin: '', path: '', method: 'GET', responseHeaders: 'raw' })) expectAssignable>(dispatcher.request({ origin: '', path: '', method: 'GET', responseHeaders: null })) + expectAssignable>>(dispatcher.request({ origin: '', path: '', method: 'GET', opaque: { example: '' } })) // pipeline expectAssignable(dispatcher.pipeline({ origin: '', path: '', method: 'GET', maxRedirections: 0 }, data => { @@ -84,6 +85,11 @@ expectAssignable(new Dispatcher()) expectAssignable(data) return new Readable() })) + expectAssignable(dispatcher.pipeline({ origin: '', path: '', method: 'GET', opaque: { example: '' } }, data => { + expectAssignable>(data) + expectType<{ example: string }>(data.opaque) + return new Readable() + })) // stream expectAssignable>(dispatcher.stream({ origin: '', path: '', method: 'GET', maxRedirections: 0 }, data => { @@ -94,6 +100,10 @@ expectAssignable(new Dispatcher()) expectAssignable(data) return new Writable() })) + expectAssignable>>(dispatcher.stream({ origin: '', path: '', method: 'GET', opaque: { example: '' } }, data => { + expectType<{ example: string }>(data.opaque); + return new Writable(); + })); expectAssignable(dispatcher.stream( { origin: '', path: '', method: 'GET', reset: false }, data => { @@ -116,6 +126,18 @@ expectAssignable(new Dispatcher()) expectAssignable(data) } )) + expectAssignable(dispatcher.stream( + { origin: new URL('http://localhost'), path: '', method: 'GET', opaque: { example: '' } }, + data => { + expectAssignable>(data) + return new Writable() + }, + (err, data) => { + expectAssignable(err) + expectAssignable>(data) + expectType<{ example: string }>(data.opaque) + } + )) expectAssignable>(dispatcher.stream({ origin: '', path: '', method: 'GET', responseHeaders: 'raw' }, data => { expectAssignable(data) return new Writable() diff --git a/types/api.d.ts b/types/api.d.ts index 400341dddc0..4fbebb6cd2e 100644 --- a/types/api.d.ts +++ b/types/api.d.ts @@ -11,30 +11,30 @@ export { } /** Performs an HTTP request. */ -declare function request( +declare function request( url: string | URL | UrlObject, - options?: { dispatcher?: Dispatcher } & Omit & Partial>, -): Promise; + options?: { dispatcher?: Dispatcher } & Omit, 'origin' | 'path' | 'method'> & Partial>, +): Promise>; /** A faster version of `request`. */ -declare function stream( +declare function stream( url: string | URL | UrlObject, - options: { dispatcher?: Dispatcher } & Omit, - factory: Dispatcher.StreamFactory -): Promise; + options: { dispatcher?: Dispatcher } & Omit, 'origin' | 'path'>, + factory: Dispatcher.StreamFactory +): Promise>; /** For easy use with `stream.pipeline`. */ -declare function pipeline( +declare function pipeline( url: string | URL | UrlObject, - options: { dispatcher?: Dispatcher } & Omit, - handler: Dispatcher.PipelineHandler + options: { dispatcher?: Dispatcher } & Omit, 'origin' | 'path'>, + handler: Dispatcher.PipelineHandler ): Duplex; /** Starts two-way communications with the requested resource. */ -declare function connect( +declare function connect( url: string | URL | UrlObject, - options?: { dispatcher?: Dispatcher } & Omit -): Promise; + options?: { dispatcher?: Dispatcher } & Omit, 'origin' | 'path'> +): Promise>; /** Upgrade to a different protocol. */ declare function upgrade( diff --git a/types/dispatcher.d.ts b/types/dispatcher.d.ts index 89350159eab..6f33adc4a1d 100644 --- a/types/dispatcher.d.ts +++ b/types/dispatcher.d.ts @@ -16,19 +16,19 @@ declare class Dispatcher extends EventEmitter { /** Dispatches a request. This API is expected to evolve through semver-major versions and is less stable than the preceding higher level APIs. It is primarily intended for library developers who implement higher level APIs on top of this. */ dispatch(options: Dispatcher.DispatchOptions, handler: Dispatcher.DispatchHandlers): boolean; /** Starts two-way communications with the requested resource. */ - connect(options: Dispatcher.ConnectOptions): Promise; - connect(options: Dispatcher.ConnectOptions, callback: (err: Error | null, data: Dispatcher.ConnectData) => void): void; + connect(options: Dispatcher.ConnectOptions): Promise>; + connect(options: Dispatcher.ConnectOptions, callback: (err: Error | null, data: Dispatcher.ConnectData) => void): void; /** Compose a chain of dispatchers */ compose(dispatchers: Dispatcher.DispatcherComposeInterceptor[]): Dispatcher.ComposedDispatcher; compose(...dispatchers: Dispatcher.DispatcherComposeInterceptor[]): Dispatcher.ComposedDispatcher; /** Performs an HTTP request. */ - request(options: Dispatcher.RequestOptions): Promise; - request(options: Dispatcher.RequestOptions, callback: (err: Error | null, data: Dispatcher.ResponseData) => void): void; + request(options: Dispatcher.RequestOptions): Promise>; + request(options: Dispatcher.RequestOptions, callback: (err: Error | null, data: Dispatcher.ResponseData) => void): void; /** For easy use with `stream.pipeline`. */ - pipeline(options: Dispatcher.PipelineOptions, handler: Dispatcher.PipelineHandler): Duplex; + pipeline(options: Dispatcher.PipelineOptions, handler: Dispatcher.PipelineHandler): Duplex; /** A faster version of `Dispatcher.request`. */ - stream(options: Dispatcher.RequestOptions, factory: Dispatcher.StreamFactory): Promise; - stream(options: Dispatcher.RequestOptions, factory: Dispatcher.StreamFactory, callback: (err: Error | null, data: Dispatcher.StreamData) => void): void; + stream(options: Dispatcher.RequestOptions, factory: Dispatcher.StreamFactory): Promise>; + stream(options: Dispatcher.RequestOptions, factory: Dispatcher.StreamFactory, callback: (err: Error | null, data: Dispatcher.StreamData) => void): void; /** Upgrade to a different protocol. */ upgrade(options: Dispatcher.UpgradeOptions): Promise; upgrade(options: Dispatcher.UpgradeOptions, callback: (err: Error | null, data: Dispatcher.UpgradeData) => void): void; @@ -125,7 +125,7 @@ declare namespace Dispatcher { /** For H2, it appends the expect: 100-continue header, and halts the request body until a 100-continue is received from the remote server*/ expectContinue?: boolean; } - export interface ConnectOptions { + export interface ConnectOptions { origin: string | URL; path: string; /** Default: `null` */ @@ -133,7 +133,7 @@ declare namespace Dispatcher { /** Default: `null` */ signal?: AbortSignal | EventEmitter | null; /** This argument parameter is passed through to `ConnectData` */ - opaque?: unknown; + opaque?: TOpaque; /** Default: 0 */ maxRedirections?: number; /** Default: false */ @@ -141,9 +141,9 @@ declare namespace Dispatcher { /** Default: `null` */ responseHeaders?: 'raw' | null; } - export interface RequestOptions extends DispatchOptions { + export interface RequestOptions extends DispatchOptions { /** Default: `null` */ - opaque?: unknown; + opaque?: TOpaque; /** Default: `null` */ signal?: AbortSignal | EventEmitter | null; /** Default: 0 */ @@ -157,7 +157,7 @@ declare namespace Dispatcher { /** Default: `64 KiB` */ highWaterMark?: number; } - export interface PipelineOptions extends RequestOptions { + export interface PipelineOptions extends RequestOptions { /** `true` if the `handler` will return an object stream. Default: `false` */ objectMode?: boolean; } @@ -178,43 +178,43 @@ declare namespace Dispatcher { /** Default: `null` */ responseHeaders?: 'raw' | null; } - export interface ConnectData { + export interface ConnectData { statusCode: number; headers: IncomingHttpHeaders; socket: Duplex; - opaque: unknown; + opaque: TOpaque; } - export interface ResponseData { + export interface ResponseData { statusCode: number; headers: IncomingHttpHeaders; body: BodyReadable & BodyMixin; trailers: Record; - opaque: unknown; + opaque: TOpaque; context: object; } - export interface PipelineHandlerData { + export interface PipelineHandlerData { statusCode: number; headers: IncomingHttpHeaders; - opaque: unknown; + opaque: TOpaque; body: BodyReadable; context: object; } - export interface StreamData { - opaque: unknown; + export interface StreamData { + opaque: TOpaque; trailers: Record; } - export interface UpgradeData { + export interface UpgradeData { headers: IncomingHttpHeaders; socket: Duplex; - opaque: unknown; + opaque: TOpaque; } - export interface StreamFactoryData { + export interface StreamFactoryData { statusCode: number; headers: IncomingHttpHeaders; - opaque: unknown; + opaque: TOpaque; context: object; } - export type StreamFactory = (data: StreamFactoryData) => Writable; + export type StreamFactory = (data: StreamFactoryData) => Writable; export interface DispatchHandlers { /** Invoked before request is dispatched on socket. May be invoked multiple times when a request is retried when the request at the head of the pipeline fails. */ onConnect?(abort: (err?: Error) => void): void; @@ -233,7 +233,7 @@ declare namespace Dispatcher { /** Invoked when a body chunk is sent to the server. May be invoked multiple times for chunked requests */ onBodySent?(chunkSize: number, totalBytesSent: number): void; } - export type PipelineHandler = (data: PipelineHandlerData) => Readable; + export type PipelineHandler = (data: PipelineHandlerData) => Readable; export type HttpMethod = 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE' | 'PATCH'; /**