import { t as Interceptor } from "../../interceptor-dtJZ_9QT.js"; import { TypedEvent } from "rettime"; import http from "node:http"; import net from "node:net"; import tls from "node:tls"; //#region src/interceptors/net/utils/normalize-net-connect-args.d.ts interface NetworkConnectionOptions { /** * @note The port may be a string when a URL is (incorrectly) passed * to `net.connect()`. Node.js reads URLs as plain options objects. */ port?: number | string | null; path: string | null; host?: string | null; protocol?: string | null; auth?: string | null; family?: number | null; hints?: number | null; session?: Buffer; localAddress?: string | null; localPort?: number | null; timeout?: number; lookup?: net.LookupFunction; allowHalfOpen?: boolean | null; noDelay?: boolean | null; keepAlive?: boolean | null; keepAliveInitialDelay?: number | null; autoSelectFamily?: boolean | null; autoSelectFamilyAttemptTimeout?: number | null; } //#endregion //#region src/interceptors/net/utils/normalize-tls-connect-args.d.ts type TlsConnectionOptions = tls.ConnectionOptions & NetworkConnectionOptions; //#endregion //#region src/interceptors/net/socket-controller.d.ts declare const kRawSocket: unique symbol; declare const kPatched: unique symbol; type OperationStatus = 0 | 1; declare module 'node:net' { interface Socket { [kPatched]?: boolean; _httpMessage?: object | null; _pendingData: string | Buffer | Array<{ chunk: string | Buffer; encoding?: BufferEncoding; callback?: (error?: Error | null) => void; }> | null; _pendingEncoding: BufferEncoding | ''; _bytesDispatched: number; _writeGeneric(writev: boolean, data: NonNullable, encoding: BufferEncoding, callback?: (error?: Error | null) => void): void; _handle: TcpHandle; _start: () => void; _unrefTimer: () => void; } } declare module 'node:tls' { interface TLSSocket { /** * Whether the handshake of this socket is still pending. */ secureConnecting: boolean; _handle: TcpHandle & { start: () => void; onhandshakedone: () => void; onnewsession: (sessionId: unknown, session: Buffer) => void; getSession: () => Buffer; isSessionReused: () => boolean; getServername: () => string; getALPNNegotiatedProtocol: () => string | false; getCipher: () => { name: string; standardName: string; version: string; }; getEphemeralKeyInfo: () => tls.EphemeralKeyInfo; verifyError: () => void; }; } } interface TcpHandle { open: (fd: unknown) => OperationStatus; connect: (request: TcpWrap, address: string, port: number) => void; connect6: (request: TcpWrap, address: string, port: number) => void; listen: (backlog: number) => OperationStatus; onconnection?: () => void; getpeername?: (addressInfo: ReturnType) => OperationStatus; getsockname?: (addressInfo: ReturnType) => OperationStatus; reading: boolean; onread: () => void; readStart: () => void; readStop: () => void; bytesRead: number; bytesWritten: number; ref?: () => void; unref?: () => void; hasRef?: () => boolean; fchmod: (mode: number) => void; setBlocking: (blocking: boolean) => OperationStatus; setNoDelay?: (noDelay: boolean) => void; setKeepAlive?: (keepAlive: boolean, initialDelay: number) => void; setTypeOfService?: (tos: number) => OperationStatus; shutdown: (reqest: unknown) => OperationStatus; close: () => void; _parent?: TcpHandle; } interface TcpWrap { oncomplete: (status: OperationStatus, owner: TcpHandle, request: TcpWrap, readable?: boolean, writable?: boolean) => void; } declare abstract class SocketController { static PENDING: 0; static CLAIMED: 1; static PASSTHROUGH: 2; readyState: typeof SocketController.PENDING | typeof SocketController.CLAIMED | typeof SocketController.PASSTHROUGH; private [kRawSocket]; constructor(socket: net.Socket); /** * Claim this socket. Once claimed, the connection attempt succeeds * regardless of the requested host and the interceptor becomes the * mocked server for this connection. */ claim(): void; /** * Establish this socket connection as-is. */ passthrough(): void; } type FlushPendingDataFunction = (data: NonNullable, encoding: BufferEncoding | undefined, callback: (data: NonNullable) => void) => void; declare class TcpSocketController extends SocketController { #private; protected readonly socket: net.Socket; protected readonly createConnection: () => net.Socket; serverSocket: net.Socket; protected pendingConnection: PromiseWithResolvers<[TcpWrap, TcpHandle]>; constructor(socket: net.Socket, createConnection: () => net.Socket, connectionOptions?: NetworkConnectionOptions); /** * Reset this controller to the pending state so the next exchange * on this socket can be handled anew. This is meant for kept-alive * sockets that are reused for multiple exchanges by clients that * don't emit the "free" event on the socket (e.g. Undici). */ reset(): void; /** * Retarget this connection: the exchanges that follow belong to the * given target (e.g. the authority of an established "CONNECT" * tunnel) and are handled anew. An unclaimed exchange then passes * through to that target instead of the originally dialed one, and * a claimed exchange reports it as the peer. */ retarget(connectionOptions: NetworkConnectionOptions): void; /** * The options of the connection this socket currently represents * (the retargeted ones once retargeted, see `retarget()`). */ get connectionOptions(): NetworkConnectionOptions | undefined; /** * Create the transport for a protocol layered over this socket * (e.g. "tls.connect({ socket })"). A connection passed through to * its target carries the layered protocol as-is (e.g. a tunnel * established by a real proxy). Otherwise, the target is dialed * directly: no real connection to it exists (e.g. a tunnel this * interceptor established). */ createTransport(): net.Socket; /** * Schedule a reset of this controller to happen right before the * next client write. The consumer signals the boundary of the * current exchange (e.g. an HTTP message boundary) the moment it is * parsed — mid-delivery of the exchange's final chunk — when an * immediate reset would discard that chunk. Deferring the reset to * the next write lets the current exchange settle as-is while the * next exchange's first write already buffers for a new verdict * (instead of following the previous one, e.g. leaking to the * passthrough connection). */ scheduleReset(): void; /** * Emulate the connection notification if the socket is still * pending after its connection request, has no writes buffered, * and its client appears to wait for that notification. */ protected emulateConnectIfIdle(): void; /** * Whether the client appears to wait for the connection * notification before writing (e.g. Undici). */ protected isAwaitingConnect(): boolean; protected emulateConnect(): void; /** * Invoke the callback once this claimed socket is connected: upon * the mocked connection completing, or right away for a socket * that is already connected (e.g. a kept-alive socket reused for * the next exchange, a TLS socket over a connected transport). */ protected whenConnected(callback: () => void): void; /** * Suspend forwarding of the passthrough socket events ("data", "end", "close") * to the client socket. The events are buffered in order until `uncorkReads()` * is called. This allows the consumer to delay the delivery of the original * response to the client (e.g. until its own asynchronous logic settles). * * @note Pausing the client socket is not enough to delay the delivery. * Consumers like Undici read the pushed data from a paused socket * directly via `socket.read()`, which is unaffected by `socket.pause()`. */ corkReads(): void; /** * Resume forwarding of the passthrough socket events to the client socket, * replaying any events buffered while the reads were corked. */ uncorkReads(): void; claim(): void; passthrough(flushPendingData?: FlushPendingDataFunction): net.Socket; /** * Forward events for the lifetime of the connection, including while * it is idle in an agent pool. Reusing it must not add more listeners. */ protected addPassthroughSocketListeners(realSocket: net.Socket): () => void; } declare class TlsSocketController extends TcpSocketController { #private; protected readonly socket: tls.TLSSocket; protected readonly createConnection: () => tls.TLSSocket; constructor(socket: tls.TLSSocket, createConnection: () => tls.TLSSocket, tlsConnectionOptions?: TlsConnectionOptions); protected emulateConnect(): void; protected isAwaitingConnect(): boolean; claim(): void; passthrough(flushPendingData?: FlushPendingDataFunction): tls.TLSSocket; protected addPassthroughSocketListeners(realSocket: net.Socket): () => void; } //#endregion //#region src/utils/internal-connection.d.ts interface InternalConnectionContext { run(callback: () => T): T; consume(): boolean; } declare global { var __MSW_INTERNAL_CONNECTION_CONTEXT: InternalConnectionContext | undefined; } //#endregion //#region src/interceptors/net/index.d.ts declare module 'node:tls' { interface TLSSocket { /** * @note Wraps the given transport's handle (or a fresh one, if * none is given) into the TLS handle of this socket. */ _wrapHandle: (wrap: net.Socket | null, handle: TcpHandle | undefined, wrapHasActiveWriteFromPrevOwner: boolean) => TcpHandle; } } declare module 'node:http' { interface Agent { /** * @note An undocumented method backing every agent-driven request * (see "#stopReusingUnpatchedSockets"). */ addRequest?: (request: http.ClientRequest, ...args: Array) => void; } } interface SocketConnectionEventData { socket: net.Socket | tls.TLSSocket; connectionOptions: NetworkConnectionOptions; controller: TcpSocketController | TlsSocketController; } declare class SocketConnectionEvent extends TypedEvent { socket: net.Socket | tls.TLSSocket; connectionOptions: NetworkConnectionOptions; controller: TcpSocketController | TlsSocketController; constructor(data: DataType); } type SocketEventMap = { connection: SocketConnectionEvent; }; /** * Interceptor for `net.Socket` connections. */ export declare class SocketInterceptor extends Interceptor { #private; static symbol: symbol; protected predicate(): boolean; protected setup(): void; } //#endregion //# sourceMappingURL=index.d.ts.map