@ac-kit/node 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +28 -0
- package/README.md +39 -0
- package/dist/child-process/exec-async.d.ts +24 -0
- package/dist/child-process/exec-async.d.ts.map +1 -0
- package/dist/child-process/exec-async.js +33 -0
- package/dist/child-process/exec-async.js.map +1 -0
- package/dist/error/node-aggregate-error.d.ts +18 -0
- package/dist/error/node-aggregate-error.d.ts.map +1 -0
- package/dist/error/node-aggregate-error.js +13 -0
- package/dist/error/node-aggregate-error.js.map +1 -0
- package/dist/error/node-error.d.ts +26 -0
- package/dist/error/node-error.d.ts.map +1 -0
- package/dist/error/node-error.js +21 -0
- package/dist/error/node-error.js.map +1 -0
- package/dist/error/node-exec-error.d.ts +21 -0
- package/dist/error/node-exec-error.d.ts.map +1 -0
- package/dist/error/node-exec-error.js +17 -0
- package/dist/error/node-exec-error.js.map +1 -0
- package/dist/error/node-system-error.d.ts +46 -0
- package/dist/error/node-system-error.d.ts.map +1 -0
- package/dist/error/node-system-error.js +35 -0
- package/dist/error/node-system-error.js.map +1 -0
- package/dist/error/process-exit-error.d.ts +22 -0
- package/dist/error/process-exit-error.d.ts.map +1 -0
- package/dist/error/process-exit-error.js +46 -0
- package/dist/error/process-exit-error.js.map +1 -0
- package/dist/fs/compress-file.d.ts +42 -0
- package/dist/fs/compress-file.d.ts.map +1 -0
- package/dist/fs/compress-file.js +72 -0
- package/dist/fs/compress-file.js.map +1 -0
- package/dist/fs/create-temp-dir.d.ts +13 -0
- package/dist/fs/create-temp-dir.d.ts.map +1 -0
- package/dist/fs/create-temp-dir.js +18 -0
- package/dist/fs/create-temp-dir.js.map +1 -0
- package/dist/fs/escape-path.d.ts +19 -0
- package/dist/fs/escape-path.d.ts.map +1 -0
- package/dist/fs/escape-path.js +20 -0
- package/dist/fs/escape-path.js.map +1 -0
- package/dist/fs/exists-async.d.ts +9 -0
- package/dist/fs/exists-async.d.ts.map +1 -0
- package/dist/fs/exists-async.js +17 -0
- package/dist/fs/exists-async.js.map +1 -0
- package/dist/fs/file-content-equal.d.ts +18 -0
- package/dist/fs/file-content-equal.d.ts.map +1 -0
- package/dist/fs/file-content-equal.js +50 -0
- package/dist/fs/file-content-equal.js.map +1 -0
- package/dist/fs/is-directory-async.d.ts +11 -0
- package/dist/fs/is-directory-async.d.ts.map +1 -0
- package/dist/fs/is-directory-async.js +18 -0
- package/dist/fs/is-directory-async.js.map +1 -0
- package/dist/fs/types.d.ts +19 -0
- package/dist/fs/types.d.ts.map +1 -0
- package/dist/fs/types.js +23 -0
- package/dist/fs/types.js.map +1 -0
- package/dist/fs/walk-paths.d.ts +108 -0
- package/dist/fs/walk-paths.d.ts.map +1 -0
- package/dist/fs/walk-paths.js +197 -0
- package/dist/fs/walk-paths.js.map +1 -0
- package/dist/fs/write-file-atomic.d.ts +42 -0
- package/dist/fs/write-file-atomic.d.ts.map +1 -0
- package/dist/fs/write-file-atomic.js +126 -0
- package/dist/fs/write-file-atomic.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/module/import-module.d.ts +13 -0
- package/dist/module/import-module.d.ts.map +1 -0
- package/dist/module/import-module.js +18 -0
- package/dist/module/import-module.js.map +1 -0
- package/dist/module/optional-import.d.ts +19 -0
- package/dist/module/optional-import.d.ts.map +1 -0
- package/dist/module/optional-import.js +30 -0
- package/dist/module/optional-import.js.map +1 -0
- package/dist/module/resolve-module.d.ts +13 -0
- package/dist/module/resolve-module.d.ts.map +1 -0
- package/dist/module/resolve-module.js +26 -0
- package/dist/module/resolve-module.js.map +1 -0
- package/dist/net/dgram-socket.d.ts +235 -0
- package/dist/net/dgram-socket.d.ts.map +1 -0
- package/dist/net/dgram-socket.js +341 -0
- package/dist/net/dgram-socket.js.map +1 -0
- package/dist/net/ipc-socket.d.ts +34 -0
- package/dist/net/ipc-socket.d.ts.map +1 -0
- package/dist/net/ipc-socket.js +63 -0
- package/dist/net/ipc-socket.js.map +1 -0
- package/dist/net/stream-socket.d.ts +156 -0
- package/dist/net/stream-socket.d.ts.map +1 -0
- package/dist/net/stream-socket.js +188 -0
- package/dist/net/stream-socket.js.map +1 -0
- package/dist/net/tcp-server.d.ts +110 -0
- package/dist/net/tcp-server.d.ts.map +1 -0
- package/dist/net/tcp-server.js +198 -0
- package/dist/net/tcp-server.js.map +1 -0
- package/dist/net/tcp-socket.d.ts +87 -0
- package/dist/net/tcp-socket.d.ts.map +1 -0
- package/dist/net/tcp-socket.js +153 -0
- package/dist/net/tcp-socket.js.map +1 -0
- package/dist/net/tls-socket.d.ts +45 -0
- package/dist/net/tls-socket.d.ts.map +1 -0
- package/dist/net/tls-socket.js +148 -0
- package/dist/net/tls-socket.js.map +1 -0
- package/dist/process/fork-process.d.ts +63 -0
- package/dist/process/fork-process.d.ts.map +1 -0
- package/dist/process/fork-process.js +98 -0
- package/dist/process/fork-process.js.map +1 -0
- package/dist/process/guarded.d.ts +12 -0
- package/dist/process/guarded.d.ts.map +1 -0
- package/dist/process/guarded.js +25 -0
- package/dist/process/guarded.js.map +1 -0
- package/dist/process/spawn-process.d.ts +37 -0
- package/dist/process/spawn-process.d.ts.map +1 -0
- package/dist/process/spawn-process.js +73 -0
- package/dist/process/spawn-process.js.map +1 -0
- package/dist/process/spawned-process.d.ts +102 -0
- package/dist/process/spawned-process.d.ts.map +1 -0
- package/dist/process/spawned-process.js +226 -0
- package/dist/process/spawned-process.js.map +1 -0
- package/dist/process/start-process.d.ts +54 -0
- package/dist/process/start-process.d.ts.map +1 -0
- package/dist/process/start-process.js +73 -0
- package/dist/process/start-process.js.map +1 -0
- package/dist/shell/escape-command-arg.d.ts +9 -0
- package/dist/shell/escape-command-arg.d.ts.map +1 -0
- package/dist/shell/escape-command-arg.js +13 -0
- package/dist/shell/escape-command-arg.js.map +1 -0
- package/dist/shell/escape-command.d.ts +10 -0
- package/dist/shell/escape-command.d.ts.map +1 -0
- package/dist/shell/escape-command.js +12 -0
- package/dist/shell/escape-command.js.map +1 -0
- package/dist/stream/non-closing-writable-stream.d.ts +14 -0
- package/dist/stream/non-closing-writable-stream.d.ts.map +1 -0
- package/dist/stream/non-closing-writable-stream.js +20 -0
- package/dist/stream/non-closing-writable-stream.js.map +1 -0
- package/dist/stream/write-async.d.ts +12 -0
- package/dist/stream/write-async.d.ts.map +1 -0
- package/dist/stream/write-async.js +22 -0
- package/dist/stream/write-async.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import * as net from "node:net";
|
|
2
|
+
import { EventDispatcherMapBase } from "@ac-kit/async";
|
|
3
|
+
/**
|
|
4
|
+
* Base class for stream-oriented client sockets.
|
|
5
|
+
*
|
|
6
|
+
* This abstraction wraps a {@link net.Socket} instance and exposes:
|
|
7
|
+
*
|
|
8
|
+
* - A stable, duplex {@link stream} for reading and writing data.
|
|
9
|
+
* - Common lifecycle properties such as {@link closed}, {@link destroyed},
|
|
10
|
+
* {@link bytesRead}, {@link bytesWritten} and {@link connecting}.
|
|
11
|
+
* - Timeout management via the {@link timeout} property.
|
|
12
|
+
* - Promise-based {@link end} and {@link write} helpers.
|
|
13
|
+
* - Strongly-typed lifecycle events via {@link StreamSocketEvents}.
|
|
14
|
+
*
|
|
15
|
+
* It is intentionally transport-agnostic: it does not assume a particular
|
|
16
|
+
* address family or protocol. Concrete subclasses such as {@link TcpSocket} add
|
|
17
|
+
* protocol-specific concerns (for example `InetEndpoint` accessors, TCP
|
|
18
|
+
* keep-alive configuration, or DNS resolution events) on top of this base.
|
|
19
|
+
*
|
|
20
|
+
* Unless explicitly documented otherwise, methods mirror the semantics of their
|
|
21
|
+
* underlying {@link net.Socket} counterparts.
|
|
22
|
+
*/
|
|
23
|
+
export class StreamSocket extends EventDispatcherMapBase {
|
|
24
|
+
sock;
|
|
25
|
+
handledErrorEvents = new Set();
|
|
26
|
+
/**
|
|
27
|
+
* Creates a new {@link StreamSocket} instance.
|
|
28
|
+
*
|
|
29
|
+
* @param options Options for creating the underlying Node.js socket.
|
|
30
|
+
* @returns A new `StreamSocket` instance.
|
|
31
|
+
*/
|
|
32
|
+
static from(options) {
|
|
33
|
+
return new StreamSocket(new net.Socket(options));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates a new {@link StreamSocket} instance.
|
|
37
|
+
*
|
|
38
|
+
* @param sock The underlying Node.js socket.
|
|
39
|
+
*/
|
|
40
|
+
constructor(sock) {
|
|
41
|
+
super();
|
|
42
|
+
this.sock = sock;
|
|
43
|
+
this.setupEventForwarding();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Underlying duplex stream for reading and writing data.
|
|
47
|
+
*
|
|
48
|
+
* This is the wrapped {@link net.Socket} instance and can be passed directly
|
|
49
|
+
* to APIs that expect a Node.js stream.
|
|
50
|
+
*/
|
|
51
|
+
get stream() {
|
|
52
|
+
return this.sock;
|
|
53
|
+
}
|
|
54
|
+
/** Indicates whether the socket has been fully closed. */
|
|
55
|
+
get closed() {
|
|
56
|
+
return this.sock.closed;
|
|
57
|
+
}
|
|
58
|
+
/** Indicates whether the underlying socket has been destroyed. */
|
|
59
|
+
get destroyed() {
|
|
60
|
+
return this.sock.destroyed;
|
|
61
|
+
}
|
|
62
|
+
/** Total number of bytes read from the socket so far. */
|
|
63
|
+
get bytesRead() {
|
|
64
|
+
return this.sock.bytesRead;
|
|
65
|
+
}
|
|
66
|
+
/** Total number of bytes written to the socket so far. */
|
|
67
|
+
get bytesWritten() {
|
|
68
|
+
return this.sock.bytesWritten;
|
|
69
|
+
}
|
|
70
|
+
/** Whether the socket is currently in the process of connecting. */
|
|
71
|
+
get connecting() {
|
|
72
|
+
return this.sock.connecting;
|
|
73
|
+
}
|
|
74
|
+
/** Current inactivity timeout in milliseconds, or `null` if disabled. */
|
|
75
|
+
get timeout() {
|
|
76
|
+
return this.sock.timeout ?? null;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Updates the inactivity timeout for the socket.
|
|
80
|
+
*
|
|
81
|
+
* When set to a positive number, the socket emits a "timeout" event if no I/O
|
|
82
|
+
* activity occurs within the given number of milliseconds. A value of `0` or
|
|
83
|
+
* `null` disables the timeout entirely.
|
|
84
|
+
*/
|
|
85
|
+
set timeout(timeout) {
|
|
86
|
+
this.sock.setTimeout(timeout ?? 0);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Marks the socket as referenced, preventing the Node.js process from exiting
|
|
90
|
+
* while the socket is active.
|
|
91
|
+
*/
|
|
92
|
+
ref() {
|
|
93
|
+
this.sock.ref();
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Marks the socket as unreferenced, allowing the Node.js process to exit even
|
|
97
|
+
* if the socket is still active.
|
|
98
|
+
*/
|
|
99
|
+
unref() {
|
|
100
|
+
this.sock.unref();
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Half-closes the socket, optionally waiting for a full close.
|
|
104
|
+
*
|
|
105
|
+
* If `waitForClose` is omitted or `false`, the promise resolves once the
|
|
106
|
+
* local side has finished sending data and the FIN has been queued. When
|
|
107
|
+
* `waitForClose` is `true`, the promise resolves only after the remote side
|
|
108
|
+
* has also closed and the "close" event has fired.
|
|
109
|
+
*
|
|
110
|
+
* @param options Optional settings for ending the socket.
|
|
111
|
+
* @returns A promise that resolves once the socket has ended.
|
|
112
|
+
*/
|
|
113
|
+
end(options) {
|
|
114
|
+
return new Promise((resolve, reject) => {
|
|
115
|
+
const handleError = (error) => {
|
|
116
|
+
this.handledErrorEvents.add(error);
|
|
117
|
+
reject(error);
|
|
118
|
+
};
|
|
119
|
+
const handleEnd = () => {
|
|
120
|
+
this.sock.removeListener("error", handleError);
|
|
121
|
+
resolve();
|
|
122
|
+
};
|
|
123
|
+
this.sock.prependOnceListener("error", handleError);
|
|
124
|
+
if (options?.waitForClose && !this.sock.closed) {
|
|
125
|
+
this.sock.prependOnceListener("close", () => {
|
|
126
|
+
this.sock.removeListener("error", handleError);
|
|
127
|
+
resolve();
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
this.sock.end(options?.waitForClose && !this.sock.closed ? undefined : handleEnd);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Writes data to the socket and resolves once that chunk has been flushed.
|
|
135
|
+
*
|
|
136
|
+
* Awaiting the result is what applies backpressure: the promise settles on
|
|
137
|
+
* the chunk's own flush rather than on the whole buffer draining, so a
|
|
138
|
+
* producer that awaits each write never outruns the socket. A caller that
|
|
139
|
+
* does not await is free to queue without bound.
|
|
140
|
+
*
|
|
141
|
+
* @param data The data to write.
|
|
142
|
+
* @throws When the socket errors or is destroyed before the chunk flushes.
|
|
143
|
+
*/
|
|
144
|
+
write(data) {
|
|
145
|
+
return new Promise((resolve, reject) => {
|
|
146
|
+
const callback = (error) => {
|
|
147
|
+
if (error) {
|
|
148
|
+
reject(error);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
resolve();
|
|
152
|
+
};
|
|
153
|
+
this.sock.write(data, callback);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Immediately destroys the underlying socket.
|
|
158
|
+
*
|
|
159
|
+
* Pending I/O is discarded, the connection is closed and the socket
|
|
160
|
+
* transitions to a terminal state. Any registered "close" listeners will
|
|
161
|
+
* still be invoked.
|
|
162
|
+
*/
|
|
163
|
+
destroy() {
|
|
164
|
+
this.sock.destroy();
|
|
165
|
+
}
|
|
166
|
+
setupEventForwarding() {
|
|
167
|
+
this.sock.on("error", (err) => {
|
|
168
|
+
if (this.handledErrorEvents.has(err)) {
|
|
169
|
+
this.handledErrorEvents.delete(err);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
this.dispatch("error", [err]);
|
|
173
|
+
});
|
|
174
|
+
this.sock.on("close", (hadError) => {
|
|
175
|
+
this.dispatch("close", [hadError]);
|
|
176
|
+
});
|
|
177
|
+
this.sock.on("connect", () => {
|
|
178
|
+
this.dispatch("connect", []);
|
|
179
|
+
});
|
|
180
|
+
this.sock.on("ready", () => {
|
|
181
|
+
this.dispatch("ready", []);
|
|
182
|
+
});
|
|
183
|
+
this.sock.on("timeout", () => {
|
|
184
|
+
this.dispatch("timeout", []);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=stream-socket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-socket.js","sourceRoot":"","sources":["../../src/net/stream-socket.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import * as net from "node:net";
|
|
2
|
+
import { EventDispatcherMapBase, IEventDispatcherMap } from "@ac-kit/async";
|
|
3
|
+
import { InetEndpoint, type IError } from "@ac-kit/core";
|
|
4
|
+
import type { Except } from "type-fest";
|
|
5
|
+
import { TcpSocket } from "./tcp-socket.js";
|
|
6
|
+
/** Event map for TcpServer server-specific events. */
|
|
7
|
+
export type TcpServerEvents = {
|
|
8
|
+
/** Emitted when the server closes. */
|
|
9
|
+
close: [];
|
|
10
|
+
/**
|
|
11
|
+
* Emitted when a new connection is made. The connection is wrapped in a
|
|
12
|
+
* TcpClient instance.
|
|
13
|
+
*/
|
|
14
|
+
connection: [client: TcpSocket];
|
|
15
|
+
/**
|
|
16
|
+
* Emitted when a new connection is dropped. Provides the local and remote
|
|
17
|
+
* endpoint information of the dropped connection.
|
|
18
|
+
*/
|
|
19
|
+
drop: [
|
|
20
|
+
localEndpoint: InetEndpoint | null,
|
|
21
|
+
remoteEndpoint: InetEndpoint | null
|
|
22
|
+
];
|
|
23
|
+
/** Emitted when an error occurs. */
|
|
24
|
+
error: [err: IError];
|
|
25
|
+
/** Emitted when the server has been bound after calling server.listen(). */
|
|
26
|
+
listening: [];
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* TCP server to accept incoming connections.
|
|
30
|
+
*
|
|
31
|
+
* Example usage:
|
|
32
|
+
*
|
|
33
|
+
* ```ts
|
|
34
|
+
* const server = TcpServer.from();
|
|
35
|
+
* server.on("connection", (client) => {
|
|
36
|
+
* console.log("Client connected");
|
|
37
|
+
* client.stream.on("data", (data) => {
|
|
38
|
+
* console.log("Received:", data.toString());
|
|
39
|
+
* });
|
|
40
|
+
* });
|
|
41
|
+
* await server.listen(8080, "0.0.0.0");
|
|
42
|
+
* // ... later
|
|
43
|
+
* await server.close();
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare class TcpServer extends EventDispatcherMapBase<TcpServerEvents> implements IEventDispatcherMap<TcpServerEvents> {
|
|
47
|
+
private readonly srv;
|
|
48
|
+
/**
|
|
49
|
+
* Creates a new `TcpServer` instance with the specified options.
|
|
50
|
+
*
|
|
51
|
+
* @param options Options for creating the TCP server.
|
|
52
|
+
* @returns A new `TcpServer` instance.
|
|
53
|
+
*/
|
|
54
|
+
static from(options?: net.ServerOpts): TcpServer;
|
|
55
|
+
private readonly handledErrorEvents;
|
|
56
|
+
constructor(srv: net.Server);
|
|
57
|
+
/**
|
|
58
|
+
* Gets the current number of concurrent connections on the server.
|
|
59
|
+
*
|
|
60
|
+
* @returns A promise that resolves with the connection count.
|
|
61
|
+
*/
|
|
62
|
+
getConnections(): Promise<number>;
|
|
63
|
+
/** Gets whether the server is currently listening for connections. */
|
|
64
|
+
get listening(): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Sets the maximum number of queued pending connections.
|
|
67
|
+
*
|
|
68
|
+
* @param maxConnections The maximum number of connections to queue.
|
|
69
|
+
*/
|
|
70
|
+
set maxConnections(maxConnections: number);
|
|
71
|
+
/** Gets the maximum number of queued pending connections. */
|
|
72
|
+
get maxConnections(): number;
|
|
73
|
+
/**
|
|
74
|
+
* References the server, preventing the process from exiting while the server
|
|
75
|
+
* is active.
|
|
76
|
+
*/
|
|
77
|
+
ref(): void;
|
|
78
|
+
/**
|
|
79
|
+
* Unreferences the server, allowing the process from exiting even if the
|
|
80
|
+
* server is active.
|
|
81
|
+
*/
|
|
82
|
+
unref(): void;
|
|
83
|
+
/**
|
|
84
|
+
* Starts the TCP server listening on the specified port and host.
|
|
85
|
+
*
|
|
86
|
+
* @param port The port to listen on. If 0, a random available port will be
|
|
87
|
+
* assigned.
|
|
88
|
+
* @param host The host/interface to bind to. Defaults to '::' (IPv6) or
|
|
89
|
+
* '0.0.0.0' (IPv4).
|
|
90
|
+
* @param options Additional listen options.
|
|
91
|
+
* @returns A promise that resolves when the server is successfully listening.
|
|
92
|
+
*/
|
|
93
|
+
listen(port: number, host?: string, options?: Except<net.ListenOptions, "port" | "host">): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Closes the TCP server, stopping it from accepting new connections. Existing
|
|
96
|
+
* connections are not automatically closed.
|
|
97
|
+
*
|
|
98
|
+
* @returns A promise that resolves when the server is fully closed.
|
|
99
|
+
*/
|
|
100
|
+
close(): Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Gets the address information of the server.
|
|
103
|
+
*
|
|
104
|
+
* @returns The server's endpoint information or null if the server is not
|
|
105
|
+
* listening.
|
|
106
|
+
*/
|
|
107
|
+
address(): InetEndpoint | null;
|
|
108
|
+
private setupEventForwarding;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=tcp-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tcp-server.d.ts","sourceRoot":"","sources":["../../src/net/tcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAEhC,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAEN,YAAY,EAEZ,KAAK,MAAM,EACX,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,sDAAsD;AACtD,MAAM,MAAM,eAAe,GAAG;IAC7B,sCAAsC;IACtC,KAAK,EAAE,EAAE,CAAC;IAEV;;;OAGG;IACH,UAAU,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAEhC;;;OAGG;IACH,IAAI,EAAE;QACL,aAAa,EAAE,YAAY,GAAG,IAAI;QAClC,cAAc,EAAE,YAAY,GAAG,IAAI;KACnC,CAAC;IAEF,oCAAoC;IACpC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAErB,4EAA4E;IAC5E,SAAS,EAAE,EAAE,CAAC;CACd,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,SACZ,SAAQ,sBAAsB,CAAC,eAAe,CAC9C,YAAW,mBAAmB,CAAC,eAAe,CAAC;IAcnC,OAAO,CAAC,QAAQ,CAAC,GAAG;IAZhC;;;;;OAKG;IACH,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,UAAU,GAAG,SAAS,CAE/C;IAED,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA0B;IAE7D,YAA6B,GAAG,EAAE,GAAG,CAAC,MAAM,EAG3C;IAED;;;;OAIG;IACH,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAUhC;IAED,sEAAsE;IACtE,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;;;OAIG;IACH,IAAI,cAAc,CAAC,cAAc,EAAE,MAAM,EAExC;IAED,6DAA6D;IAC7D,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED;;;OAGG;IACH,GAAG,IAAI,IAAI,CAEV;IAED;;;OAGG;IACH,KAAK,IAAI,IAAI,CAEZ;IAED;;;;;;;;;OASG;IACH,MAAM,CACL,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAAC,GAClD,OAAO,CAAC,IAAI,CAAC,CAoBf;IAED;;;;;OAKG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAUrB;IAED;;;;;OAKG;IACH,OAAO,IAAI,YAAY,GAAG,IAAI,CAiB7B;IAED,OAAO,CAAC,oBAAoB;CAsD5B"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import * as net from "node:net";
|
|
2
|
+
import { EventDispatcherMapBase } from "@ac-kit/async";
|
|
3
|
+
import { composeInetAddress, UnsupportedError, } from "@ac-kit/core";
|
|
4
|
+
import { TcpSocket } from "./tcp-socket.js";
|
|
5
|
+
/**
|
|
6
|
+
* TCP server to accept incoming connections.
|
|
7
|
+
*
|
|
8
|
+
* Example usage:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* const server = TcpServer.from();
|
|
12
|
+
* server.on("connection", (client) => {
|
|
13
|
+
* console.log("Client connected");
|
|
14
|
+
* client.stream.on("data", (data) => {
|
|
15
|
+
* console.log("Received:", data.toString());
|
|
16
|
+
* });
|
|
17
|
+
* });
|
|
18
|
+
* await server.listen(8080, "0.0.0.0");
|
|
19
|
+
* // ... later
|
|
20
|
+
* await server.close();
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export class TcpServer extends EventDispatcherMapBase {
|
|
24
|
+
srv;
|
|
25
|
+
/**
|
|
26
|
+
* Creates a new `TcpServer` instance with the specified options.
|
|
27
|
+
*
|
|
28
|
+
* @param options Options for creating the TCP server.
|
|
29
|
+
* @returns A new `TcpServer` instance.
|
|
30
|
+
*/
|
|
31
|
+
static from(options) {
|
|
32
|
+
return new TcpServer(net.createServer(options));
|
|
33
|
+
}
|
|
34
|
+
handledErrorEvents = new Set();
|
|
35
|
+
constructor(srv) {
|
|
36
|
+
super();
|
|
37
|
+
this.srv = srv;
|
|
38
|
+
this.setupEventForwarding();
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Gets the current number of concurrent connections on the server.
|
|
42
|
+
*
|
|
43
|
+
* @returns A promise that resolves with the connection count.
|
|
44
|
+
*/
|
|
45
|
+
getConnections() {
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
this.srv.getConnections((error, count) => {
|
|
48
|
+
if (error) {
|
|
49
|
+
reject(error);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
resolve(count);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/** Gets whether the server is currently listening for connections. */
|
|
58
|
+
get listening() {
|
|
59
|
+
return this.srv.listening;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Sets the maximum number of queued pending connections.
|
|
63
|
+
*
|
|
64
|
+
* @param maxConnections The maximum number of connections to queue.
|
|
65
|
+
*/
|
|
66
|
+
set maxConnections(maxConnections) {
|
|
67
|
+
this.srv.maxConnections = maxConnections;
|
|
68
|
+
}
|
|
69
|
+
/** Gets the maximum number of queued pending connections. */
|
|
70
|
+
get maxConnections() {
|
|
71
|
+
return this.srv.maxConnections;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* References the server, preventing the process from exiting while the server
|
|
75
|
+
* is active.
|
|
76
|
+
*/
|
|
77
|
+
ref() {
|
|
78
|
+
this.srv.ref();
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Unreferences the server, allowing the process from exiting even if the
|
|
82
|
+
* server is active.
|
|
83
|
+
*/
|
|
84
|
+
unref() {
|
|
85
|
+
this.srv.unref();
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Starts the TCP server listening on the specified port and host.
|
|
89
|
+
*
|
|
90
|
+
* @param port The port to listen on. If 0, a random available port will be
|
|
91
|
+
* assigned.
|
|
92
|
+
* @param host The host/interface to bind to. Defaults to '::' (IPv6) or
|
|
93
|
+
* '0.0.0.0' (IPv4).
|
|
94
|
+
* @param options Additional listen options.
|
|
95
|
+
* @returns A promise that resolves when the server is successfully listening.
|
|
96
|
+
*/
|
|
97
|
+
listen(port, host, options) {
|
|
98
|
+
return new Promise((resolve, reject) => {
|
|
99
|
+
const handleError = (error) => {
|
|
100
|
+
this.handledErrorEvents.add(error);
|
|
101
|
+
reject(error);
|
|
102
|
+
};
|
|
103
|
+
this.srv.prependOnceListener("error", handleError);
|
|
104
|
+
this.srv.listen({
|
|
105
|
+
...options,
|
|
106
|
+
port,
|
|
107
|
+
host,
|
|
108
|
+
}, () => {
|
|
109
|
+
this.srv.removeListener("error", handleError);
|
|
110
|
+
resolve();
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Closes the TCP server, stopping it from accepting new connections. Existing
|
|
116
|
+
* connections are not automatically closed.
|
|
117
|
+
*
|
|
118
|
+
* @returns A promise that resolves when the server is fully closed.
|
|
119
|
+
*/
|
|
120
|
+
close() {
|
|
121
|
+
return new Promise((resolve, reject) => {
|
|
122
|
+
this.srv.close((error) => {
|
|
123
|
+
if (error) {
|
|
124
|
+
reject(error);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
resolve();
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Gets the address information of the server.
|
|
134
|
+
*
|
|
135
|
+
* @returns The server's endpoint information or null if the server is not
|
|
136
|
+
* listening.
|
|
137
|
+
*/
|
|
138
|
+
address() {
|
|
139
|
+
const addr = this.srv.address();
|
|
140
|
+
if (addr === null) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
if (typeof addr === "string") {
|
|
144
|
+
throw new UnsupportedError(`Unsupported address type: string. Expected AddressInfo object.`);
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
...composeInetAddress(addr.family, addr.address),
|
|
148
|
+
port: addr.port,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
setupEventForwarding() {
|
|
152
|
+
this.srv.on("connection", (socket) => {
|
|
153
|
+
const client = new TcpSocket(socket);
|
|
154
|
+
this.dispatch("connection", [client]);
|
|
155
|
+
});
|
|
156
|
+
this.srv.on("close", () => {
|
|
157
|
+
this.dispatch("close", []);
|
|
158
|
+
});
|
|
159
|
+
this.srv.on("error", (err) => {
|
|
160
|
+
if (this.handledErrorEvents.has(err)) {
|
|
161
|
+
this.handledErrorEvents.delete(err);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
this.dispatch("error", [err]);
|
|
165
|
+
});
|
|
166
|
+
this.srv.on("listening", () => {
|
|
167
|
+
this.dispatch("listening", []);
|
|
168
|
+
});
|
|
169
|
+
this.srv.on("drop", (data) => {
|
|
170
|
+
let localEndpoint;
|
|
171
|
+
if (data?.localAddress !== undefined &&
|
|
172
|
+
data?.localPort !== undefined &&
|
|
173
|
+
data?.localFamily !== undefined) {
|
|
174
|
+
localEndpoint = {
|
|
175
|
+
...composeInetAddress(data.localFamily, data.localAddress),
|
|
176
|
+
port: data.localPort,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
localEndpoint = null;
|
|
181
|
+
}
|
|
182
|
+
let remoteEndpoint;
|
|
183
|
+
if (data?.remoteAddress !== undefined &&
|
|
184
|
+
data?.remotePort !== undefined &&
|
|
185
|
+
data?.remoteFamily !== undefined) {
|
|
186
|
+
remoteEndpoint = {
|
|
187
|
+
...composeInetAddress(data.remoteFamily, data.remoteAddress),
|
|
188
|
+
port: data.remotePort,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
remoteEndpoint = null;
|
|
193
|
+
}
|
|
194
|
+
this.dispatch("drop", [localEndpoint, remoteEndpoint]);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=tcp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tcp-server.js","sourceRoot":"","sources":["../../src/net/tcp-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import * as net from "node:net";
|
|
2
|
+
import { InetAddress, InetEndpoint } from "@ac-kit/core";
|
|
3
|
+
import type { Except } from "type-fest";
|
|
4
|
+
import { StreamSocket, type StreamSocketEvents } from "./stream-socket.js";
|
|
5
|
+
/** Event map for TcpSocket socket-specific events. */
|
|
6
|
+
export type TcpSocketEvents = StreamSocketEvents & {
|
|
7
|
+
/**
|
|
8
|
+
* Emitted when a new connection attempt is started. May be emitted multiple
|
|
9
|
+
* times if family autoselection is enabled.
|
|
10
|
+
*/
|
|
11
|
+
connectionAttempt: [endpoint: InetEndpoint];
|
|
12
|
+
/**
|
|
13
|
+
* Emitted when a connection attempt failed. May be emitted multiple times if
|
|
14
|
+
* family autoselection is enabled.
|
|
15
|
+
*/
|
|
16
|
+
connectionAttemptFailed: [endpoint: InetEndpoint, error: Error];
|
|
17
|
+
/**
|
|
18
|
+
* Emitted when a connection attempt timed out. May be emitted multiple times
|
|
19
|
+
* if family autoselection is enabled.
|
|
20
|
+
*/
|
|
21
|
+
connectionAttemptTimeout: [endpoint: InetEndpoint];
|
|
22
|
+
/** Emitted after resolving the host name but before connecting. */
|
|
23
|
+
lookup: [err: Error | null, address: InetAddress, host: string];
|
|
24
|
+
};
|
|
25
|
+
export type TcpSocketConnectOptions = Except<net.TcpSocketConnectOpts, "port"> & {
|
|
26
|
+
signal?: AbortSignal;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* TCP socket for establishing connections to TCP servers.
|
|
30
|
+
*
|
|
31
|
+
* Example usage:
|
|
32
|
+
*
|
|
33
|
+
* ```ts
|
|
34
|
+
* const tcpSocket = new TcpSocket.from();
|
|
35
|
+
* await tcpSocket.connect(80, "example.com");
|
|
36
|
+
* await tcpSocket.write("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n");
|
|
37
|
+
* await tcpSocket.end({ waitForClose: true });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare class TcpSocket<TSock extends net.Socket = net.Socket, TEvents extends TcpSocketEvents = TcpSocketEvents> extends StreamSocket<TSock, TEvents> {
|
|
41
|
+
/**
|
|
42
|
+
* Creates a new {@link TcpSocket} instance.
|
|
43
|
+
*
|
|
44
|
+
* @param options Options for creating the underlying Node.js socket.
|
|
45
|
+
* @returns A new `TcpSocket` instance.
|
|
46
|
+
*/
|
|
47
|
+
static from(options?: Except<net.SocketConstructorOpts, "fd">): TcpSocket;
|
|
48
|
+
constructor(sock: TSock);
|
|
49
|
+
/**
|
|
50
|
+
* Returns the remote endpoint information of the socket.
|
|
51
|
+
*
|
|
52
|
+
* @throws {UnsupportedError} If the socket family is not IPv4 or IPv6.
|
|
53
|
+
*/
|
|
54
|
+
get remoteEndpoint(): InetEndpoint | null;
|
|
55
|
+
/**
|
|
56
|
+
* Returns the local endpoint information of the socket.
|
|
57
|
+
*
|
|
58
|
+
* @throws {UnsupportedError} If the socket family is not IPv4 or IPv6.
|
|
59
|
+
*/
|
|
60
|
+
get localEndpoint(): InetEndpoint | null;
|
|
61
|
+
/**
|
|
62
|
+
* Sets the keep-alive option for the socket.
|
|
63
|
+
*
|
|
64
|
+
* @param enable Whether to enable keep-alive.
|
|
65
|
+
* @param initialDelay The initial delay in milliseconds before the first
|
|
66
|
+
* keep-alive probe.
|
|
67
|
+
*/
|
|
68
|
+
setKeepAlive(enable: boolean, initialDelay?: number): void;
|
|
69
|
+
/**
|
|
70
|
+
* Disables the Nagle algorithm for the socket.
|
|
71
|
+
*
|
|
72
|
+
* @param noDelay Whether to disable the Nagle algorithm.
|
|
73
|
+
*/
|
|
74
|
+
setNoDelay(noDelay: boolean): void;
|
|
75
|
+
/**
|
|
76
|
+
* Establishes a TCP connection to the specified port and host.
|
|
77
|
+
*
|
|
78
|
+
* @param port The port to connect to.
|
|
79
|
+
* @param host The host to connect to (defaults to `localhost`).
|
|
80
|
+
* @param options Connection options.
|
|
81
|
+
* @returns A promise that resolves when the connection is successfully
|
|
82
|
+
* established.
|
|
83
|
+
*/
|
|
84
|
+
connect(port: number, options?: TcpSocketConnectOptions): Promise<void>;
|
|
85
|
+
protected setupEventForwarding(): void;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=tcp-socket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tcp-socket.d.ts","sourceRoot":"","sources":["../../src/net/tcp-socket.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAEhC,OAAO,EAEN,WAAW,EACX,YAAY,EAEZ,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE3E,sDAAsD;AACtD,MAAM,MAAM,eAAe,GAAG,kBAAkB,GAAG;IAClD;;;OAGG;IACH,iBAAiB,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAE5C;;;OAGG;IACH,uBAAuB,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAEhE;;;OAGG;IACH,wBAAwB,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAEnD,mEAAmE;IACnE,MAAM,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;CAChE,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAC3C,GAAG,CAAC,oBAAoB,EACxB,MAAM,CACN,GAAG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,qBAAa,SAAS,CACrB,KAAK,SAAS,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,EACrC,OAAO,SAAS,eAAe,GAAG,eAAe,CAChD,SAAQ,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC;IACrC;;;;;OAKG;IACH,OAAgB,IAAI,CACnB,OAAO,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,qBAAqB,EAAE,IAAI,CAAC,GAC/C,SAAS,CAEX;IAED,YAAY,IAAI,EAAE,KAAK,EAGtB;IAED;;;;OAIG;IACH,IAAI,cAAc,IAAI,YAAY,GAAG,IAAI,CAiBxC;IAED;;;;OAIG;IACH,IAAI,aAAa,IAAI,YAAY,GAAG,IAAI,CAiBvC;IAED;;;;;;OAMG;IACH,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAEzD;IAED;;;;OAIG;IACH,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEjC;IAED;;;;;;;;OAQG;IACG,OAAO,CACZ,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,uBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAgCf;IAED,UAAmB,oBAAoB,IAAI,IAAI,CAkC9C;CACD"}
|