@vibecook/truffle 0.4.7 → 0.4.9

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/dist/http.js ADDED
@@ -0,0 +1,116 @@
1
+ // node:http interop for the mesh (RFC 021 Phase 2).
2
+ //
3
+ // `mesh.http` lets existing node:http / Express code talk to peers over the
4
+ // mesh with a one-line change. Two directions:
5
+ //
6
+ // • Outbound: point a request at a peer through a MeshAgent
7
+ // mesh.http.get('http://100.64.0.7:8080/api/status', (res) => …)
8
+ // await mesh.http.fetchText('kitchen-pi', 8080, '/api/status')
9
+ // • Inbound: feed mesh TCP connections into a stock http.Server
10
+ // const httpServer = http.createServer(app); // e.g. Express
11
+ // mesh.net
12
+ // .createServer((socket) => httpServer.emit('connection', socket))
13
+ // .listen(8080);
14
+ //
15
+ // Nothing here is mesh-specific beyond the Agent seam: `http.Agent#
16
+ // createConnection` is documented to accept any `stream.Duplex`, and
17
+ // TruffleSocket (see ./net.ts) is one, so node:http drives it exactly like a
18
+ // real net.Socket. The compat shims that make that true live in ./net.ts.
19
+ import http from 'node:http';
20
+ /**
21
+ * An `http.Agent` that dials its connections over the mesh instead of the
22
+ * host network. Pass it as `{ agent }` to any `node:http` request and the
23
+ * request travels to the peer named by the URL hostname (or `options.host`).
24
+ *
25
+ * Connection reuse behaves exactly like the stock agent. The default
26
+ * `keepAlive: false` opens a fresh mesh connection per request and closes it
27
+ * on response end; `new MeshAgent(net, { keepAlive: true })` pools and reuses
28
+ * idle sockets like any http.Agent (but see the idle-reaping caveat on
29
+ * `TruffleSocket.setTimeout` — quiet pooled sockets aren't reaped on a timer).
30
+ */
31
+ export class MeshAgent extends http.Agent {
32
+ #net;
33
+ constructor(net, opts) {
34
+ super(opts);
35
+ this.#net = net;
36
+ }
37
+ /**
38
+ * Called by node:http to obtain a socket for a request. Returns a mesh
39
+ * TruffleSocket (a `stream.Duplex`) synchronously — it connects in the
40
+ * background and emits `'connect'` later, which is exactly the net.Socket
41
+ * contract http expects. The callback form is also honoured for robustness
42
+ * (node uses whichever settles first, once).
43
+ */
44
+ createConnection(options, callback) {
45
+ const socket = this.#net.connect({ host: hostOf(options), port: portOf(options) });
46
+ if (callback) {
47
+ const onConnect = () => {
48
+ socket.removeListener('error', onError);
49
+ callback(null, socket);
50
+ };
51
+ const onError = (err) => {
52
+ socket.removeListener('connect', onConnect);
53
+ callback(err, socket);
54
+ };
55
+ socket.once('connect', onConnect);
56
+ socket.once('error', onError);
57
+ }
58
+ return socket;
59
+ }
60
+ }
61
+ /** The peer reference for a request: URL hostname, or `options.host`. */
62
+ function hostOf(options) {
63
+ // ClientRequest normalises `options.host = hostname || host || 'localhost'`
64
+ // before the agent sees it; prefer `hostname` explicitly all the same.
65
+ const host = options.hostname ?? options.host;
66
+ if (!host)
67
+ throw new TypeError('mesh.http: request is missing a host (peer reference)');
68
+ return host;
69
+ }
70
+ function portOf(options) {
71
+ const port = typeof options.port === 'string' ? Number(options.port) : options.port;
72
+ return port && Number.isFinite(port) ? port : 80;
73
+ }
74
+ export function createHttpNamespace(net) {
75
+ const agent = new MeshAgent(net);
76
+ // Inject the mesh agent unless the caller supplied their own (or `false`).
77
+ function withAgent(options) {
78
+ return { ...options, agent: options?.agent ?? agent };
79
+ }
80
+ // Normalise node:http's overloads and route through `fn` (request or get).
81
+ function dispatch(fn, arg1, arg2, arg3) {
82
+ if (typeof arg2 === 'function' || arg2 === undefined) {
83
+ // (url|options, callback?) form.
84
+ if (typeof arg1 === 'string' || arg1 instanceof URL) {
85
+ return fn(arg1, withAgent(), arg2);
86
+ }
87
+ return fn(withAgent(arg1), arg2);
88
+ }
89
+ // (url, options, callback?) form.
90
+ return fn(arg1, withAgent(arg2), arg3);
91
+ }
92
+ function request(arg1, arg2, arg3) {
93
+ return dispatch(http.request, arg1, arg2, arg3);
94
+ }
95
+ function get(arg1, arg2, arg3) {
96
+ return dispatch(http.get, arg1, arg2, arg3);
97
+ }
98
+ function fetchText(peer, port, path = '/') {
99
+ return new Promise((resolve, reject) => {
100
+ const req = http.request({ host: peer, port, path, method: 'GET', agent }, (res) => {
101
+ const chunks = [];
102
+ res.on('data', (chunk) => chunks.push(chunk));
103
+ res.on('end', () => resolve({
104
+ status: res.statusCode ?? 0,
105
+ headers: res.headers,
106
+ body: Buffer.concat(chunks).toString('utf8'),
107
+ }));
108
+ res.on('error', reject);
109
+ });
110
+ req.on('error', reject);
111
+ req.end();
112
+ });
113
+ }
114
+ return { agent, Agent: MeshAgent, request, get, fetchText };
115
+ }
116
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,10 @@
1
- export { NapiNode, NapiFileTransfer, NapiOfferResponder, NapiSyncedStore, } from '@vibecook/truffle-native';
2
- export type { NapiNodeConfig, NapiNodeIdentity, NapiPeer, NapiPingResult, NapiHealthInfo, NapiPeerEvent, NapiNamespacedMessage, NapiFileOffer, NapiTransferResult, NapiTransferProgress, NapiFileTransferEvent, NapiSlice, NapiStoreEvent, } from '@vibecook/truffle-native';
1
+ export { NapiNode, NapiFileTransfer, NapiOfferResponder, NapiSyncedStore, NapiProxy, NapiCrdtDoc, NapiTcpSocket, NapiTcpListener, NapiUdpSocket, NapiQuicConnection, NapiQuicListener, NapiQuicStream, } from '@vibecook/truffle-native';
2
+ export type { NapiNodeConfig, NapiNodeIdentity, NapiPeer, NapiPingResult, NapiHealthInfo, NapiPeerEvent, NapiNamespacedMessage, NapiFileOffer, NapiTransferResult, NapiTransferProgress, NapiFileTransferEvent, NapiSlice, NapiStoreEvent, NapiProxyConfig, NapiProxyInfo, NapiProxyEvent, NapiCrdtDocEvent, NapiDatagram, } from '@vibecook/truffle-native';
3
3
  export { resolveSidecarPath } from './sidecar.js';
