Skip to content

Commit

Permalink
src: add .opened promise
Browse files Browse the repository at this point in the history
  • Loading branch information
flakey5 committed Nov 3, 2023
1 parent b7f050e commit 1b21755
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 6 deletions.
45 changes: 40 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import net from 'node:net';
import tls from 'node:tls';
import { Duplex } from 'node:stream';
import type { ReadableStream, WritableStream } from 'node:stream/web';
import type { SocketAddress, SocketOptions } from './types';
import type { SocketAddress, SocketInfo, SocketOptions } from './types';
import { isSocketAddress } from './is-socket-address';

export function connect(
Expand All @@ -23,11 +23,15 @@ export function connect(
export class Socket {
readable: ReadableStream<unknown>;
writable: WritableStream<unknown>;
opened: Promise<SocketInfo>;
closed: Promise<void>;

private socket: net.Socket | tls.TLSSocket;
private allowHalfOpen: boolean;
private secureTransport: SocketOptions['secureTransport'];
private openedIsResolved: boolean;
private openedResolve!: (info: SocketInfo) => void;
private openedReject!: (reason?: unknown) => void;
private closedResolve!: () => void;
private closedReject!: (reason?: unknown) => void;
private startTlsCalled = false;
Expand All @@ -39,6 +43,19 @@ export class Socket {
this.secureTransport = options?.secureTransport ?? 'off';
this.allowHalfOpen = options?.allowHalfOpen ?? true;

this.openedIsResolved = false;
this.opened = new Promise((resolve, reject) => {
this.openedResolve = (info): void => {
this.openedIsResolved = true;
resolve(info);
};
this.openedReject = (...args): void => {
this.openedIsResolved = true;
// eslint-disable-next-line prefer-promise-reject-errors -- ESLint gets this wrong as we are completely forwarding the arguments to reject.
reject(...args);
};
});

this.closed = new Promise((resolve, reject) => {
this.closedResolve = (...args): void => {
resolve(...args);
Expand All @@ -64,18 +81,36 @@ export class Socket {
this.socket = new tls.TLSSocket(addressOrSocket);
}

if (this.socket instanceof tls.TLSSocket) {
this.socket.on('secureConnection', () => {
this.openedResolve({
remoteAddress: this.socket.remoteAddress,
localAddress: this.socket.localAddress,
});
});
} else {
this.socket.on('connection', () => {
this.openedResolve({
remoteAddress: this.socket.remoteAddress,
localAddress: this.socket.localAddress,
});
});
}

this.socket.on('close', (hadError) => {
if (!hadError) {
this.closedResolve();
}
});

this.socket.on('error', (err) => {
if (err instanceof Error) {
this.closedReject(new SocketError(err.message));
} else {
this.closedReject(new SocketError(err as string));
const socketError = new SocketError(
err instanceof Error ? err.message : (err as string),
);
if (!this.openedIsResolved) {
this.openedReject(socketError);
}
this.closedReject(socketError);
});

// types are wrong. fixed based on docs https://nodejs.org/dist/latest/docs/api/stream.html#streamduplextowebstreamduplex
Expand Down
5 changes: 5 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ export interface SocketAddress {
/** The port number to connect to. Example: `5432`. */
port: number;
}

export interface SocketInfo {
remoteAddress?: string;
localAddress?: string;
}
4 changes: 3 additions & 1 deletion test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
void tap.test(
'Socket connected to tcp server with secureTransport: off',
async (t) => {
t.plan(6);
t.plan(7);
let connectCount = 0;
const message = 'abcde\r\n';

Expand All @@ -38,6 +38,8 @@ void tap.test(
'should pipe message',
);

await t.resolveMatch(socket.opened, { localAddress: '127.0.0.1' });

const close = socket.close();
t.equal(
socket.closed,
Expand Down

0 comments on commit 1b21755

Please sign in to comment.