diff --git a/src/BaseAgent.ts b/src/BaseAgent.ts index 49834eb5..826207e2 100644 --- a/src/BaseAgent.ts +++ b/src/BaseAgent.ts @@ -2,7 +2,7 @@ import { AsyncLocalStorage } from 'node:async_hooks'; import { Agent, Dispatcher } from 'undici'; -import { FetchOpaque } from './FetchOpaqueInterceptor.js'; +import type { FetchOpaque } from './FetchOpaqueInterceptor.js'; export interface BaseAgentOptions extends Agent.Options { opaqueLocalStorage?: AsyncLocalStorage; diff --git a/src/FormData.ts b/src/FormData.ts index 3a3cd810..d67d6844 100644 --- a/src/FormData.ts +++ b/src/FormData.ts @@ -6,7 +6,7 @@ import _FormData from 'form-data'; const NON_ASCII_RE = /[^\x00-\x7F]/i; export class FormData extends _FormData { - _getContentDisposition(value: any, options: any) { + _getContentDisposition(value: any, options: any): string | undefined { // support non-ascii filename // https://github.com/form-data/form-data/pull/571 let filename; diff --git a/src/HttpAgent.ts b/src/HttpAgent.ts index cbe6450b..dc04368c 100644 --- a/src/HttpAgent.ts +++ b/src/HttpAgent.ts @@ -1,9 +1,11 @@ import dns from 'node:dns'; -import { LookupFunction, isIP } from 'node:net'; +import { isIP } from 'node:net'; +import type { LookupFunction } from 'node:net'; import { Agent, Dispatcher, buildConnector } from 'undici'; -import { BaseAgent, BaseAgentOptions } from './BaseAgent.js'; +import { BaseAgent } from './BaseAgent.js'; +import type { BaseAgentOptions } from './BaseAgent.js'; export type CheckAddressFunction = (ip: string, family: number | string, hostname: string) => boolean; diff --git a/src/HttpClient.ts b/src/HttpClient.ts index fda8912f..268eb1ee 100644 --- a/src/HttpClient.ts +++ b/src/HttpClient.ts @@ -1,8 +1,9 @@ import diagnosticsChannel from 'node:diagnostics_channel'; +import type { Channel } from 'node:diagnostics_channel'; import { EventEmitter } from 'node:events'; import { createReadStream } from 'node:fs'; import { STATUS_CODES } from 'node:http'; -import { LookupFunction } from 'node:net'; +import type { LookupFunction } from 'node:net'; import { basename } from 'node:path'; import { performance } from 'node:perf_hooks'; import querystring from 'node:querystring'; @@ -23,13 +24,14 @@ import { request as undiciRequest, Dispatcher, Agent, getGlobalDispatcher, Pool import undiciSymbols from 'undici/lib/core/symbols.js'; import { initDiagnosticsChannel } from './diagnosticsChannel.js'; -import { FetchOpaque } from './FetchOpaqueInterceptor.js'; +import type { FetchOpaque } from './FetchOpaqueInterceptor.js'; import { FormData } from './FormData.js'; -import { HttpAgent, CheckAddressFunction } from './HttpAgent.js'; +import { HttpAgent } from './HttpAgent.js'; +import type { CheckAddressFunction } from './HttpAgent.js'; import { HttpClientConnectTimeoutError, HttpClientRequestTimeoutError } from './HttpClientError.js'; import type { IncomingHttpHeaders } from './IncomingHttpHeaders.js'; -import { RequestURL, RequestOptions, HttpMethod, RequestMeta } from './Request.js'; -import { RawResponseWithMeta, HttpClientResponse, SocketInfo } from './Response.js'; +import type { RequestURL, RequestOptions, HttpMethod, RequestMeta } from './Request.js'; +import type { RawResponseWithMeta, HttpClientResponse, SocketInfo } from './Response.js'; import symbols from './symbols.js'; import { parseJSON, digestAuthHeader, globalId, performanceTime, isReadable, updateSocketInfo } from './utils.js'; @@ -38,7 +40,7 @@ type UndiciRequestOption = Exists[1]>; type PropertyShouldBe = Omit & { [P in K]: V }; type IUndiciRequestOption = PropertyShouldBe; -export const PROTO_RE = /^https?:\/\//i; +export const PROTO_RE: RegExp = /^https?:\/\//i; export interface UndiciTimingInfo { startTime: number; @@ -64,7 +66,7 @@ export interface UndiciTimingInfo { // keep typo compatibility export interface UnidiciTimingInfo extends UndiciTimingInfo {} -function noop() { +function noop(): void { // noop } @@ -108,11 +110,11 @@ export type ClientOptions = { }; }; -export const VERSION = 'VERSION'; +export const VERSION: string = 'VERSION'; // 'node-urllib/4.0.0 Node.js/18.19.0 (darwin; x64)' -export const HEADER_USER_AGENT = `node-urllib/${VERSION} Node.js/${process.version.substring(1)} (${process.platform}; ${process.arch})`; +export const HEADER_USER_AGENT: string = `node-urllib/${VERSION} Node.js/${process.version.substring(1)} (${process.platform}; ${process.arch})`; -function getFileName(stream: Readable) { +function getFileName(stream: Readable): string { const filePath: string = (stream as any).path; if (filePath) { return basename(filePath); @@ -120,7 +122,7 @@ function getFileName(stream: Readable) { return ''; } -function defaultIsRetry(response: HttpClientResponse) { +function defaultIsRetry(response: HttpClientResponse): boolean { return response.status >= 500; } @@ -132,7 +134,12 @@ export type RequestContext = { history: string[]; }; -export const channels = { +export const channels: { + request: Channel; + response: Channel; + fetchRequest: Channel; + fetchResponse: Channel; +} = { request: diagnosticsChannel.channel('urllib:request'), response: diagnosticsChannel.channel('urllib:response'), fetchRequest: diagnosticsChannel.channel('urllib:fetch:request'), @@ -205,15 +212,15 @@ export class HttpClient extends EventEmitter { initDiagnosticsChannel(); } - getDispatcher() { + getDispatcher(): Dispatcher { return this.#dispatcher ?? getGlobalDispatcher(); } - setDispatcher(dispatcher: Dispatcher) { + setDispatcher(dispatcher: Dispatcher): void { this.#dispatcher = dispatcher; } - getDispatcherPoolStats() { + getDispatcherPoolStats(): Record { const agent = this.getDispatcher(); // origin => Pool Instance const clients: Map> | undefined = Reflect.get(agent, undiciSymbols.kClients); @@ -239,12 +246,12 @@ export class HttpClient extends EventEmitter { return poolStatsMap; } - async request(url: RequestURL, options?: RequestOptions) { + async request(url: RequestURL, options?: RequestOptions): Promise> { return await this.#requestInternal(url, options); } // alias to request, keep compatible with urllib@2 HttpClient.curl - async curl(url: RequestURL, options?: RequestOptions) { + async curl(url: RequestURL, options?: RequestOptions): Promise> { return await this.request(url, options); } diff --git a/src/diagnosticsChannel.ts b/src/diagnosticsChannel.ts index 507ad7f2..2b07a75e 100644 --- a/src/diagnosticsChannel.ts +++ b/src/diagnosticsChannel.ts @@ -3,7 +3,7 @@ import { Socket } from 'node:net'; import { performance } from 'node:perf_hooks'; import { debuglog } from 'node:util'; -import { DiagnosticsChannel } from 'undici'; +import type { DiagnosticsChannel } from 'undici'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore @@ -82,7 +82,7 @@ function getRequestOpaque(request: DiagnosticsChannel.Request, kHandler?: symbol return handler?.opts?.opaque ?? handler?.opaque; } -export function initDiagnosticsChannel() { +export function initDiagnosticsChannel(): void { // make sure init global DiagnosticsChannel once if (initedDiagnosticsChannel) return; initedDiagnosticsChannel = true; diff --git a/src/fetch.ts b/src/fetch.ts index cb9c042f..e9f0acb5 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -1,17 +1,8 @@ import { AsyncLocalStorage } from 'node:async_hooks'; import { debuglog } from 'node:util'; -import { - fetch as UndiciFetch, - RequestInfo, - RequestInit, - Request, - Response, - Agent, - getGlobalDispatcher, - Pool, - Dispatcher, -} from 'undici'; +import { fetch as UndiciFetch, Request, Response, Agent, getGlobalDispatcher, Pool, Dispatcher } from 'undici'; +import type { RequestInfo, RequestInit } from 'undici'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore import undiciSymbols from 'undici/lib/core/symbols.js'; @@ -19,21 +10,23 @@ import undiciSymbols from 'undici/lib/core/symbols.js'; // @ts-ignore import { getResponseState } from 'undici/lib/web/fetch/response.js'; -import { BaseAgent, BaseAgentOptions } from './BaseAgent.js'; +import { BaseAgent } from './BaseAgent.js'; +import type { BaseAgentOptions } from './BaseAgent.js'; import { initDiagnosticsChannel } from './diagnosticsChannel.js'; -import { FetchOpaque } from './FetchOpaqueInterceptor.js'; -import { HttpAgent, HttpAgentOptions } from './HttpAgent.js'; -import { - channels, +import type { FetchOpaque } from './FetchOpaqueInterceptor.js'; +import { HttpAgent } from './HttpAgent.js'; +import type { HttpAgentOptions } from './HttpAgent.js'; +import { channels } from './HttpClient.js'; +import type { ClientOptions, PoolStat, RequestDiagnosticsMessage, ResponseDiagnosticsMessage, UndiciTimingInfo, } from './HttpClient.js'; -import { IncomingHttpHeaders } from './IncomingHttpHeaders.js'; -import { FetchMeta, HttpMethod, RequestMeta } from './Request.js'; -import { RawResponseWithMeta, SocketInfo } from './Response.js'; +import type { IncomingHttpHeaders } from './IncomingHttpHeaders.js'; +import type { FetchMeta, HttpMethod, RequestMeta } from './Request.js'; +import type { RawResponseWithMeta, SocketInfo } from './Response.js'; import symbols from './symbols.js'; import { convertHeader, globalId, performanceTime, updateSocketInfo } from './utils.js'; @@ -63,7 +56,7 @@ export class FetchFactory { static #instance = new FetchFactory(); - setClientOptions(clientOptions: ClientOptions) { + setClientOptions(clientOptions: ClientOptions): void { let dispatcherOption: BaseAgentOptions = { opaqueLocalStorage: this.#opaqueLocalStorage, }; @@ -96,15 +89,15 @@ export class FetchFactory { initDiagnosticsChannel(); } - getDispatcher() { + getDispatcher(): Dispatcher { return this.#dispatcher ?? getGlobalDispatcher(); } - setDispatcher(dispatcher: Agent) { + setDispatcher(dispatcher: Agent): void { this.#dispatcher = dispatcher; } - getDispatcherPoolStats() { + getDispatcherPoolStats(): Record { const agent = this.getDispatcher(); // origin => Pool Instance const clients: Map> | undefined = Reflect.get(agent, undiciSymbols.kClients); @@ -130,11 +123,11 @@ export class FetchFactory { return poolStatsMap; } - static setClientOptions(clientOptions: ClientOptions) { + static setClientOptions(clientOptions: ClientOptions): void { FetchFactory.#instance.setClientOptions(clientOptions); } - static getDispatcherPoolStats() { + static getDispatcherPoolStats(): Record { return FetchFactory.#instance.getDispatcherPoolStats(); } @@ -283,11 +276,11 @@ export class FetchFactory { return res!; } - static getDispatcher() { + static getDispatcher(): Dispatcher { return FetchFactory.#instance.getDispatcher(); } - static setDispatcher(dispatcher: Agent) { + static setDispatcher(dispatcher: Agent): void { FetchFactory.#instance.setDispatcher(dispatcher); } @@ -296,4 +289,4 @@ export class FetchFactory { } } -export const fetch = FetchFactory.fetch; +export const fetch: (input: RequestInfo, init?: UrllibRequestInit) => Promise = FetchFactory.fetch; diff --git a/src/index.ts b/src/index.ts index ad69b5ff..ca917e5f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,8 @@ import { patchForNode16 } from './utils.js'; patchForNode16(); import { HttpClient, HEADER_USER_AGENT } from './HttpClient.js'; -import { RequestOptions, RequestURL } from './Request.js'; +import type { RequestOptions, RequestURL } from './Request.js'; +import type { HttpClientResponse } from './Response.js'; let httpClient: HttpClient; let allowH2HttpClient: HttpClient; @@ -63,7 +64,10 @@ interface UrllibRequestOptions extends RequestOptions { allowH2?: boolean; } -export async function request(url: RequestURL, options?: UrllibRequestOptions) { +export async function request( + url: RequestURL, + options?: UrllibRequestOptions, +): Promise> { if (options?.socketPath) { let domainSocketHttpclient = domainSocketHttpClients.get(options.socketPath); if (!domainSocketHttpclient) { @@ -83,7 +87,7 @@ export async function request(url: RequestURL, options?: UrllibRequestO // import * as urllib from 'urllib'; // urllib.curl(url); // ``` -export async function curl(url: RequestURL, options?: UrllibRequestOptions) { +export async function curl(url: RequestURL, options?: UrllibRequestOptions): Promise> { return await request(url, options); } @@ -95,25 +99,16 @@ export { setGlobalDispatcher, getGlobalDispatcher, Request, - RequestInfo, - RequestInit, Response, - BodyInit, - ResponseInit, Headers, FormData, } from 'undici'; +export type { RequestInfo, RequestInit, BodyInit, ResponseInit } from 'undici'; // HttpClient2 is keep compatible with urllib@2 HttpClient2 -export { - HttpClient, - HttpClient as HttpClient2, - HEADER_USER_AGENT as USER_AGENT, - RequestDiagnosticsMessage, - ResponseDiagnosticsMessage, - ClientOptions, -} from './HttpClient.js'; +export { HttpClient, HttpClient as HttpClient2, HEADER_USER_AGENT as USER_AGENT } from './HttpClient.js'; +export type { RequestDiagnosticsMessage, ResponseDiagnosticsMessage, ClientOptions } from './HttpClient.js'; // RequestOptions2 is keep compatible with urllib@2 RequestOptions2 -export { +export type { RequestOptions, RequestOptions as RequestOptions2, RequestURL, @@ -122,16 +117,22 @@ export { FixJSONCtlChars, } from './Request.js'; -export { CheckAddressFunction } from './HttpAgent.js'; +export type { CheckAddressFunction } from './HttpAgent.js'; -export { SocketInfo, Timing, RawResponseWithMeta, HttpClientResponse } from './Response.js'; -export { IncomingHttpHeaders } from './IncomingHttpHeaders.js'; +export type { SocketInfo, Timing, RawResponseWithMeta, HttpClientResponse } from './Response.js'; +export type { IncomingHttpHeaders } from './IncomingHttpHeaders.js'; export * from './HttpClientError.js'; export { FetchFactory, fetch } from './fetch.js'; export { FormData as WebFormData } from './FormData.js'; -export default { +const urllib: { + request: typeof request; + curl: typeof curl; + USER_AGENT: string; +} = { request, curl, USER_AGENT: HEADER_USER_AGENT, }; + +export default urllib; diff --git a/src/symbols.ts b/src/symbols.ts index 7890ff41..27774b82 100644 --- a/src/symbols.ts +++ b/src/symbols.ts @@ -1,4 +1,25 @@ -export default { +const symbols: { + kSocketId: symbol; + kSocketStartTime: symbol; + kSocketConnectedTime: symbol; + kSocketConnectErrorTime: symbol; + kSocketRequestEndTime: symbol; + kSocketLocalAddress: symbol; + kSocketLocalPort: symbol; + kSocketConnectHost: symbol; + kSocketConnectPort: symbol; + kSocketConnectProtocol: symbol; + kHandledRequests: symbol; + kHandledResponses: symbol; + kRequestSocket: symbol; + kRequestId: symbol; + kRequestStartTime: symbol; + kEnableRequestTiming: symbol; + kRequestTiming: symbol; + kRequestOriginalOpaque: symbol; + kRequestInternalOpaque: symbol; + kErrorSocket: symbol; +} = { kSocketId: Symbol('socket id'), kSocketStartTime: Symbol('socket start time'), kSocketConnectedTime: Symbol('socket connected time'), @@ -20,3 +41,5 @@ export default { kRequestInternalOpaque: Symbol('request internal opaque'), kErrorSocket: Symbol('socket of error'), }; + +export default symbols; diff --git a/src/utils.ts b/src/utils.ts index 603fbe53..56999d07 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -5,9 +5,9 @@ import { Readable } from 'node:stream'; import { ReadableStream, TransformStream } from 'node:stream/web'; import { toUSVString } from 'node:util'; -import { IncomingHttpHeaders } from './IncomingHttpHeaders.js'; +import type { IncomingHttpHeaders } from './IncomingHttpHeaders.js'; import type { FixJSONCtlChars } from './Request.js'; -import { SocketInfo } from './Response.js'; +import type { SocketInfo } from './Response.js'; import symbols from './symbols.js'; const JSONCtlCharsMap: Record = { @@ -30,7 +30,7 @@ function replaceJSONCtlChars(value: string) { return value.replace(JSONCtlCharsRE, replaceOneChar); } -export function parseJSON(data: string, fixJSONCtlChars?: FixJSONCtlChars) { +export function parseJSON(data: string, fixJSONCtlChars?: FixJSONCtlChars): unknown { if (typeof fixJSONCtlChars === 'function') { data = fixJSONCtlChars(data); } else if (fixJSONCtlChars) { @@ -60,7 +60,7 @@ export function parseJSON(data: string, fixJSONCtlChars?: FixJSONCtlChars) { return data; } -function md5(s: string) { +function md5(s: string): string { const sum = createHash('md5'); sum.update(s, 'utf8'); return sum.digest('hex'); @@ -70,7 +70,7 @@ const AUTH_KEY_VALUE_RE = /(\w{1,100})=["']?([^'"]+)["']?/; let NC = 0; const NC_PAD = '00000000'; -export function digestAuthHeader(method: string, uri: string, wwwAuthenticate: string, userpass: string) { +export function digestAuthHeader(method: string, uri: string, wwwAuthenticate: string, userpass: string): string { // WWW-Authenticate: Digest realm="testrealm@host.com", // qop="auth,auth-int", // nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", @@ -139,18 +139,18 @@ export function digestAuthHeader(method: string, uri: string, wwwAuthenticate: s const MAX_ID_VALUE = Math.pow(2, 31) - 10; const globalIds: Record = {}; -export function globalId(category: string) { +export function globalId(category: string): number { if (!globalIds[category] || globalIds[category] >= MAX_ID_VALUE) { globalIds[category] = 0; } return ++globalIds[category]; } -export function performanceTime(startTime: number, now?: number) { +export function performanceTime(startTime: number, now?: number): number { return Math.floor(((now ?? performance.now()) - startTime) * 1000) / 1000; } -export function isReadable(stream: any) { +export function isReadable(stream: any): boolean { if (typeof Readable.isReadable === 'function') return Readable.isReadable(stream); // patch from node // https://github.com/nodejs/node/blob/1287530385137dda1d44975063217ccf90759475/lib/internal/streams/utils.js#L119 @@ -165,7 +165,7 @@ export function isReadable(stream: any) { ); } -export function updateSocketInfo(socketInfo: SocketInfo, internalOpaque: any, err?: any) { +export function updateSocketInfo(socketInfo: SocketInfo, internalOpaque: any, err?: any): void { const socket = internalOpaque[symbols.kRequestSocket] ?? err?.[symbols.kErrorSocket]; if (socket) { @@ -218,7 +218,7 @@ export function convertHeader(headers: Headers): IncomingHttpHeaders { } // support require from Node.js 16 -export function patchForNode16() { +export function patchForNode16(): void { if (typeof global.ReadableStream === 'undefined') { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore diff --git a/test/HttpClient.test.ts b/test/HttpClient.test.ts index 72911b75..4b6e4c91 100644 --- a/test/HttpClient.test.ts +++ b/test/HttpClient.test.ts @@ -2,14 +2,15 @@ import { strict as assert } from 'node:assert'; import dns from 'node:dns'; import { once } from 'node:events'; import { sensitiveHeaders, createSecureServer } from 'node:http2'; -import { AddressInfo } from 'node:net'; +import type { AddressInfo } from 'node:net'; import { PerformanceObserver } from 'node:perf_hooks'; import { setTimeout as sleep } from 'node:timers/promises'; import selfsigned from 'selfsigned'; import { describe, it, beforeAll, afterAll } from 'vitest'; -import { HttpClient, RawResponseWithMeta, getGlobalDispatcher } from '../src/index.js'; +import { HttpClient, getGlobalDispatcher } from '../src/index.js'; +import type { RawResponseWithMeta } from '../src/index.js'; import { startServer } from './fixtures/server.js'; import { nodeMajorVersion } from './utils.js'; diff --git a/test/diagnostics_channel.test.ts b/test/diagnostics_channel.test.ts index 8d1377dc..7dd0fa6a 100644 --- a/test/diagnostics_channel.test.ts +++ b/test/diagnostics_channel.test.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'node:assert'; import diagnosticsChannel from 'node:diagnostics_channel'; import { once } from 'node:events'; import { createSecureServer } from 'node:http2'; -import { AddressInfo } from 'node:net'; +import type { AddressInfo } from 'node:net'; import { setTimeout as sleep } from 'node:timers/promises'; import selfsigned from 'selfsigned'; diff --git a/test/fetch.test.ts b/test/fetch.test.ts index b1d53d96..411f789a 100644 --- a/test/fetch.test.ts +++ b/test/fetch.test.ts @@ -5,8 +5,9 @@ import { setTimeout as sleep } from 'node:timers/promises'; import { Request } from 'undici'; import { describe, it, beforeAll, afterAll } from 'vitest'; -import { fetch, FetchDiagnosticsMessage, FetchFactory, FetchResponseDiagnosticsMessage } from '../src/fetch.js'; -import { RequestDiagnosticsMessage, ResponseDiagnosticsMessage } from '../src/HttpClient.js'; +import { fetch, FetchFactory } from '../src/fetch.js'; +import type { FetchDiagnosticsMessage, FetchResponseDiagnosticsMessage } from '../src/fetch.js'; +import type { RequestDiagnosticsMessage, ResponseDiagnosticsMessage } from '../src/HttpClient.js'; import { startServer } from './fixtures/server.js'; describe('fetch.test.ts', () => { diff --git a/test/fixtures/BufferStream.ts b/test/fixtures/BufferStream.ts index df60f8b3..78242f37 100644 --- a/test/fixtures/BufferStream.ts +++ b/test/fixtures/BufferStream.ts @@ -11,12 +11,12 @@ export class BufferStream extends Transform { this.realloc(); } - realloc() { + realloc(): void { this.buf = Buffer.alloc(BUF_SIZE); this.offset = 0; } - _transform(chunk: Buffer, _: any, callback: any) { + _transform(chunk: Buffer, _: any, callback: any): void { const currentLength = this.offset; const chunkSize = chunk.length; const newSize = currentLength + chunkSize; @@ -60,7 +60,7 @@ export class BufferStream extends Transform { return callback(null); } - _flush(callback: any) { + _flush(callback: any): void { if (this.offset) { const chunk = Buffer.alloc(this.offset); this.buf.copy(chunk); diff --git a/test/options.timeout.test.ts b/test/options.timeout.test.ts index 48848200..551f82ba 100644 --- a/test/options.timeout.test.ts +++ b/test/options.timeout.test.ts @@ -1,7 +1,7 @@ import { strict as assert } from 'node:assert'; import { once } from 'node:events'; import { createSecureServer } from 'node:http2'; -import { AddressInfo } from 'node:net'; +import type { AddressInfo } from 'node:net'; import selfsigned from 'selfsigned'; import { describe, it, beforeAll, afterAll } from 'vitest'; diff --git a/test/options.timing.test.ts b/test/options.timing.test.ts index 40811f89..9a92399d 100644 --- a/test/options.timing.test.ts +++ b/test/options.timing.test.ts @@ -3,7 +3,8 @@ import { setTimeout as sleep } from 'node:timers/promises'; import { describe, it, beforeAll, afterAll } from 'vitest'; -import urllib, { RawResponseWithMeta } from '../src/index.js'; +import urllib from '../src/index.js'; +import type { RawResponseWithMeta } from '../src/index.js'; import { startServer } from './fixtures/server.js'; describe('options.timing.test.ts', () => { diff --git a/test/urllib.options.rejectUnauthorized-false.test.ts b/test/urllib.options.rejectUnauthorized-false.test.ts index c64ede7c..62cb2547 100644 --- a/test/urllib.options.rejectUnauthorized-false.test.ts +++ b/test/urllib.options.rejectUnauthorized-false.test.ts @@ -1,7 +1,7 @@ import { strict as assert } from 'node:assert'; import { once } from 'node:events'; import { createSecureServer } from 'node:http2'; -import { AddressInfo } from 'node:net'; +import type { AddressInfo } from 'node:net'; import selfsigned from 'selfsigned'; import { describe, it, beforeAll, afterAll } from 'vitest'; diff --git a/test/utils.ts b/test/utils.ts index 589a71f7..bf1d621c 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -5,7 +5,7 @@ import { join } from 'node:path'; import { Readable } from 'node:stream'; import { ReadableStream } from 'node:stream/web'; -export async function readableToBytes(stream: Readable | ReadableStream) { +export async function readableToBytes(stream: Readable | ReadableStream): Promise { const chunks: Buffer[] = []; let chunk: Buffer; for await (chunk of stream) { @@ -14,12 +14,14 @@ export async function readableToBytes(stream: Readable | ReadableStream) { return Buffer.concat(chunks); } -export async function readableToString(stream: Readable | ReadableStream) { +export async function readableToString(stream: Readable | ReadableStream): Promise { const bytes = await readableToBytes(stream); return bytes.toString(); } -export async function createTempfile(content?: Buffer | string) { +export async function createTempfile( + content?: Buffer | string, +): Promise<{ tmpfile: string; cleanup: () => Promise }> { const tmpfile = join(tmpdir(), randomUUID()); if (typeof content === 'string') { content = Buffer.from(content); @@ -35,10 +37,10 @@ export async function createTempfile(content?: Buffer | string) { }; } -export function nodeMajorVersion() { +export function nodeMajorVersion(): number { return parseInt(process.versions.node.split('.')[0]); } -export function isWindows() { +export function isWindows(): boolean { return platform() === 'win32'; } diff --git a/tsconfig.json b/tsconfig.json index a83410c1..148d5b50 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,10 @@ "target": "ES2022", "module": "NodeNext", "moduleResolution": "NodeNext", + // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html#isolated-declarations + "isolatedDeclarations": true, + // verbatimModuleSyntax is incompatible with multi-dialect builds + // "verbatimModuleSyntax": true }, "exclude": ["test/fixtures/ts*"], } diff --git a/vite.config.ts b/vite.config.ts index 5dcbc4a8..b4ef3725 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,6 +1,7 @@ import { defineConfig } from 'vitest/config'; +import type { UserConfig } from 'vitest/config'; -export default defineConfig({ +const config: UserConfig = defineConfig({ test: { include: ['test/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], testTimeout: 60000, @@ -11,3 +12,5 @@ export default defineConfig({ setupFiles: ['test/setup.ts'], }, }); + +export default config;