4
- export { createMeshNode, type CreateMeshNodeOptions } from './create-mesh-node.js';
4
+ export { TruffleSocket, TruffleServer, createNetNamespace, type TruffleNet, type NetConnectOptions, type ConnectionListener, } from './net.js';
5
+ export { MeshAgent, createHttpNamespace, type TruffleHttp } from './http.js';
6
+ export { TruffleQuicStream, TruffleQuicConnection, TruffleQuicServer, createQuicNamespace, type TruffleQuic, } from './quic.js';
7
+ export { TruffleDgramSocket, createDgramNamespace, type TruffleDgram, type TruffleRemoteInfo, } from './dgram.js';
8
+ export { createWsNamespace, type TruffleWs, type TruffleWsServer, type TruffleWsServerOptions, type WsLoader, } from './ws.js';
9
+ export { createMeshNode, type CreateMeshNodeOptions, type MeshNode } from './create-mesh-node.js';
5
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,GAChB,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,QAAQ,EACR,cAAc,EACd,cAAc,EACd,aAAa,EACb,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,SAAS,EACT,cAAc,GACf,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGlD,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,SAAS,EACT,WAAW,EACX,aAAa,EACb,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,GACf,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,QAAQ,EACR,cAAc,EACd,cAAc,EACd,aAAa,EACb,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,SAAS,EACT,cAAc,EACd,eAAe,EACf,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,YAAY,GACb,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGlD,OAAO,EACL,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,GACxB,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAG7E,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,WAAW,GACjB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACvB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,iBAAiB,EACjB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,QAAQ,GACd,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1,17 @@
1
1
  // Re-export classes (values) from the native Rust addon
