@delali/narsil 0.2.2 → 0.2.3-next.33

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.
Files changed (66) hide show
  1. package/README.md +12 -9
  2. package/dist/adapters/filesystem.d.ts +1 -1
  3. package/dist/adapters/filesystem.mjs +1 -1
  4. package/dist/adapters/indexeddb.d.ts +1 -1
  5. package/dist/adapters/indexeddb.mjs +1 -1
  6. package/dist/adapters/memory.d.ts +1 -1
  7. package/dist/{adapters-CVqI5NBt.d.ts → adapters-79OIa4xm.d.ts} +1 -1
  8. package/dist/brute-force-DbHYCTc3.d.ts +8 -0
  9. package/dist/chunk-BFIH7OV5.mjs +185 -0
  10. package/dist/chunk-C6VVLMRX.mjs +63 -0
  11. package/dist/{chunk-UNJZ7ZDB.mjs → chunk-EMI63EXP.mjs} +33 -2
  12. package/dist/chunk-MFFAJ2NR.mjs +135 -0
  13. package/dist/chunk-OBXS7OZM.mjs +376 -0
  14. package/dist/{chunk-ASI6AOW2.mjs → chunk-RO4EFWE6.mjs} +7833 -3524
  15. package/dist/{chunk-WLR5BFL3.mjs → chunk-TEAJO7CU.mjs} +3067 -2087
  16. package/dist/{chunk-S7RJJMHI.mjs → chunk-WDL632CN.mjs} +699 -222
  17. package/dist/{chunk-BKAI2WXI.mjs → chunk-WTONLDU3.mjs} +5 -0
  18. package/dist/client-DQHB_swQ.d.ts +793 -0
  19. package/dist/client.d.ts +6 -0
  20. package/dist/client.mjs +843 -0
  21. package/dist/{config-DXypXAfN.d.ts → config-ChZ7lfqc.d.ts} +3 -3
  22. package/dist/direct-executor-YARCDMJF.mjs +8 -0
  23. package/dist/distribution/coordinator/etcd.d.ts +3 -3
  24. package/dist/distribution/coordinator/etcd.mjs +471 -2
  25. package/dist/distribution/coordinator/in-memory.d.ts +3 -3
  26. package/dist/distribution/coordinator/in-memory.mjs +286 -1
  27. package/dist/distribution/transport/grpc.d.ts +45 -0
  28. package/dist/distribution/transport/grpc.mjs +586 -0
  29. package/dist/distribution/transport/in-memory.d.ts +118 -0
  30. package/dist/distribution/transport/in-memory.mjs +214 -0
  31. package/dist/distribution/transport/tcp.d.ts +27 -0
  32. package/dist/distribution/transport/tcp.mjs +595 -0
  33. package/dist/distribution.d.ts +241 -192
  34. package/dist/distribution.mjs +6620 -4795
  35. package/dist/embeddings/openai.d.ts +1 -1
  36. package/dist/embeddings/openai.mjs +1 -1
  37. package/dist/{engine-CO9Wnfie.d.ts → engine-DScGlT2Z.d.ts} +30 -3
  38. package/dist/index.browser.mjs +10035 -3914
  39. package/dist/index.d.ts +8 -8
  40. package/dist/index.mjs +8 -5
  41. package/dist/invalidation/broadcast-channel.d.ts +1 -1
  42. package/dist/invalidation/filesystem.d.ts +1 -1
  43. package/dist/invalidation/filesystem.mjs +3 -1
  44. package/dist/invalidation/noop.d.ts +1 -1
  45. package/dist/options-BORJg5XB.d.ts +234 -0
  46. package/dist/persistence/durability/checkpoint-worker.d.ts +4 -2
  47. package/dist/persistence/durability/checkpoint-worker.mjs +8 -5
  48. package/dist/react.d.ts +340 -0
  49. package/dist/react.mjs +687 -0
  50. package/dist/{schema-CE6S_aAr.d.ts → schema-emTQfEiX.d.ts} +21 -7
  51. package/dist/{search-DLBtiPdQ.d.ts → search-CQ-9bKxo.d.ts} +226 -14
  52. package/dist/server.d.ts +42 -356
  53. package/dist/server.mjs +493 -106
  54. package/dist/tasks-CnMLpfk-.d.ts +274 -0
  55. package/dist/types-BQDlIvfS.d.ts +34 -0
  56. package/dist/{types-BV3nAKTL.d.ts → types-Bfhhnh3G.d.ts} +23 -1
  57. package/dist/types-D5OwhtsQ.d.ts +97 -0
  58. package/dist/vector/hnsw-build-worker.d.ts +2 -7
  59. package/dist/vector/hnsw-build-worker.mjs +2 -1
  60. package/dist/vector/search-worker.d.ts +373 -0
  61. package/dist/vector/search-worker.mjs +279 -0
  62. package/dist/workers/entry.mjs +43 -25
  63. package/package.json +42 -2
  64. package/dist/chunk-FKK76OR7.mjs +0 -456
  65. package/dist/chunk-RQLXC2YS.mjs +0 -269
  66. package/dist/direct-executor-3W4QRA4E.mjs +0 -5
