@vibecook/truffle 0.4.8 → 0.5.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/dist/create-mesh-node.d.ts +49 -4
- package/dist/create-mesh-node.d.ts.map +1 -1
- package/dist/create-mesh-node.js +22 -4
- package/dist/create-mesh-node.js.map +1 -1
- package/dist/dgram.d.ts +106 -0
- package/dist/dgram.d.ts.map +1 -0
- package/dist/dgram.js +248 -0
- package/dist/dgram.js.map +1 -0
- package/dist/http.d.ts +57 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +116 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/net.d.ts +111 -0
- package/dist/net.d.ts.map +1 -0
- package/dist/net.js +271 -0
- package/dist/net.js.map +1 -0
- package/dist/quic.d.ts +88 -0
- package/dist/quic.d.ts.map +1 -0
- package/dist/quic.js +150 -0
- package/dist/quic.js.map +1 -0
- package/dist/ws.d.ts +72 -0
- package/dist/ws.d.ts.map +1 -0
- package/dist/ws.js +152 -0
- package/dist/ws.js.map +1 -0
- package/package.json +19 -8
- package/scripts/postinstall.cjs +29 -8
- package/sidecar-checksums.json +20 -8
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
|
package/dist/http.js.map
ADDED
|
@@ -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, 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, NapiDatagram, } from '@vibecook/truffle-native';
|
|
3
3
|
export { resolveSidecarPath } from './sidecar.js';
|
|
4
|
-
export {
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,
|
|
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,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,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, 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,
|
|
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,aAAa,EACb,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,GACf,MAAM,0BAA0B,CAAC;AAuBlC,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":"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"}
|
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
|
package/dist/net.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"net.js","sourceRoot":"","sources":["../src/net.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,EAAE;AACF,sEAAsE;AACtE,sDAAsD;AACtD,0EAA0E;AAC1E,gEAAgE;AAChE,EAAE;AACF,2EAA2E;AAC3E,2EAA2E;AAC3E,aAAa;AAEb,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAe3C;;;;;;GAMG;AACH,MAAM,OAAO,aAAc,SAAQ,MAAM;IACvC,OAAO,GAAyB,IAAI,CAAC;IACrC,MAAM,CAAyB;IAC/B,QAAQ,GAAG,KAAK,CAAC;IAEjB,gEAAgE;IAChE,aAAa,CAAU;IACvB,gFAAgF;IAChF,YAAY,CAAU;IACtB,0EAA0E;IAC1E,cAAc,CAAU;IAExB,YAAY,MAA8C;QACxD,KAAK,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,CAAC,IAAmB,EAAiB,EAAE;YACnD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YAC1C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,SAAS,CAAC;YACrD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,EAAE,IAAI,SAAS,CAAC;YACzD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC;QACF,IAAI,OAAQ,MAAqC,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACtE,gEAAgE;YAChE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;gBAClD,KAAK,CAAC,IAAI,CAAC,CAAC;gBACZ,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACrB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACnB,OAAO,IAAI,CAAC;YACd,CAAC,CAAC,CAAC;YACH,qEAAqE;YACrE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAY,CAAC,CAAC,CAAC;QACzD,CAAC;aAAM,CAAC;YACN,oEAAoE;YACpE,4DAA4D;YAC5D,kEAAkE;YAClE,gEAAgE;YAChE,+BAA+B;YAC/B,MAAM,IAAI,GAAG,KAAK,CAAC,MAAuB,CAAC,CAAC;YAC5C,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACpC,cAAc,CAAC,GAAG,EAAE;gBAClB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;oBACpB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBACrB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEQ,KAAK,CAAC,IAAY;QACzB,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,MAAM;aACR,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;aACtD,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YACd,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;YACtB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACb,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;YACtB,IAAI,CAAC,OAAO,CAAC,GAAY,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACP,CAAC;IAEQ,MAAM,CACb,KAAa,EACb,SAAyB,EACzB,QAAwC;QAExC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC/F,CAAC;IAEQ,MAAM,CAAC,QAAwC;QACtD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;IACxF,CAAC;IAEQ,QAAQ,CAAC,KAAmB,EAAE,QAAuC;QAC5E,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,8DAA8D;YAC9D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACzD,MAAM,EAAE,CAAC;QACX,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,yEAAyE;IACzE,0EAA0E;IAC1E,qEAAqE;IACrE,uEAAuE;IACvE,0EAA0E;IAC1E,wEAAwE;IACxE,mEAAmE;IAEnE,6DAA6D;IAC7D,OAAO,GAAG,CAAC,CAAC;IAEZ;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,KAAa,EAAE,QAAqB;QAC7C,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,KAAK,KAAK,CAAC;gBAAE,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;;gBACrD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6EAA6E;IAC7E,UAAU,CAAC,QAAkB;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,+EAA+E;IAC/E,YAAY,CAAC,OAAiB,EAAE,aAAsB;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mEAAmE;IACnE,GAAG;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kDAAkD;IAClD,KAAK;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6EAA6E;IAC7E,OAAO;QACL,OAAO,EAAE,CAAC;IACZ,CAAC;CACF;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,aAAc,SAAQ,YAAY;IAC7C,KAAK,CAAW;IAChB,SAAS,GAA2B,IAAI,CAAC;IACzC,OAAO,GAAG,KAAK,CAAC;IAChB,aAAa,GAAG,KAAK,CAAC;IAEtB,gFAAgF;IAChF,IAAI,CAAU;IAEd,YAAY,IAAc,EAAE,kBAAuC;QACjE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,kBAAkB;YAAE,IAAI,CAAC,EAAE,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;IACpE,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,IAAY,EAAE,iBAA8B;QACjD,IAAI,IAAI,CAAC,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC/D,IAAI,iBAAiB;YAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;QACjE,IAAI,CAAC,KAAK;aACP,SAAS,CAAC,IAAI,CAAC;aACf,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;YACjB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACjB,KAAK,QAAQ,CAAC,KAAK,EAAE,CAAC;gBACtB,OAAO;YACT,CAAC;YACD,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;YAC1B,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACvB,KAAK,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QAC3C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,QAAyB;QACzC,IAAI,CAAC;YACH,SAAS,CAAC;gBACR,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACvC,IAAI,MAAM,KAAK,IAAI;oBAAE,MAAM;gBAC3B,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,IAAI,CAAC,OAAO;gBAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,CAAC,UAAU,EAAE,CAAC;IACpB,CAAC;IAED,UAAU;QACR,IAAI,IAAI,CAAC,aAAa;YAAE,OAAO;QAC/B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrB,CAAC;IAED,iFAAiF;IACjF,OAAO;QACL,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IAC9D,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,QAAqB;QACzB,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,IAAI,CAAC,aAAa;gBAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;;gBAC5C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC9B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,QAAQ,EAAE,CAAC;YACb,oEAAoE;YACpE,qEAAqE;YACrE,2CAA2C;YAC3C,KAAK,QAAQ,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAcD,MAAM,UAAU,kBAAkB,CAAC,IAAc;IAG/C,SAAS,OAAO,CAAC,aAAyC,EAAE,SAAkB;QAC5E,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAClB,OAAO,aAAa,KAAK,QAAQ;YAC/B,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,IAAI,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE;YAChD,CAAC,CAAC,aAAa,CAAC;QACpB,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,SAAS,CAAC,kCAAkC,CAAC,CAAC;QACnE,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,OAAO;QACL,OAAO;QACP,gBAAgB,EAAE,OAAO;QACzB,YAAY,EAAE,CAAC,kBAAuC,EAAE,EAAE,CACxD,IAAI,aAAa,CAAC,IAAI,EAAE,kBAAkB,CAAC;KAC9C,CAAC;AACJ,CAAC"}
|