2
- export { NapiNode, NapiFileTransfer, NapiOfferResponder, NapiSyncedStore, } from '@vibecook/truffle-native';
2
+ export { NapiNode, NapiFileTransfer, NapiOfferResponder, NapiSyncedStore, NapiProxy, NapiCrdtDoc, NapiTcpSocket, NapiTcpListener, NapiUdpSocket, NapiQuicConnection, NapiQuicListener, NapiQuicStream, } from '@vibecook/truffle-native';
3
3
  // Sidecar binary resolution
4
4
  export { resolveSidecarPath } from './sidecar.js';
5
+ // node:net-shaped raw TCP API over the mesh (RFC 021)
6
+ export { TruffleSocket, TruffleServer, createNetNamespace, } from './net.js';
7
+ // node:http interop over the mesh (RFC 021)
8
+ export { MeshAgent, createHttpNamespace } from './http.js';
9
+ // QUIC over the mesh (RFC 021)
10
+ export { TruffleQuicStream, TruffleQuicConnection, TruffleQuicServer, createQuicNamespace, } from './quic.js';
11
+ // node:dgram-shaped raw UDP API over the mesh (RFC 021)
12
+ export { TruffleDgramSocket, createDgramNamespace, } from './dgram.js';
13
+ // WebSocket over the mesh via the `ws` package (RFC 021)
14
+ export { createWsNamespace, } from './ws.js';
5
15
  // High-level API
6
16
  export { createMeshNode } from './create-mesh-node.js';