@@ -0,0 +1,595 @@
1
+ import { DEFAULT_TCP_CONFIG, encodeTransportMessage, encodeFrame, FRAME_TYPE_REQUEST, FrameParser, FRAME_TYPE_RESPONSE, decodeTransportMessage, FRAME_TYPE_STREAM_CHUNK, FRAME_TYPE_STREAM_END } from '../../chunk-MFFAJ2NR.mjs';
2
+ import { MAX_MESSAGE_SIZE_BYTES, TransportError, TransportErrorCodes } from '../../chunk-C6VVLMRX.mjs';
3
+ import { connect as connect$1, createServer as createServer$1 } from 'net';
4
+ import { connect, createServer } from 'tls';
5
+
6
+ // src/distribution/transport/tcp/parse-address.ts
7
+ function parseAddress(address) {
8
+ const lastColon = address.lastIndexOf(":");
9
+ if (lastColon === -1) {
10
+ throw new TransportError(
11
+ TransportErrorCodes.CONNECT_FAILED,
12
+ `Invalid address format '${address}', expected host:port`,
13
+ {
14
+ address
15
+ }
16
+ );
17
+ }
18
+ const host = address.slice(0, lastColon);
19
+ const port = address.slice(lastColon + 1);
20
+ if (host.length === 0 || host.includes("\0")) {
21
+ throw new TransportError(TransportErrorCodes.CONNECT_FAILED, `Invalid host in address '${address}'`, { address });
22
+ }
23
+ return [host, port];
24
+ }
25
+
26
+ // src/distribution/transport/tcp/connection.ts
27
+ var TcpConnectionPool = class {
28
+ connections = /* @__PURE__ */ new Map();
29
+ pendingRequests = /* @__PURE__ */ new Map();
30
+ pendingStreams = /* @__PURE__ */ new Map();
31
+ parsers = /* @__PURE__ */ new Map();
32
+ config;
33
+ closed = false;
34
+ constructor(config) {
35
+ this.config = config;
36
+ }
37
+ updateTlsConfig(nextTlsConfig) {
38
+ this.config = {
39
+ ...this.config,
40
+ tls: nextTlsConfig
41
+ };
42
+ }
43
+ async send(target, message) {
44
+ if (this.closed) {
45
+ throw new TransportError(TransportErrorCodes.PEER_UNAVAILABLE, "Connection pool has been shut down");
46
+ }
47
+ const messageBytes = encodeTransportMessage(message);
48
+ if (messageBytes.byteLength > MAX_MESSAGE_SIZE_BYTES) {
49
+ throw new TransportError(
50
+ TransportErrorCodes.MESSAGE_TOO_LARGE,
51
+ `Message payload (${messageBytes.byteLength} bytes) exceeds the ${MAX_MESSAGE_SIZE_BYTES} byte limit`,
52
+ { target, requestId: message.requestId, payloadSize: messageBytes.byteLength }
53
+ );
54
+ }
55
+ const socket = await this.getOrCreateConnection(target);
56
+ const frame = encodeFrame(FRAME_TYPE_REQUEST, message.requestId, messageBytes);
57
+ const pendingKey = `${target}:${message.requestId}`;
58
+ return new Promise((resolve, reject) => {
59
+ const timer = setTimeout(() => {
60
+ this.pendingRequests.delete(pendingKey);
61
+ reject(
62
+ new TransportError(
63
+ TransportErrorCodes.TIMEOUT,
64
+ `Request to '${target}' timed out after ${this.config.requestTimeout}ms`,
65
+ {
66
+ target,
67
+ requestId: message.requestId,
68
+ timeoutMs: this.config.requestTimeout
69
+ }
70
+ )
71
+ );
72
+ }, this.config.requestTimeout);
73
+ this.pendingRequests.set(pendingKey, { target, resolve, reject, timer });
74
+ socket.write(frame, (err) => {
75
+ if (err) {
76
+ clearTimeout(timer);
77
+ this.pendingRequests.delete(pendingKey);
78
+ reject(
79
+ new TransportError(TransportErrorCodes.PEER_UNAVAILABLE, `Failed to write to '${target}': ${err.message}`, {
80
+ target,
81
+ requestId: message.requestId
82
+ })
83
+ );
84
+ }
85
+ });
86
+ });
87
+ }
88
+ async stream(target, message, handler) {
89
+ if (this.closed) {
90
+ throw new TransportError(TransportErrorCodes.PEER_UNAVAILABLE, "Connection pool has been shut down");
91
+ }
92
+ const messageBytes = encodeTransportMessage(message);
93
+ const socket = await this.getOrCreateConnection(target);
94
+ const frame = encodeFrame(FRAME_TYPE_REQUEST, message.requestId, messageBytes);
95
+ const pendingKey = `${target}:${message.requestId}`;
96
+ return new Promise((resolve, reject) => {
97
+ const timer = setTimeout(() => {
98
+ this.pendingStreams.delete(pendingKey);
99
+ reject(
100
+ new TransportError(
101
+ TransportErrorCodes.TIMEOUT,
102
+ `Stream to '${target}' timed out after ${this.config.snapshotTimeout}ms`,
103
+ {
104
+ target,
105
+ requestId: message.requestId,
106
+ timeoutMs: this.config.snapshotTimeout
107
+ }
108
+ )
109
+ );
110
+ }, this.config.snapshotTimeout);
111
+ this.pendingStreams.set(pendingKey, { target, handler, resolve, reject, timer });
112
+ socket.write(frame, (err) => {
113
+ if (err) {
114
+ clearTimeout(timer);
115
+ this.pendingStreams.delete(pendingKey);
116
+ reject(
117
+ new TransportError(
118
+ TransportErrorCodes.PEER_UNAVAILABLE,
119
+ `Failed to write stream to '${target}': ${err.message}`,
120
+ {
121
+ target,
122
+ requestId: message.requestId
123
+ }
124
+ )
125
+ );
126
+ }
127
+ });
128
+ });
129
+ }
130
+ async getOrCreateConnection(target) {
131
+ const existing = this.connections.get(target);
132
+ if (existing !== void 0 && !existing.destroyed) {
133
+ return existing;
134
+ }
135
+ const [host, portStr] = parseAddress(target);
136
+ const port = Number.parseInt(portStr, 10);
137
+ if (Number.isNaN(port) || port < 0 || port > 65535) {
138
+ throw new TransportError(TransportErrorCodes.CONNECT_FAILED, `Invalid port in target address '${target}'`, {
139
+ target
140
+ });
141
+ }
142
+ return new Promise((resolve, reject) => {
143
+ let settled = false;
144
+ const tlsConfig = this.config.tls;
145
+ const socket = tlsConfig !== void 0 ? connect({
146
+ host,
147
+ port,
148
+ cert: tlsConfig.cert,
149
+ key: tlsConfig.key,
150
+ ca: tlsConfig.ca,
151
+ rejectUnauthorized: tlsConfig.rejectUnauthorized ?? true
152
+ }) : connect$1({ host, port });
153
+ const connectEvent = tlsConfig !== void 0 ? "secureConnect" : "connect";
154
+ const connectTimer = setTimeout(() => {
155
+ if (!settled) {
156
+ settled = true;
157
+ socket.destroy();
158
+ reject(
159
+ new TransportError(
160
+ TransportErrorCodes.TIMEOUT,
161
+ `Connection to '${target}' timed out after ${this.config.connectTimeout}ms`,
162
+ { target, timeoutMs: this.config.connectTimeout }
163
+ )
164
+ );
165
+ }
166
+ }, this.config.connectTimeout);
167
+ socket.once(connectEvent, () => {
168
+ if (settled) {
169
+ socket.destroy();
170
+ return;
171
+ }
172
+ settled = true;
173
+ clearTimeout(connectTimer);
174
+ this.setupConnection(target, socket);
175
+ resolve(socket);
176
+ });
177
+ socket.once("error", (err) => {
178
+ if (!settled) {
179
+ settled = true;
180
+ clearTimeout(connectTimer);
181
+ reject(
182
+ new TransportError(TransportErrorCodes.CONNECT_FAILED, `Failed to connect to '${target}': ${err.message}`, {
183
+ target
184
+ })
185
+ );
186
+ }
187
+ });
188
+ });
189
+ }
190
+ setupConnection(target, socket) {
191
+ this.connections.set(target, socket);
192
+ const parser = new FrameParser((frame) => {
193
+ this.handleIncomingFrame(target, frame);
194
+ });
195
+ this.parsers.set(target, parser);
196
+ socket.on("data", (data) => {
197
+ try {
198
+ parser.feed(new Uint8Array(data));
199
+ } catch (err) {
200
+ this.handleConnectionError(target, err instanceof Error ? err : new Error(String(err)));
201
+ }
202
+ });
203
+ socket.on("error", (err) => {
204
+ this.handleConnectionError(target, err);
205
+ });
206
+ socket.on("close", () => {
207
+ this.connections.delete(target);
208
+ this.parsers.delete(target);
209
+ this.rejectPendingForTarget(
210
+ target,
211
+ new TransportError(
212
+ TransportErrorCodes.PEER_UNAVAILABLE,
213
+ `Connection to '${target}' closed before a response was received`,
214
+ { target }
215
+ )
216
+ );
217
+ });
218
+ }
219
+ handleIncomingFrame(target, frame) {
220
+ const pendingKey = `${target}:${frame.requestId}`;
221
+ if (frame.frameType === FRAME_TYPE_RESPONSE) {
222
+ const pendingReq = this.pendingRequests.get(pendingKey);
223
+ if (pendingReq !== void 0) {
224
+ this.pendingRequests.delete(pendingKey);
225
+ clearTimeout(pendingReq.timer);
226
+ try {
227
+ const message = decodeTransportMessage(frame.data);
228
+ pendingReq.resolve(message);
229
+ } catch (err) {
230
+ pendingReq.reject(
231
+ new TransportError(
232
+ TransportErrorCodes.DECODE_FAILED,
233
+ `Failed to decode response: ${err instanceof Error ? err.message : String(err)}`
234
+ )
235
+ );
236
+ }
237
+ return;
238
+ }
239
+ const pendingStream = this.pendingStreams.get(pendingKey);
240
+ if (pendingStream !== void 0) {
241
+ try {
242
+ const message = decodeTransportMessage(frame.data);
243
+ pendingStream.handler(message.payload);
244
+ } catch (err) {
245
+ this.pendingStreams.delete(pendingKey);
246
+ clearTimeout(pendingStream.timer);
247
+ pendingStream.reject(
248
+ new TransportError(
249
+ TransportErrorCodes.DECODE_FAILED,
250
+ `Failed to decode stream frame: ${err instanceof Error ? err.message : String(err)}`,
251
+ { target, requestId: frame.requestId }
252
+ )
253
+ );
254
+ }
255
+ }
256
+ return;
257
+ }
258
+ if (frame.frameType === FRAME_TYPE_STREAM_CHUNK) {
259
+ const pending = this.pendingStreams.get(pendingKey);
260
+ if (pending !== void 0) {
261
+ pending.handler(frame.data);
262
+ }
263
+ return;
264
+ }
265
+ if (frame.frameType === FRAME_TYPE_STREAM_END) {
266
+ const pending = this.pendingStreams.get(pendingKey);
267
+ if (pending !== void 0) {
268
+ this.pendingStreams.delete(pendingKey);
269
+ clearTimeout(pending.timer);
270
+ pending.resolve();
271
+ }
272
+ }
273
+ }
274
+ handleConnectionError(target, err) {
275
+ const socket = this.connections.get(target);
276
+ this.connections.delete(target);
277
+ this.parsers.delete(target);
278
+ if (socket !== void 0 && !socket.destroyed) {
279
+ socket.destroy();
280
+ }
281
+ this.rejectPendingForTarget(
282
+ target,
283
+ new TransportError(TransportErrorCodes.PEER_UNAVAILABLE, `Connection to '${target}' lost: ${err.message}`, {
284
+ target
285
+ })
286
+ );
287
+ }
288
+ rejectPendingForTarget(target, error) {
289
+ for (const [pendingKey, pending] of this.pendingRequests) {
290
+ if (pending.target !== target) {
291
+ continue;
292
+ }
293
+ clearTimeout(pending.timer);
294
+ this.pendingRequests.delete(pendingKey);
295
+ pending.reject(error);
296
+ }
297
+ for (const [pendingKey, pending] of this.pendingStreams) {
298
+ if (pending.target !== target) {
299
+ continue;
300
+ }
301
+ clearTimeout(pending.timer);
302
+ this.pendingStreams.delete(pendingKey);
303
+ pending.reject(error);
304
+ }
305
+ }
306
+ getConnection(target) {
307
+ const conn = this.connections.get(target);
308
+ if (conn?.destroyed) {
309
+ this.connections.delete(target);
310
+ return void 0;
311
+ }
312
+ return conn;
313
+ }
314
+ async shutdown() {
315
+ if (this.closed) {
316
+ return;
317
+ }
318
+ this.closed = true;
319
+ for (const [, pending] of this.pendingRequests) {
320
+ clearTimeout(pending.timer);
321
+ pending.reject(new TransportError(TransportErrorCodes.PEER_UNAVAILABLE, "Connection pool shutting down"));
322
+ }
323
+ this.pendingRequests.clear();
324
+ for (const [, pending] of this.pendingStreams) {
325
+ clearTimeout(pending.timer);
326
+ pending.reject(new TransportError(TransportErrorCodes.PEER_UNAVAILABLE, "Connection pool shutting down"));
327
+ }
328
+ this.pendingStreams.clear();
329
+ const closePromises = [];
330
+ for (const [target, socket] of this.connections) {
331
+ closePromises.push(
332
+ new Promise((resolve) => {
333
+ socket.once("close", () => resolve());
334
+ socket.destroy();
335
+ })
336
+ );
337
+ this.connections.delete(target);
338
+ }
339
+ this.parsers.clear();
340
+ await Promise.all(closePromises);
341
+ }
342
+ };
343
+ function writeAwaitingDrain(socket, frame) {
344
+ if (socket.write(frame)) {
345
+ return Promise.resolve();
346
+ }
347
+ return new Promise((resolve) => {
348
+ socket.once("drain", resolve);
349
+ });
350
+ }
351
+ var TcpServer = class {
352
+ server = null;
353
+ clients = /* @__PURE__ */ new Set();
354
+ config;
355
+ handler = null;
356
+ closed = false;
357
+ boundPort = 0;
358
+ tlsServer = null;
359
+ constructor(config) {
360
+ this.config = config;
361
+ }
362
+ getPort() {
363
+ return this.boundPort;
364
+ }
365
+ updateTlsConfig(nextTlsConfig) {
366
+ this.config = {
367
+ ...this.config,
368
+ tls: nextTlsConfig
369
+ };
370
+ if (this.server === null) {
371
+ return;
372
+ }
373
+ if (this.tlsServer === null) {
374
+ throw new TransportError(
375
+ TransportErrorCodes.PEER_UNAVAILABLE,
376
+ "Cannot rotate TLS context on a server that was started without TLS"
377
+ );
378
+ }
379
+ this.tlsServer.setSecureContext(toSecureContextOptions(nextTlsConfig));
380
+ }
381
+ async start(handler) {
382
+ if (this.closed) {
383
+ throw new TransportError(TransportErrorCodes.PEER_UNAVAILABLE, "TCP server has been shut down");
384
+ }
385
+ const previousHandler = this.handler;
386
+ this.handler = handler;
387
+ if (this.server !== null) {
388
+ return () => {
389
+ if (this.handler === handler) {
390
+ this.handler = previousHandler ?? null;
391
+ }
392
+ };
393
+ }
394
+ return new Promise((resolve, reject) => {
395
+ const tlsConfig = this.config.tls;
396
+ const server = tlsConfig !== void 0 ? createServer(
397
+ {
398
+ cert: tlsConfig.cert,
399
+ key: tlsConfig.key,
400
+ ca: tlsConfig.ca,
401
+ requestCert: true,
402
+ rejectUnauthorized: tlsConfig.rejectUnauthorized ?? true
403
+ },
404
+ (clientSocket) => {
405
+ this.handleClient(clientSocket);
406
+ }
407
+ ) : createServer$1((clientSocket) => {
408
+ this.handleClient(clientSocket);
409
+ });
410
+ server.on("error", (err) => {
411
+ if (this.server === null) {
412
+ reject(new TransportError(TransportErrorCodes.CONNECT_FAILED, `TCP server failed to start: ${err.message}`));
413
+ }
414
+ });
415
+ server.listen(this.config.port, this.config.host, () => {
416
+ this.server = server;
417
+ this.tlsServer = tlsConfig !== void 0 ? server : null;
418
+ const addr = server.address();
419
+ if (addr !== null && typeof addr === "object") {
420
+ this.boundPort = addr.port;
421
+ }
422
+ resolve(() => {
423
+ if (this.handler === handler) {
424
+ this.handler = previousHandler ?? null;
425
+ }
426
+ });
427
+ });
428
+ });
429
+ }
430
+ handleClient(socket) {
431
+ if (this.clients.size >= this.config.maxConnections) {
432
+ socket.destroy();
433
+ return;
434
+ }
435
+ this.clients.add(socket);
436
+ const parser = new FrameParser((frame) => {
437
+ if (frame.frameType !== FRAME_TYPE_REQUEST) {
438
+ return;
439
+ }
440
+ if (this.handler === null) {
441
+ return;
442
+ }
443
+ this.processRequest(socket, frame, this.handler);
444
+ });
445
+ socket.on("data", (data) => {
446
+ try {
447
+ parser.feed(new Uint8Array(data));
448
+ } catch (_) {
449
+ socket.destroy();
450
+ }
451
+ });
452
+ socket.on("error", () => {
453
+ socket.destroy();
454
+ });
455
+ socket.on("close", () => {
456
+ this.clients.delete(socket);
457
+ });
458
+ }
459
+ processRequest(socket, frame, handler) {
460
+ try {
461
+ const message = decodeTransportMessage(frame.data);
462
+ let respondCount = 0;
463
+ const respond = (response) => {
464
+ if (socket.destroyed) {
465
+ return Promise.resolve();
466
+ }
467
+ respondCount++;
468
+ if (respondCount === 1) {
469
+ const responseBytes = encodeTransportMessage(response);
470
+ return writeAwaitingDrain(socket, encodeFrame(FRAME_TYPE_RESPONSE, frame.requestId, responseBytes));
471
+ }
472
+ return writeAwaitingDrain(socket, encodeFrame(FRAME_TYPE_STREAM_CHUNK, frame.requestId, response.payload));
473
+ };
474
+ const result = handler(message, respond);
475
+ const finalize = () => {
476
+ if (respondCount > 0 && !socket.destroyed) {
477
+ const endFrame = encodeFrame(FRAME_TYPE_STREAM_END, frame.requestId, new Uint8Array(0));
478
+ socket.write(endFrame);
479
+ }
480
+ };
481
+ if (result instanceof Promise) {
482
+ result.then(finalize, (err) => {
483
+ this.sendErrorResponse(socket, frame.requestId, err);
484
+ });
485
+ } else {
486
+ finalize();
487
+ }
488
+ } catch (err) {
489
+ this.sendErrorResponse(socket, frame.requestId, err);
490
+ }
491
+ }
492
+ sendErrorResponse(socket, requestId, err) {
493
+ if (socket.destroyed) {
494
+ return;
495
+ }
496
+ const errorMsg = err instanceof Error ? err.message : String(err);
497
+ const errorResponse = {
498
+ type: "error",
499
+ sourceId: "",
500
+ requestId,
501
+ payload: new TextEncoder().encode(errorMsg)
502
+ };
503
+ const responseBytes = encodeTransportMessage(errorResponse);
504
+ const responseFrame = encodeFrame(FRAME_TYPE_RESPONSE, requestId, responseBytes);
505
+ socket.write(responseFrame);
506
+ }
507
+ async shutdown() {
508
+ if (this.closed) {
509
+ return;
510
+ }
511
+ this.closed = true;
512
+ this.handler = null;
513
+ for (const client of this.clients) {
514
+ client.destroy();
515
+ }
516
+ this.clients.clear();
517
+ if (this.server !== null) {
518
+ await new Promise((resolve) => {
519
+ const server = this.server;
520
+ if (server === null) {
521
+ resolve();
522
+ return;
523
+ }
524
+ server.close(() => resolve());
525
+ });
526
+ this.server = null;
527
+ this.tlsServer = null;
528
+ }
529
+ }
530
+ };
531
+ function toSecureContextOptions(tlsConfig) {
532
+ return {
533
+ cert: tlsConfig.cert,
534
+ key: tlsConfig.key,
535
+ ca: tlsConfig.ca
536
+ };
537
+ }
538
+
539
+ // src/distribution/transport/tcp/index.ts
540
+ function createTcpTransport(nodeId, config) {
541
+ const resolvedConfig = {
542
+ ...DEFAULT_TCP_CONFIG,
543
+ ...config
544
+ };
545
+ const pool = new TcpConnectionPool(resolvedConfig);
546
+ const server = new TcpServer(resolvedConfig);
547
+ let isShutdown = false;
548
+ function assertNotShutdown() {
549
+ if (isShutdown) {
550
+ throw new TransportError(
551
+ TransportErrorCodes.PEER_UNAVAILABLE,
552
+ `TCP transport for node '${nodeId}' has been shut down`,
553
+ { nodeId }
554
+ );
555
+ }
556
+ }
557
+ return {
558
+ getPort() {
559
+ return server.getPort();
560
+ },
561
+ rotateTlsContext(nextTlsConfig) {
562
+ assertNotShutdown();
563
+ pool.updateTlsConfig(nextTlsConfig);
564
+ server.updateTlsConfig(nextTlsConfig);
565
+ },
566
+ async send(target, message) {
567
+ assertNotShutdown();
568
+ if (message.payload.byteLength > MAX_MESSAGE_SIZE_BYTES) {
569
+ throw new TransportError(
570
+ TransportErrorCodes.MESSAGE_TOO_LARGE,
571
+ `Message payload (${message.payload.byteLength} bytes) exceeds the ${MAX_MESSAGE_SIZE_BYTES} byte limit`,
572
+ { target, requestId: message.requestId, payloadSize: message.payload.byteLength }
573
+ );
574
+ }
575
+ return pool.send(target, message);
576
+ },
577
+ async stream(target, message, handler) {
578
+ assertNotShutdown();
579
+ return pool.stream(target, message, handler);
580
+ },
581
+ async listen(handler) {
582
+ assertNotShutdown();
583
+ return server.start(handler);
584
+ },
585
+ async shutdown() {
586
+ if (isShutdown) {
587
+ return;
588
+ }
589
+ isShutdown = true;
590
+ await Promise.all([pool.shutdown(), server.shutdown()]);
591
+ }
592
+ };
593
+ }
594
+
595
+ export { createTcpTransport };