Skip to content

Commit 374402e

Browse files
authored
feat: enable isolatedDeclarations (#615)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Tightened TypeScript typings and added explicit return types across public APIs; many imports converted to type-only. * **New Features** * Introduced a default urllib-style runtime object exposing request, curl and USER_AGENT. * **Chores** * Updated build/config typing options to improve compile-time checks. * **Tests** * Test imports adjusted to use type-only imports; test behavior unchanged. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent ca378bc commit 374402e

19 files changed

+137
-99
lines changed

src/BaseAgent.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { AsyncLocalStorage } from 'node:async_hooks';
22

33
import { Agent, Dispatcher } from 'undici';
44

5-
import { FetchOpaque } from './FetchOpaqueInterceptor.js';
5+
import type { FetchOpaque } from './FetchOpaqueInterceptor.js';
66

77
export interface BaseAgentOptions extends Agent.Options {
88
opaqueLocalStorage?: AsyncLocalStorage<FetchOpaque>;

src/FormData.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import _FormData from 'form-data';
66
const NON_ASCII_RE = /[^\x00-\x7F]/i;
77

88
export class FormData extends _FormData {
9-
_getContentDisposition(value: any, options: any) {
9+
_getContentDisposition(value: any, options: any): string | undefined {
1010
// support non-ascii filename
1111
// https://github.com/form-data/form-data/pull/571
1212
let filename;

src/HttpAgent.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import dns from 'node:dns';
2-
import { LookupFunction, isIP } from 'node:net';
2+
import { isIP } from 'node:net';
3+
import type { LookupFunction } from 'node:net';
34

45
import { Agent, Dispatcher, buildConnector } from 'undici';
56

6-
import { BaseAgent, BaseAgentOptions } from './BaseAgent.js';
7+
import { BaseAgent } from './BaseAgent.js';
8+
import type { BaseAgentOptions } from './BaseAgent.js';
79

810
export type CheckAddressFunction = (ip: string, family: number | string, hostname: string) => boolean;
911

src/HttpClient.ts

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import diagnosticsChannel from 'node:diagnostics_channel';
2+
import type { Channel } from 'node:diagnostics_channel';
23
import { EventEmitter } from 'node:events';
34
import { createReadStream } from 'node:fs';
45
import { STATUS_CODES } from 'node:http';
5-
import { LookupFunction } from 'node:net';
6+
import type { LookupFunction } from 'node:net';
67
import { basename } from 'node:path';
78
import { performance } from 'node:perf_hooks';
89
import querystring from 'node:querystring';
@@ -23,13 +24,14 @@ import { request as undiciRequest, Dispatcher, Agent, getGlobalDispatcher, Pool
2324
import undiciSymbols from 'undici/lib/core/symbols.js';
2425

2526
import { initDiagnosticsChannel } from './diagnosticsChannel.js';
26-
import { FetchOpaque } from './FetchOpaqueInterceptor.js';
27+
import type { FetchOpaque } from './FetchOpaqueInterceptor.js';
2728
import { FormData } from './FormData.js';
28-
import { HttpAgent, CheckAddressFunction } from './HttpAgent.js';
29+
import { HttpAgent } from './HttpAgent.js';
30+
import type { CheckAddressFunction } from './HttpAgent.js';
2931
import { HttpClientConnectTimeoutError, HttpClientRequestTimeoutError } from './HttpClientError.js';
3032
import type { IncomingHttpHeaders } from './IncomingHttpHeaders.js';
31-
import { RequestURL, RequestOptions, HttpMethod, RequestMeta } from './Request.js';
32-
import { RawResponseWithMeta, HttpClientResponse, SocketInfo } from './Response.js';
33+
import type { RequestURL, RequestOptions, HttpMethod, RequestMeta } from './Request.js';
34+
import type { RawResponseWithMeta, HttpClientResponse, SocketInfo } from './Response.js';
3335
import symbols from './symbols.js';
3436
import { parseJSON, digestAuthHeader, globalId, performanceTime, isReadable, updateSocketInfo } from './utils.js';
3537

@@ -38,7 +40,7 @@ type UndiciRequestOption = Exists<Parameters<typeof undiciRequest>[1]>;
3840
type PropertyShouldBe<T, K extends keyof T, V> = Omit<T, K> & { [P in K]: V };
3941
type IUndiciRequestOption = PropertyShouldBe<UndiciRequestOption, 'headers', IncomingHttpHeaders>;
4042

41-
export const PROTO_RE = /^https?:\/\//i;
43+
export const PROTO_RE: RegExp = /^https?:\/\//i;
4244

4345
export interface UndiciTimingInfo {
4446
startTime: number;
@@ -64,7 +66,7 @@ export interface UndiciTimingInfo {
6466
// keep typo compatibility
6567
export interface UnidiciTimingInfo extends UndiciTimingInfo {}
6668

67-
function noop() {
69+
function noop(): void {
6870
// noop
6971
}
7072

@@ -108,19 +110,19 @@ export type ClientOptions = {
108110
};
109111
};
110112

111-
export const VERSION = 'VERSION';
113+
export const VERSION: string = 'VERSION';
112114
// 'node-urllib/4.0.0 Node.js/18.19.0 (darwin; x64)'
113-
export const HEADER_USER_AGENT = `node-urllib/${VERSION} Node.js/${process.version.substring(1)} (${process.platform}; ${process.arch})`;
115+
export const HEADER_USER_AGENT: string = `node-urllib/${VERSION} Node.js/${process.version.substring(1)} (${process.platform}; ${process.arch})`;
114116

115-
function getFileName(stream: Readable) {
117+
function getFileName(stream: Readable): string {
116118
const filePath: string = (stream as any).path;
117119
if (filePath) {
118120
return basename(filePath);
119121
}
120122
return '';
121123
}
122124

123-
function defaultIsRetry(response: HttpClientResponse) {
125+
function defaultIsRetry(response: HttpClientResponse): boolean {
124126
return response.status >= 500;
125127
}
126128

@@ -132,7 +134,12 @@ export type RequestContext = {
132134
history: string[];
133135
};
134136

135-
export const channels = {
137+
export const channels: {
138+
request: Channel;
139+
response: Channel;
140+
fetchRequest: Channel;
141+
fetchResponse: Channel;
142+
} = {
136143
request: diagnosticsChannel.channel('urllib:request'),
137144
response: diagnosticsChannel.channel('urllib:response'),
138145
fetchRequest: diagnosticsChannel.channel('urllib:fetch:request'),
@@ -205,15 +212,15 @@ export class HttpClient extends EventEmitter {
205212
initDiagnosticsChannel();
206213
}
207214

208-
getDispatcher() {
215+
getDispatcher(): Dispatcher {
209216
return this.#dispatcher ?? getGlobalDispatcher();
210217
}
211218

212-
setDispatcher(dispatcher: Dispatcher) {
219+
setDispatcher(dispatcher: Dispatcher): void {
213220
this.#dispatcher = dispatcher;
214221
}
215222

216-
getDispatcherPoolStats() {
223+
getDispatcherPoolStats(): Record<string, PoolStat> {
217224
const agent = this.getDispatcher();
218225
// origin => Pool Instance
219226
const clients: Map<string, WeakRef<Pool>> | undefined = Reflect.get(agent, undiciSymbols.kClients);
@@ -239,12 +246,12 @@ export class HttpClient extends EventEmitter {
239246
return poolStatsMap;
240247
}
241248

242-
async request<T = any>(url: RequestURL, options?: RequestOptions) {
249+
async request<T = any>(url: RequestURL, options?: RequestOptions): Promise<HttpClientResponse<T>> {
243250
return await this.#requestInternal<T>(url, options);
244251
}
245252

246253
// alias to request, keep compatible with urllib@2 HttpClient.curl
247-
async curl<T = any>(url: RequestURL, options?: RequestOptions) {
254+
async curl<T = any>(url: RequestURL, options?: RequestOptions): Promise<HttpClientResponse<T>> {
248255
return await this.request<T>(url, options);
249256
}
250257

src/diagnosticsChannel.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Socket } from 'node:net';
33
import { performance } from 'node:perf_hooks';
44
import { debuglog } from 'node:util';
55

6-
import { DiagnosticsChannel } from 'undici';
6+
import type { DiagnosticsChannel } from 'undici';
77

88
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
99
// @ts-ignore
@@ -82,7 +82,7 @@ function getRequestOpaque(request: DiagnosticsChannel.Request, kHandler?: symbol
8282
return handler?.opts?.opaque ?? handler?.opaque;
8383
}
8484

85-
export function initDiagnosticsChannel() {
85+
export function initDiagnosticsChannel(): void {
8686
// make sure init global DiagnosticsChannel once
8787
if (initedDiagnosticsChannel) return;
8888
initedDiagnosticsChannel = true;

src/fetch.ts

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,32 @@
11
import { AsyncLocalStorage } from 'node:async_hooks';
22
import { debuglog } from 'node:util';
33

4-
import {
5-
fetch as UndiciFetch,
6-
RequestInfo,
7-
RequestInit,
8-
Request,
9-
Response,
10-
Agent,
11-
getGlobalDispatcher,
12-
Pool,
13-
Dispatcher,
14-
} from 'undici';
4+
import { fetch as UndiciFetch, Request, Response, Agent, getGlobalDispatcher, Pool, Dispatcher } from 'undici';
5+
import type { RequestInfo, RequestInit } from 'undici';
156
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
167
// @ts-ignore
178
import undiciSymbols from 'undici/lib/core/symbols.js';
189
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
1910
// @ts-ignore
2011
import { getResponseState } from 'undici/lib/web/fetch/response.js';
2112

22-
import { BaseAgent, BaseAgentOptions } from './BaseAgent.js';
13+
import { BaseAgent } from './BaseAgent.js';
14+
import type { BaseAgentOptions } from './BaseAgent.js';
2315
import { initDiagnosticsChannel } from './diagnosticsChannel.js';
24-
import { FetchOpaque } from './FetchOpaqueInterceptor.js';
25-
import { HttpAgent, HttpAgentOptions } from './HttpAgent.js';
26-
import {
27-
channels,
16+
import type { FetchOpaque } from './FetchOpaqueInterceptor.js';
17+
import { HttpAgent } from './HttpAgent.js';
18+
import type { HttpAgentOptions } from './HttpAgent.js';
19+
import { channels } from './HttpClient.js';
20+
import type {
2821
ClientOptions,
2922
PoolStat,
3023
RequestDiagnosticsMessage,
3124
ResponseDiagnosticsMessage,
3225
UndiciTimingInfo,
3326
} from './HttpClient.js';
34-
import { IncomingHttpHeaders } from './IncomingHttpHeaders.js';
35-
import { FetchMeta, HttpMethod, RequestMeta } from './Request.js';
36-
import { RawResponseWithMeta, SocketInfo } from './Response.js';
27+
import type { IncomingHttpHeaders } from './IncomingHttpHeaders.js';
28+
import type { FetchMeta, HttpMethod, RequestMeta } from './Request.js';
29+
import type { RawResponseWithMeta, SocketInfo } from './Response.js';
3730
import symbols from './symbols.js';
3831
import { convertHeader, globalId, performanceTime, updateSocketInfo } from './utils.js';
3932

@@ -63,7 +56,7 @@ export class FetchFactory {
6356

6457
static #instance = new FetchFactory();
6558

66-
setClientOptions(clientOptions: ClientOptions) {
59+
setClientOptions(clientOptions: ClientOptions): void {
6760
let dispatcherOption: BaseAgentOptions = {
6861
opaqueLocalStorage: this.#opaqueLocalStorage,
6962
};
@@ -96,15 +89,15 @@ export class FetchFactory {
9689
initDiagnosticsChannel();
9790
}
9891

99-
getDispatcher() {
92+
getDispatcher(): Dispatcher {
10093
return this.#dispatcher ?? getGlobalDispatcher();
10194
}
10295

103-
setDispatcher(dispatcher: Agent) {
96+
setDispatcher(dispatcher: Agent): void {
10497
this.#dispatcher = dispatcher;
10598
}
10699

107-
getDispatcherPoolStats() {
100+
getDispatcherPoolStats(): Record<string, PoolStat> {
108101
const agent = this.getDispatcher();
109102
// origin => Pool Instance
110103
const clients: Map<string, WeakRef<Pool>> | undefined = Reflect.get(agent, undiciSymbols.kClients);
@@ -130,11 +123,11 @@ export class FetchFactory {
130123
return poolStatsMap;
131124
}
132125

133-
static setClientOptions(clientOptions: ClientOptions) {
126+
static setClientOptions(clientOptions: ClientOptions): void {
134127
FetchFactory.#instance.setClientOptions(clientOptions);
135128
}
136129

137-
static getDispatcherPoolStats() {
130+
static getDispatcherPoolStats(): Record<string, PoolStat> {
138131
return FetchFactory.#instance.getDispatcherPoolStats();
139132
}
140133

@@ -283,11 +276,11 @@ export class FetchFactory {
283276
return res!;
284277
}
285278

286-
static getDispatcher() {
279+
static getDispatcher(): Dispatcher {
287280
return FetchFactory.#instance.getDispatcher();
288281
}
289282

290-
static setDispatcher(dispatcher: Agent) {
283+
static setDispatcher(dispatcher: Agent): void {
291284
FetchFactory.#instance.setDispatcher(dispatcher);
292285
}
293286

@@ -296,4 +289,4 @@ export class FetchFactory {
296289
}
297290
}
298291

299-
export const fetch = FetchFactory.fetch;
292+
export const fetch: (input: RequestInfo, init?: UrllibRequestInit) => Promise<Response> = FetchFactory.fetch;

src/index.ts

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import { patchForNode16 } from './utils.js';
55
patchForNode16();
66

77
import { HttpClient, HEADER_USER_AGENT } from './HttpClient.js';
8-
import { RequestOptions, RequestURL } from './Request.js';
8+
import type { RequestOptions, RequestURL } from './Request.js';
9+
import type { HttpClientResponse } from './Response.js';
910

1011
let httpClient: HttpClient;
1112
let allowH2HttpClient: HttpClient;
@@ -63,7 +64,10 @@ interface UrllibRequestOptions extends RequestOptions {
6364
allowH2?: boolean;
6465
}
6566

66-
export async function request<T = any>(url: RequestURL, options?: UrllibRequestOptions) {
67+
export async function request<T = any>(
68+
url: RequestURL,
69+
options?: UrllibRequestOptions,
70+
): Promise<HttpClientResponse<T>> {
6771
if (options?.socketPath) {
6872
let domainSocketHttpclient = domainSocketHttpClients.get<HttpClient>(options.socketPath);
6973
if (!domainSocketHttpclient) {
@@ -83,7 +87,7 @@ export async function request<T = any>(url: RequestURL, options?: UrllibRequestO
8387
// import * as urllib from 'urllib';
8488
// urllib.curl(url);
8589
// ```
86-
export async function curl<T = any>(url: RequestURL, options?: UrllibRequestOptions) {
90+
export async function curl<T = any>(url: RequestURL, options?: UrllibRequestOptions): Promise<HttpClientResponse<T>> {
8791
return await request<T>(url, options);
8892
}
8993

@@ -95,25 +99,16 @@ export {
9599
setGlobalDispatcher,
96100
getGlobalDispatcher,
97101
Request,
98-
RequestInfo,
99-
RequestInit,
100102
Response,
101-
BodyInit,
102-
ResponseInit,
103103
Headers,
104104
FormData,
105105
} from 'undici';
106+
export type { RequestInfo, RequestInit, BodyInit, ResponseInit } from 'undici';
106107
// HttpClient2 is keep compatible with urllib@2 HttpClient2
107-
export {
108-
HttpClient,
109-
HttpClient as HttpClient2,
110-
HEADER_USER_AGENT as USER_AGENT,
111-
RequestDiagnosticsMessage,
112-
ResponseDiagnosticsMessage,
113-
ClientOptions,
114-
} from './HttpClient.js';
108+
export { HttpClient, HttpClient as HttpClient2, HEADER_USER_AGENT as USER_AGENT } from './HttpClient.js';
109+
export type { RequestDiagnosticsMessage, ResponseDiagnosticsMessage, ClientOptions } from './HttpClient.js';
115110
// RequestOptions2 is keep compatible with urllib@2 RequestOptions2
116-
export {
111+
export type {
117112
RequestOptions,
118113
RequestOptions as RequestOptions2,
119114
RequestURL,
@@ -122,16 +117,22 @@ export {
122117
FixJSONCtlChars,
123118
} from './Request.js';
124119

125-
export { CheckAddressFunction } from './HttpAgent.js';
120+
export type { CheckAddressFunction } from './HttpAgent.js';
126121

127-
export { SocketInfo, Timing, RawResponseWithMeta, HttpClientResponse } from './Response.js';
128-
export { IncomingHttpHeaders } from './IncomingHttpHeaders.js';
122+
export type { SocketInfo, Timing, RawResponseWithMeta, HttpClientResponse } from './Response.js';
123+
export type { IncomingHttpHeaders } from './IncomingHttpHeaders.js';
129124
export * from './HttpClientError.js';
130125
export { FetchFactory, fetch } from './fetch.js';
131126
export { FormData as WebFormData } from './FormData.js';
132127

133-
export default {
128+
const urllib: {
129+
request: typeof request;
130+
curl: typeof curl;
131+
USER_AGENT: string;
132+
} = {
134133
request,
135134
curl,
136135
USER_AGENT: HEADER_USER_AGENT,
137136
};
137+
138+
export default urllib;

0 commit comments

Comments
 (0)