7
17
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,OAAO,EACL,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,GAChB,MAAM,0BAA0B,CAAC;AAmBlC,4BAA4B;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,iBAAiB;AACjB,OAAO,EAAE,cAAc,EAA8B,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,OAAO,EACL,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,SAAS,EACT,WAAW,EACX,aAAa,EACb,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,GACf,MAAM,0BAA0B,CAAC;AAwBlC,4BAA4B;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,sDAAsD;AACtD,OAAO,EACL,aAAa,EACb,aAAa,EACb,kBAAkB,GAInB,MAAM,UAAU,CAAC;AAElB,4CAA4C;AAC5C,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAoB,MAAM,WAAW,CAAC;AAE7E,+BAA+B;AAC/B,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,GAEpB,MAAM,WAAW,CAAC;AAEnB,wDAAwD;AACxD,OAAO,EACL,kBAAkB,EAClB,oBAAoB,GAGrB,MAAM,YAAY,CAAC;AAEpB,yDAAyD;AACzD,OAAO,EACL,iBAAiB,GAKlB,MAAM,SAAS,CAAC;AAEjB,iBAAiB;AACjB,OAAO,EAAE,cAAc,EAA6C,MAAM,uBAAuB,CAAC"}
package/dist/net.d.ts ADDED
@@ -0,0 +1,111 @@
1
+ import { Duplex } from 'node:stream';
2
+ import { EventEmitter } from 'node:events';
3
+ import type { NapiNode, NapiTcpSocket } from '@vibecook/truffle-native';
4
+ export interface NetConnectOptions {
5
+ /**
6
+ * Peer to connect to: device id (or unique ≥4-char prefix), device
7
+ * name, Tailscale hostname, or Tailscale IP.
8
+ */
9
+ host: string;
10
+ /** Port on the peer. */
11
+ port: number;
12
+ }
13
+ export type ConnectionListener = (socket: TruffleSocket) => void;
14
+ /**
15
+ * A TCP connection over the mesh, as a standard `stream.Duplex`.
16
+ *
17
+ * Mirrors `net.Socket` semantics where it matters: `'connect'`/`'ready'`
18
+ * on establishment, `end()` half-closes (FIN) while reads continue,
19
+ * `'end'` on peer EOF, `destroy()` tears down both directions.
20
+ */
21
+ export declare class TruffleSocket extends Duplex {
22
+ #private;
23
+ /** Logical remote address (`host:port`); set once connected. */
24
+ remoteAddress?: string;
25
+ /** Stable peer id (resolved device id, or WhoIs node id inbound) when known. */
26
+ remotePeerId?: string;
27
+ /** Human-readable peer name from the WhoIs identity (inbound sockets). */
28
+ remotePeerName?: string;
29
+ constructor(native: NapiTcpSocket | Promise<NapiTcpSocket>);
30
+ _read(size: number): void;
31
+ _write(chunk: Buffer, _encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
32
+ _final(callback: (error?: Error | null) => void): void;
33
+ _destroy(error: Error | null, callback: (error: Error | null) => void): void;
34
+ /** net.Socket#timeout, as recorded by {@link setTimeout}. */
35
+ timeout: number;
36
+ /**
37
+ * net.Socket#setTimeout. Records the value and, like net.Socket, wires an
38
+ * optional one-shot `'timeout'` listener (and clears it when `msecs` is 0).
39
+ *
40
+ * Caveat: the mesh bridge doesn't surface socket idle activity to JS
41
+ * without forcing the readable side into flowing mode (which would defeat
42
+ * the pull-model backpressure), so no idle timer is armed and `'timeout'`
43
+ * never fires on its own — enforce inactivity limits at the app layer if
44
+ * you need them. http's default server timeout is 0 (disabled) and the
45
+ * default agent is `keepAlive: false`, so this is inert on the common
46
+ * paths and exists so calling code doesn't throw. Never auto-destroys the
47
+ * socket, matching net.Socket.
48
+ */
49
+ setTimeout(msecs: number, callback?: () => void): this;
50
+ /** net.Socket#setNoDelay — no-op: Nagle doesn't apply to the mesh bridge. */
51
+ setNoDelay(_noDelay?: boolean): this;
52
+ /** net.Socket#setKeepAlive — no-op: the bridge has no TCP keepalive to set. */
53
+ setKeepAlive(_enable?: boolean, _initialDelay?: number): this;
54
+ /** net.Socket#ref — no-op: no libuv handle backs a mesh socket. */
55
+ ref(): this;
56
+ /** net.Socket#unref — no-op (see {@link ref}). */
57
+ unref(): this;
58
+ /** net.Socket#address — mesh sockets have no local IP/port; returns `{}`. */
59
+ address(): {
60
+ address?: string;
61
+ family?: string;
62
+ port?: number;
63
+ };
64
+ }
65
+ /**
66
+ * A TCP server on the mesh, mimicking `net.Server`.
67
+ *
68
+ * Events: `'listening'`, `'connection'` ([`TruffleSocket`]), `'close'`,
69
+ * `'error'`. To serve HTTP over the mesh:
70
+ *
71
+ * ```ts
72
+ * const httpServer = http.createServer(app);
73
+ * mesh.net
74
+ * .createServer((socket) => httpServer.emit('connection', socket))
75
+ * .listen(8080);
76
+ * ```
77
+ */
78
+ export declare class TruffleServer extends EventEmitter {
79
+ #private;
80
+ /** Bound port; set once `'listening'` fires (resolved when 0 was requested). */
81
+ port?: number;
82
+ constructor(node: NapiNode, connectionListener?: ConnectionListener);
83
+ /**
84
+ * Start listening on `port` (0 = ephemeral; read `server.port` after
85
+ * `'listening'`). Returns `this`, like `net.Server#listen`.
86
+ */
87
+ listen(port: number, listeningListener?: () => void): this;
88
+ /** `net.Server#address` compat (port only — mesh listeners have no local IP). */
89
+ address(): {
90
+ port: number;
91
+ } | null;
92
+ /**
93
+ * Stop accepting connections and release the port. `callback` fires on
94
+ * `'close'` — including when the server already closed (e.g. the accept
95
+ * loop ended on its own after a mesh teardown), like `net.Server#close`.
96
+ */
97
+ close(callback?: () => void): this;
98
+ }
99
+ /** node:net-shaped namespace bound to a mesh node. */
100
+ export interface TruffleNet {
101
+ /** Open a connection to a peer. Returns the socket immediately; it emits `'connect'`. */
102
+ connect(options: NetConnectOptions): TruffleSocket;
103
+ connect(port: number, host: string): TruffleSocket;
104
+ /** Alias of `connect`, mirroring `net.createConnection`. */
105
+ createConnection(options: NetConnectOptions): TruffleSocket;
106
+ createConnection(port: number, host: string): TruffleSocket;
107
+ /** Create a server; call `.listen(port)` to bind, like `net.createServer`. */
108
+ createServer(connectionListener?: ConnectionListener): TruffleServer;
109
+ }
110
+ export declare function createNetNamespace(node: NapiNode): TruffleNet;
111
+ //# sourceMappingURL=net.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"net.d.ts","sourceRoot":"","sources":["../src/net.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAmB,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzF,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;AAEjE;;;;;;GAMG;AACH,qBAAa,aAAc,SAAQ,MAAM;;IAKvC,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,cAAc,CAAC,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAoCjD,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAezB,MAAM,CACb,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,cAAc,EACzB,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,GACvC,IAAI;IAIE,MAAM,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI;IAItD,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI;IAoBrF,6DAA6D;IAC7D,OAAO,SAAK;IAEZ;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI;IAStD,6EAA6E;IAC7E,UAAU,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI;IAIpC,+EAA+E;IAC/E,YAAY,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI;IAI7D,mEAAmE;IACnE,GAAG,IAAI,IAAI;IAIX,kDAAkD;IAClD,KAAK,IAAI,IAAI;IAIb,6EAA6E;IAC7E,OAAO,IAAI;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;CAGhE;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,aAAc,SAAQ,YAAY;;IAM7C,gFAAgF;IAChF,IAAI,CAAC,EAAE,MAAM,CAAC;gBAEF,IAAI,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EAAE,kBAAkB;IAMnE;;;OAGG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI;IAsC1D,iFAAiF;IACjF,OAAO,IAAI;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAIlC;;;;OAIG;IACH,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI;CAmBnC;AAED,sDAAsD;AACtD,MAAM,WAAW,UAAU;IACzB,yFAAyF;IACzF,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,aAAa,CAAC;IACnD,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC;IACnD,4DAA4D;IAC5D,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,aAAa,CAAC;IAC5D,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC;IAC5D,8EAA8E;IAC9E,YAAY,CAAC,kBAAkB,CAAC,EAAE,kBAAkB,GAAG,aAAa,CAAC;CACtE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAkB7D"}
package/dist/net.js ADDED
@@ -0,0 +1,271 @@
1
+ // node:net-shaped API over truffle's raw TCP transport (RFC 021 Phase 2).
2
+ //
3
+ // TruffleSocket is a real stream.Duplex, so everything that accepts a
4
+ // Node socket-ish duplex works over the mesh: piping,
5
+ // `httpServer.emit('connection', socket)`, `http.Agent#createConnection`,
6
+ // the `ws` package via a custom agent, undici's `connect`, etc.
7
+ //
8
+ // Backpressure comes from the pull-model native handle: `_read` awaits one
9
+ // native `read()` at a time, `_write` resolves when the transport accepted
10
+ // the bytes.
11
+ import { Duplex } from 'node:stream';
12
+ import { EventEmitter } from 'node:events';
13
+ /**
14
+ * A TCP connection over the mesh, as a standard `stream.Duplex`.
15
+ *
16
+ * Mirrors `net.Socket` semantics where it matters: `'connect'`/`'ready'`
17
+ * on establishment, `end()` half-closes (FIN) while reads continue,
18
+ * `'end'` on peer EOF, `destroy()` tears down both directions.
19
+ */
20
+ export class TruffleSocket extends Duplex {
21
+ #native = null;
22
+ #ready;
23
+ #reading = false;
24
+ /** Logical remote address (`host:port`); set once connected. */
25
+ remoteAddress;
26
+ /** Stable peer id (resolved device id, or WhoIs node id inbound) when known. */
27
+ remotePeerId;
28
+ /** Human-readable peer name from the WhoIs identity (inbound sockets). */
29
+ remotePeerName;
30
+ constructor(native) {
31
+ super({ allowHalfOpen: true });
32
+ const adopt = (sock) => {
33
+ this.#native = sock;
34
+ this.remoteAddress = sock.remoteAddress();
35
+ this.remotePeerId = sock.remotePeerId() ?? undefined;
36
+ this.remotePeerName = sock.remotePeerName() ?? undefined;
37
+ return sock;
38
+ };
39
+ if (typeof native.then === 'function') {
40
+ // Outbound: the dial is in flight; metadata lands on 'connect'.
41
+ this.#ready = Promise.resolve(native).then((sock) => {
42
+ adopt(sock);
43
+ this.emit('connect');
44
+ this.emit('ready');
45
+ return sock;
46
+ });
47
+ // A failed dial destroys the socket with the error, like net.Socket.
48
+ this.#ready.catch((err) => this.destroy(err));
49
+ }
50
+ else {
51
+ // Inbound (accept-path) sockets are already connected: set the peer
52
+ // metadata synchronously so a 'connection' handler can read
53
+ // remotePeerId/remotePeerName immediately for accept-time gating.
54
+ // The events still fire asynchronously — constructor-time emits
55
+ // would have no listeners yet.
56
+ const sock = adopt(native);
57
+ this.#ready = Promise.resolve(sock);
58
+ queueMicrotask(() => {
59
+ if (!this.destroyed) {
60
+ this.emit('connect');
61
+ this.emit('ready');
62
+ }
63
+ });
64
+ }
65
+ }
66
+ _read(size) {
67
+ if (this.#reading)
68
+ return;
69
+ this.#reading = true;
70
+ this.#ready
71
+ .then((sock) => sock.read(size > 0 ? size : undefined))
72
+ .then((chunk) => {
73
+ this.#reading = false;
74
+ this.push(chunk);
75
+ })
76
+ .catch((err) => {
77
+ this.#reading = false;
78
+ this.destroy(err);
79
+ });
80
+ }
81
+ _write(chunk, _encoding, callback) {
82
+ this.#ready.then((sock) => sock.write(chunk).then(() => callback(null), callback), callback);
83
+ }
84
+ _final(callback) {
85
+ this.#ready.then((sock) => sock.end().then(() => callback(null), callback), callback);
86
+ }
87
+ _destroy(error, callback) {
88
+ const finish = () => callback(error);
89
+ if (this.#native) {
90
+ this.#native.close().then(finish, finish);
91
+ }
92
+ else {
93
+ // Dial still in flight — close the socket when (if) it lands.
94
+ this.#ready.then((sock) => sock.close()).catch(() => { });
95
+ finish();
96
+ }
97
+ }
98
+ // ─── net.Socket compat shims (RFC 021) ────────────────────────────────
99
+ // node:http's client and server hand their sockets a few net.Socket-only
100
+ // methods (setTimeout/setNoDelay/setKeepAlive/ref/unref/address). A plain
101
+ // Duplex doesn't have them, so without these `http.request(...)` and
102
+ // `httpServer.emit('connection', socket)` throw on the missing method.
103
+ // The mesh data path is a loopback hop with no Nagle, no SO_KEEPALIVE and
104
+ // no local IP/port, so these are well-behaved no-ops that return `this`
105
+ // (net.Socket's chainable contract) — enough to satisfy node:http.
106
+ /** net.Socket#timeout, as recorded by {@link setTimeout}. */
107
+ timeout = 0;
108
+ /**
109
+ * net.Socket#setTimeout. Records the value and, like net.Socket, wires an
110
+ * optional one-shot `'timeout'` listener (and clears it when `msecs` is 0).
111
+ *
112
+ * Caveat: the mesh bridge doesn't surface socket idle activity to JS
113
+ * without forcing the readable side into flowing mode (which would defeat
114
+ * the pull-model backpressure), so no idle timer is armed and `'timeout'`
115
+ * never fires on its own — enforce inactivity limits at the app layer if
116
+ * you need them. http's default server timeout is 0 (disabled) and the
117
+ * default agent is `keepAlive: false`, so this is inert on the common
118
+ * paths and exists so calling code doesn't throw. Never auto-destroys the
119
+ * socket, matching net.Socket.
120
+ */
121
+ setTimeout(msecs, callback) {
122
+ this.timeout = msecs;
123
+ if (callback) {
124
+ if (msecs === 0)
125
+ this.removeListener('timeout', callback);
126
+ else
127
+ this.once('timeout', callback);
128
+ }
129
+ return this;
130
+ }
131
+ /** net.Socket#setNoDelay — no-op: Nagle doesn't apply to the mesh bridge. */
132
+ setNoDelay(_noDelay) {
133
+ return this;
134
+ }
135
+ /** net.Socket#setKeepAlive — no-op: the bridge has no TCP keepalive to set. */
136
+ setKeepAlive(_enable, _initialDelay) {
137
+ return this;
138
+ }
139
+ /** net.Socket#ref — no-op: no libuv handle backs a mesh socket. */
140
+ ref() {
141
+ return this;
142
+ }
143
+ /** net.Socket#unref — no-op (see {@link ref}). */
144
+ unref() {
145
+ return this;
146
+ }
147
+ /** net.Socket#address — mesh sockets have no local IP/port; returns `{}`. */
148
+ address() {
149
+ return {};
150
+ }
151
+ }
152
+ /**
153
+ * A TCP server on the mesh, mimicking `net.Server`.
154
+ *
155
+ * Events: `'listening'`, `'connection'` ([`TruffleSocket`]), `'close'`,
156
+ * `'error'`. To serve HTTP over the mesh:
157
+ *
158
+ * ```ts
159
+ * const httpServer = http.createServer(app);
160
+ * mesh.net
161
+ * .createServer((socket) => httpServer.emit('connection', socket))
162
+ * .listen(8080);
163
+ * ```
164
+ */
165
+ export class TruffleServer extends EventEmitter {
166
+ #node;
167
+ #listener = null;
168
+ #closed = false;
169
+ #closeEmitted = false;
170
+ /** Bound port; set once `'listening'` fires (resolved when 0 was requested). */
171
+ port;
172
+ constructor(node, connectionListener) {
173
+ super();
174
+ this.#node = node;
175
+ if (connectionListener)
176
+ this.on('connection', connectionListener);
177
+ }
178
+ /**
179
+ * Start listening on `port` (0 = ephemeral; read `server.port` after
180
+ * `'listening'`). Returns `this`, like `net.Server#listen`.
181
+ */
182
+ listen(port, listeningListener) {
183
+ if (this.#listener)
184
+ throw new Error('listen() already called');
185
+ if (listeningListener)
186
+ this.once('listening', listeningListener);
187
+ this.#node
188
+ .listenTcp(port)
189
+ .then((listener) => {
190
+ if (this.#closed) {
191
+ void listener.close();
192
+ return;
193
+ }
194
+ this.#listener = listener;
195
+ this.port = listener.port();
196
+ this.emit('listening');
197
+ void this.#acceptLoop(listener);
198
+ })
199
+ .catch((err) => this.emit('error', err));
200
+ return this;
201
+ }
202
+ async #acceptLoop(listener) {
203
+ try {
204
+ for (;;) {
205
+ const native = await listener.accept();
206
+ if (native === null)
207
+ break;
208
+ this.emit('connection', new TruffleSocket(native));
209
+ }
210
+ }
211
+ catch (err) {
212
+ if (!this.#closed)
213
+ this.emit('error', err);
214
+ }
215
+ this.#emitClose();
216
+ }
217
+ #emitClose() {
218
+ if (this.#closeEmitted)
219
+ return;
220
+ this.#closeEmitted = true;
221
+ this.emit('close');
222
+ }
223
+ /** `net.Server#address` compat (port only — mesh listeners have no local IP). */
224
+ address() {
225
+ return this.port === undefined ? null : { port: this.port };
226
+ }
227
+ /**
228
+ * Stop accepting connections and release the port. `callback` fires on
229
+ * `'close'` — including when the server already closed (e.g. the accept
230
+ * loop ended on its own after a mesh teardown), like `net.Server#close`.
231
+ */
232
+ close(callback) {
233
+ if (callback) {
234
+ if (this.#closeEmitted)
235
+ queueMicrotask(callback);
236
+ else
237
+ this.once('close', callback);
238
+ }
239
+ if (this.#closed)
240
+ return this;
241
+ this.#closed = true;
242
+ const listener = this.#listener;
243
+ this.#listener = null;
244
+ if (listener) {
245
+ // accept() resolves null → the loop exits and emits 'close' (unless
246
+ // the loop already ended on its own — then 'close' already fired and
247
+ // this just releases the native listener).
248
+ void listener.close();
249
+ }
250
+ else {
251
+ this.#emitClose();
252
+ }
253
+ return this;
254
+ }
255
+ }
256
+ export function createNetNamespace(node) {
257
+ function connect(optionsOrPort, maybeHost) {
258
+ const { host, port } = typeof optionsOrPort === 'number'
259
+ ? { host: maybeHost ?? '', port: optionsOrPort }
260
+ : optionsOrPort;
261
+ if (!host)
262
+ throw new TypeError('connect: host (peer) is required');
263
+ return new TruffleSocket(node.openTcp(host, port));
264
+ }
265
+ return {
266
+ connect,
267
+ createConnection: connect,
268
+ createServer: (connectionListener) => new TruffleServer(node, connectionListener),
269
+ };
270
+ }
271
+ //# sourceMappingURL=net.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"net.js","sourceRoot":"","sources":["../src/net.ts"],"names":[],"mappings":"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"}