@olane/o-node 0.7.50 → 0.7.52

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 (46) hide show
  1. package/dist/src/connection/index.d.ts +6 -1
  2. package/dist/src/connection/index.d.ts.map +1 -1
  3. package/dist/src/connection/index.js +6 -1
  4. package/dist/src/connection/interfaces/o-node-stream.config.d.ts +16 -0
  5. package/dist/src/connection/interfaces/o-node-stream.config.d.ts.map +1 -0
  6. package/dist/src/connection/interfaces/stream-init-message.d.ts +29 -0
  7. package/dist/src/connection/interfaces/stream-init-message.d.ts.map +1 -0
  8. package/dist/src/connection/interfaces/stream-init-message.js +8 -0
  9. package/dist/src/connection/interfaces/stream-manager.config.d.ts +8 -0
  10. package/dist/src/connection/interfaces/stream-manager.config.d.ts.map +1 -0
  11. package/dist/src/connection/interfaces/stream-manager.config.js +1 -0
  12. package/dist/src/connection/o-node-connection.d.ts +5 -7
  13. package/dist/src/connection/o-node-connection.d.ts.map +1 -1
  14. package/dist/src/connection/o-node-connection.js +26 -56
  15. package/dist/src/connection/o-node-connection.manager.d.ts +7 -0
  16. package/dist/src/connection/o-node-connection.manager.d.ts.map +1 -1
  17. package/dist/src/connection/o-node-connection.manager.js +23 -5
  18. package/dist/src/connection/{o-node-connection-stream.d.ts → o-node-stream.d.ts} +18 -6
  19. package/dist/src/connection/o-node-stream.d.ts.map +1 -0
  20. package/dist/src/connection/{o-node-connection-stream.js → o-node-stream.js} +20 -2
  21. package/dist/src/connection/o-node-stream.manager.d.ts +181 -0
  22. package/dist/src/connection/o-node-stream.manager.d.ts.map +1 -0
  23. package/dist/src/connection/o-node-stream.manager.js +526 -0
  24. package/dist/src/connection/stream-manager.events.d.ts +83 -0
  25. package/dist/src/connection/stream-manager.events.d.ts.map +1 -0
  26. package/dist/src/connection/stream-manager.events.js +18 -0
  27. package/dist/src/o-node.tool.d.ts +0 -1
  28. package/dist/src/o-node.tool.d.ts.map +1 -1
  29. package/dist/src/o-node.tool.js +30 -20
  30. package/dist/test/connection-management.spec.js +24 -24
  31. package/dist/test/helpers/stream-pool-test-helpers.d.ts +1 -0
  32. package/dist/test/helpers/stream-pool-test-helpers.d.ts.map +1 -0
  33. package/dist/test/helpers/stream-pool-test-helpers.js +262 -0
  34. package/dist/test/network-communication.spec.js +68 -66
  35. package/dist/test/parent-child-registration.spec.js +1 -0
  36. package/dist/test/stream-pool-manager.spec.d.ts +1 -0
  37. package/dist/test/stream-pool-manager.spec.d.ts.map +1 -0
  38. package/dist/test/stream-pool-manager.spec.js +424 -0
  39. package/package.json +7 -7
  40. package/dist/src/connection/interfaces/o-node-connection-stream.config.d.ts +0 -8
  41. package/dist/src/connection/interfaces/o-node-connection-stream.config.d.ts.map +0 -1
  42. package/dist/src/connection/o-node-connection-stream.d.ts.map +0 -1
  43. package/dist/src/connection/stream-handler.d.ts +0 -102
  44. package/dist/src/connection/stream-handler.d.ts.map +0 -1
  45. package/dist/src/connection/stream-handler.js +0 -357
  46. /package/dist/src/connection/interfaces/{o-node-connection-stream.config.js → o-node-stream.config.js} +0 -0
@@ -0,0 +1,424 @@
1
+ "use strict";
2
+ // import { expect } from 'chai';
3
+ // import { StreamPoolManager } from '../src/connection/stream-pool-manager.js';
4
+ // import { NetworkBuilder, NetworkTopologies } from './helpers/network-builder.js';
5
+ // import { createConnectionSpy } from './helpers/connection-spy.js';
6
+ // import { StreamPoolEvent } from '../src/connection/stream-pool-manager.events.js';
7
+ // import { oNodeConnectionStream } from '../src/connection/o-node-connection-stream.js';
8
+ // import type { TestTool } from './helpers/network-builder.js';
9
+ // import type { Connection } from '@olane/o-config';
10
+ // /**
11
+ // * Integration tests for StreamPoolManager using real libp2p nodes and connections
12
+ // */
13
+ // describe('StreamPoolManager Integration Tests', () => {
14
+ // let builder: NetworkBuilder;
15
+ // let leader: TestTool;
16
+ // let child: TestTool;
17
+ // let p2pConnection: Connection;
18
+ // let poolManager: StreamPoolManager | undefined;
19
+ // /**
20
+ // * Helper to create a real libp2p connection between two nodes
21
+ // */
22
+ // async function getP2pConnection(): Promise<Connection> {
23
+ // // Make a call to establish connection
24
+ // await leader.use(child.address, {
25
+ // method: 'echo',
26
+ // params: { message: 'establish connection' }
27
+ // });
28
+ // // Get the connection
29
+ // const connections = leader.p2pNode.getConnections();
30
+ // const connection = connections.find(
31
+ // conn => conn.remotePeer.toString() === child.peerId.toString()
32
+ // );
33
+ // if (!connection) {
34
+ // throw new Error('Failed to establish connection between nodes');
35
+ // }
36
+ // return connection;
37
+ // }
38
+ // /**
39
+ // * Helper to create a StreamPoolManager with real connection
40
+ // */
41
+ // async function createStreamPoolManager(config?: Partial<any>): Promise<StreamPoolManager> {
42
+ // const manager = new StreamPoolManager({
43
+ // poolSize: config?.poolSize || 10,
44
+ // readerStreamIndex: config?.readerStreamIndex ?? 0,
45
+ // streamHandler: {
46
+ // handleIncomingStream: config?.streamHandler?.handleIncomingStream || (async (stream: any) => {
47
+ // // Default handler: just keep stream alive
48
+ // return new Promise(() => {}); // Never resolves (keeps reader active)
49
+ // })
50
+ // },
51
+ // p2pConnection,
52
+ // requestHandler: config?.requestHandler,
53
+ // createStream: async () => {
54
+ // // Create a real libp2p stream
55
+ // const stream = await p2pConnection.newStream('/o-protocol/1.0.0');
56
+ // return new oNodeConnectionStream({
57
+ // p2pStream: stream,
58
+ // streamType: 'request-response',
59
+ // readTimeoutMs: 30000,
60
+ // drainTimeoutMs: 5000,
61
+ // });
62
+ // },
63
+ // ...config,
64
+ // });
65
+ // return manager;
66
+ // }
67
+ // beforeEach(async () => {
68
+ // // Create real node network
69
+ // builder = await NetworkTopologies.twoNode();
70
+ // leader = builder.getNode('o://leader')!;
71
+ // child = builder.getNode('o://child')!;
72
+ // // Establish real p2p connection
73
+ // p2pConnection = await getP2pConnection();
74
+ // });
75
+ // afterEach(async () => {
76
+ // if (poolManager) {
77
+ // await poolManager.close();
78
+ // poolManager = undefined;
79
+ // }
80
+ // await builder.cleanup();
81
+ // });
82
+ // describe('Initialization', () => {
83
+ // it('should initialize pool with default size of 10 streams', async () => {
84
+ // poolManager = await createStreamPoolManager();
85
+ // await poolManager.initialize();
86
+ // const stats = poolManager.getStats();
87
+ // expect(stats.totalStreams).to.equal(10);
88
+ // });
89
+ // it('should initialize pool with custom size', async () => {
90
+ // poolManager = await createStreamPoolManager({ poolSize: 5 });
91
+ // await poolManager.initialize();
92
+ // const stats = poolManager.getStats();
93
+ // expect(stats.totalStreams).to.equal(5);
94
+ // });
95
+ // it('should throw error when pool size is less than 2', async () => {
96
+ // expect(() => {
97
+ // poolManager = new StreamPoolManager({
98
+ // poolSize: 1,
99
+ // readerStreamIndex: 0,
100
+ // streamHandler: {} as any,
101
+ // p2pConnection,
102
+ // createStream: async () => ({} as any),
103
+ // });
104
+ // }).to.throw('Pool size must be at least 2');
105
+ // });
106
+ // it('should start dedicated reader automatically', async () => {
107
+ // let readerStarted = false;
108
+ // poolManager = await createStreamPoolManager();
109
+ // poolManager.on(StreamPoolEvent.ReaderStarted, () => {
110
+ // readerStarted = true;
111
+ // });
112
+ // await poolManager.initialize();
113
+ // // Wait a bit for reader to start
114
+ // await new Promise(resolve => setTimeout(resolve, 100));
115
+ // expect(readerStarted).to.be.true;
116
+ // });
117
+ // it('should emit pool-initialized event', async () => {
118
+ // let eventData: any;
119
+ // poolManager = await createStreamPoolManager();
120
+ // poolManager.on(StreamPoolEvent.PoolInitialized, (data: any) => {
121
+ // eventData = data;
122
+ // });
123
+ // await poolManager.initialize();
124
+ // expect(eventData).to.exist;
125
+ // expect(eventData.poolSize).to.equal(10);
126
+ // });
127
+ // it('should be idempotent (calling initialize twice is safe)', async () => {
128
+ // poolManager = await createStreamPoolManager();
129
+ // await poolManager.initialize();
130
+ // const statsFirst = poolManager.getStats();
131
+ // await poolManager.initialize();
132
+ // const statsSecond = poolManager.getStats();
133
+ // expect(statsFirst.totalStreams).to.equal(statsSecond.totalStreams);
134
+ // expect(statsSecond.totalStreams).to.equal(10);
135
+ // });
136
+ // it('should assign correct stream types', async () => {
137
+ // poolManager = await createStreamPoolManager({ poolSize: 3 });
138
+ // await poolManager.initialize();
139
+ // const stats = poolManager.getStats();
140
+ // expect(stats.requestResponseStreams).to.equal(2); // All except stream[0]
141
+ // });
142
+ // });
143
+ // describe('Round-Robin Stream Selection', () => {
144
+ // beforeEach(async () => {
145
+ // poolManager = await createStreamPoolManager({ poolSize: 5 });
146
+ // await poolManager.initialize();
147
+ // });
148
+ // it('should return streams in round-robin order', async () => {
149
+ // const stream1 = await poolManager!.getStream();
150
+ // const stream2 = await poolManager!.getStream();
151
+ // const stream3 = await poolManager!.getStream();
152
+ // const stream4 = await poolManager!.getStream();
153
+ // // Should cycle through streams[1-4]
154
+ // expect(stream1.p2pStream.id).to.not.equal(stream2.p2pStream.id);
155
+ // expect(stream2.p2pStream.id).to.not.equal(stream3.p2pStream.id);
156
+ // expect(stream3.p2pStream.id).to.not.equal(stream4.p2pStream.id);
157
+ // });
158
+ // it('should wrap around after last stream', async () => {
159
+ // // Pool size is 5, so we have streams 1-4 for request-response (4 streams total)
160
+ // const firstRound: any[] = [];
161
+ // for (let i = 0; i < 4; i++) {
162
+ // firstRound.push(await poolManager!.getStream());
163
+ // }
164
+ // const nextStream = await poolManager!.getStream();
165
+ // // Should wrap back to first request-response stream
166
+ // expect(nextStream.p2pStream.id).to.equal(firstRound[0].p2pStream.id);
167
+ // });
168
+ // it('should throw error when getStream called before initialize', async () => {
169
+ // const uninitializedManager = await createStreamPoolManager();
170
+ // try {
171
+ // await uninitializedManager.getStream();
172
+ // expect.fail('Should have thrown error');
173
+ // } catch (error: any) {
174
+ // expect(error.message).to.include('not initialized');
175
+ // } finally {
176
+ // await uninitializedManager.close();
177
+ // }
178
+ // });
179
+ // });
180
+ // describe('Stream Validation and Replacement', () => {
181
+ // it('should detect invalid stream and replace it', async () => {
182
+ // poolManager = await createStreamPoolManager({ poolSize: 3 });
183
+ // await poolManager.initialize();
184
+ // // Get first stream and forcibly close it
185
+ // const firstStream = await poolManager.getStream();
186
+ // await firstStream.p2pStream.close();
187
+ // // Wait for stream to be marked invalid
188
+ // await new Promise(resolve => setTimeout(resolve, 100));
189
+ // // Next getStream should detect and replace the invalid stream
190
+ // const nextStream = await poolManager.getStream();
191
+ // expect(nextStream.isValid).to.be.true;
192
+ // });
193
+ // it('should emit stream-replaced event when replacing stream', async () => {
194
+ // let replacedEventFired = false;
195
+ // poolManager = await createStreamPoolManager({ poolSize: 3 });
196
+ // poolManager.on(StreamPoolEvent.StreamReplaced, () => {
197
+ // replacedEventFired = true;
198
+ // });
199
+ // await poolManager.initialize();
200
+ // // Close a request-response stream
201
+ // const stream = await poolManager.getStream();
202
+ // await stream.p2pStream.close();
203
+ // // Wait for detection and replacement
204
+ // await new Promise(resolve => setTimeout(resolve, 100));
205
+ // // Trigger getStream to force validation
206
+ // await poolManager.getStream();
207
+ // expect(replacedEventFired).to.be.true;
208
+ // });
209
+ // });
210
+ // describe('Dedicated Reader Recovery', () => {
211
+ // it('should detect reader failure and trigger recovery', async () => {
212
+ // let failureDetected = false;
213
+ // const mockStreamHandler = {
214
+ // handleIncomingStream: async () => {
215
+ // failureDetected = true;
216
+ // throw new Error('Reader stream failed');
217
+ // },
218
+ // };
219
+ // poolManager = await createStreamPoolManager({
220
+ // poolSize: 3,
221
+ // streamHandler: mockStreamHandler,
222
+ // });
223
+ // poolManager.on(StreamPoolEvent.ReaderFailed, () => {
224
+ // failureDetected = true;
225
+ // });
226
+ // await poolManager.initialize();
227
+ // // Wait for reader failure event
228
+ // await new Promise(resolve => setTimeout(resolve, 500));
229
+ // const stats = poolManager.getStats();
230
+ // expect(stats.failureCount).to.be.greaterThan(0);
231
+ // });
232
+ // it('should emit reader-recovered event on successful recovery', async () => {
233
+ // let callCount = 0;
234
+ // let recoveryEventFired = false;
235
+ // const mockStreamHandler = {
236
+ // handleIncomingStream: async () => {
237
+ // callCount++;
238
+ // if (callCount === 1) {
239
+ // throw new Error('Initial failure');
240
+ // }
241
+ // // Second call succeeds (recovery)
242
+ // return new Promise(() => {}); // Never resolves (keeps reader active)
243
+ // },
244
+ // };
245
+ // poolManager = await createStreamPoolManager({
246
+ // poolSize: 3,
247
+ // streamHandler: mockStreamHandler,
248
+ // });
249
+ // poolManager.on(StreamPoolEvent.ReaderRecovered, () => {
250
+ // recoveryEventFired = true;
251
+ // });
252
+ // await poolManager.initialize();
253
+ // // Wait for recovery
254
+ // await new Promise(resolve => setTimeout(resolve, 1000));
255
+ // expect(recoveryEventFired).to.be.true;
256
+ // });
257
+ // it('should not attempt recovery during close', async () => {
258
+ // let recoveryAttempted = false;
259
+ // const mockStreamHandler = {
260
+ // handleIncomingStream: async () => {
261
+ // await new Promise((resolve) => setTimeout(resolve, 50));
262
+ // throw new Error('Reader failed');
263
+ // },
264
+ // };
265
+ // poolManager = await createStreamPoolManager({
266
+ // poolSize: 3,
267
+ // streamHandler: mockStreamHandler,
268
+ // });
269
+ // poolManager.on(StreamPoolEvent.ReaderRecovered, () => {
270
+ // recoveryAttempted = true;
271
+ // });
272
+ // await poolManager.initialize();
273
+ // // Close immediately
274
+ // await poolManager.close();
275
+ // // Wait a bit
276
+ // await new Promise((resolve) => setTimeout(resolve, 200));
277
+ // // Should not have attempted recovery
278
+ // expect(recoveryAttempted).to.be.false;
279
+ // });
280
+ // });
281
+ // describe('Statistics', () => {
282
+ // it('should return accurate totalStreams count', async () => {
283
+ // poolManager = await createStreamPoolManager({ poolSize: 7 });
284
+ // await poolManager.initialize();
285
+ // const stats = poolManager.getStats();
286
+ // expect(stats.totalStreams).to.equal(7);
287
+ // });
288
+ // it('should return accurate healthyStreams count', async () => {
289
+ // poolManager = await createStreamPoolManager({ poolSize: 5 });
290
+ // await poolManager.initialize();
291
+ // const stats = poolManager.getStats();
292
+ // expect(stats.healthyStreams).to.be.greaterThan(0);
293
+ // });
294
+ // it('should report reader health status', async () => {
295
+ // poolManager = await createStreamPoolManager({ poolSize: 3 });
296
+ // await poolManager.initialize();
297
+ // const stats = poolManager.getStats();
298
+ // expect(stats.readerStreamHealth).to.be.oneOf([
299
+ // 'healthy',
300
+ // 'unhealthy',
301
+ // 'not-initialized',
302
+ // ]);
303
+ // });
304
+ // it('should track request-response stream count', async () => {
305
+ // poolManager = await createStreamPoolManager({ poolSize: 6 });
306
+ // await poolManager.initialize();
307
+ // const stats = poolManager.getStats();
308
+ // expect(stats.requestResponseStreams).to.equal(5); // 6 total - 1 reader
309
+ // });
310
+ // it('should increment failureCount on reader failures', async () => {
311
+ // let callCount = 0;
312
+ // const mockStreamHandler = {
313
+ // handleIncomingStream: async () => {
314
+ // callCount++;
315
+ // if (callCount <= 2) {
316
+ // throw new Error('Failure');
317
+ // }
318
+ // return new Promise(() => {}); // Then succeed
319
+ // },
320
+ // };
321
+ // poolManager = await createStreamPoolManager({
322
+ // poolSize: 3,
323
+ // streamHandler: mockStreamHandler,
324
+ // });
325
+ // await poolManager.initialize();
326
+ // // Wait for failures
327
+ // await new Promise(resolve => setTimeout(resolve, 1000));
328
+ // const stats = poolManager.getStats();
329
+ // expect(stats.failureCount).to.be.at.least(1);
330
+ // });
331
+ // });
332
+ // describe('Event Emission', () => {
333
+ // it('should emit all lifecycle events with correct data', async () => {
334
+ // let poolInitialized = false;
335
+ // let readerStarted = false;
336
+ // let poolClosed = false;
337
+ // poolManager = await createStreamPoolManager({ poolSize: 3 });
338
+ // poolManager.on(StreamPoolEvent.PoolInitialized, () => {
339
+ // poolInitialized = true;
340
+ // });
341
+ // poolManager.on(StreamPoolEvent.ReaderStarted, () => {
342
+ // readerStarted = true;
343
+ // });
344
+ // poolManager.on(StreamPoolEvent.PoolClosed, () => {
345
+ // poolClosed = true;
346
+ // });
347
+ // await poolManager.initialize();
348
+ // await new Promise(resolve => setTimeout(resolve, 100));
349
+ // await poolManager.close();
350
+ // expect(poolInitialized).to.be.true;
351
+ // expect(readerStarted).to.be.true;
352
+ // expect(poolClosed).to.be.true;
353
+ // });
354
+ // it('should support multiple listeners for same event', async () => {
355
+ // let listener1Called = false;
356
+ // let listener2Called = false;
357
+ // poolManager = await createStreamPoolManager({ poolSize: 3 });
358
+ // poolManager.on(StreamPoolEvent.PoolInitialized, () => {
359
+ // listener1Called = true;
360
+ // });
361
+ // poolManager.on(StreamPoolEvent.PoolInitialized, () => {
362
+ // listener2Called = true;
363
+ // });
364
+ // await poolManager.initialize();
365
+ // expect(listener1Called).to.be.true;
366
+ // expect(listener2Called).to.be.true;
367
+ // });
368
+ // it('should allow removing event listeners', async () => {
369
+ // let callCount = 0;
370
+ // const listener = () => {
371
+ // callCount++;
372
+ // };
373
+ // poolManager = await createStreamPoolManager({ poolSize: 3 });
374
+ // poolManager.on(StreamPoolEvent.PoolInitialized, listener);
375
+ // await poolManager.initialize();
376
+ // expect(callCount).to.equal(1);
377
+ // poolManager.off(StreamPoolEvent.PoolInitialized, listener);
378
+ // // Verify off doesn't throw
379
+ // expect(() =>
380
+ // poolManager!.off(StreamPoolEvent.PoolInitialized, listener),
381
+ // ).to.not.throw();
382
+ // });
383
+ // });
384
+ // describe('Cleanup and Lifecycle', () => {
385
+ // it('should close all streams on close()', async () => {
386
+ // poolManager = await createStreamPoolManager({ poolSize: 5 });
387
+ // await poolManager.initialize();
388
+ // const statsBefore = poolManager.getStats();
389
+ // expect(statsBefore.totalStreams).to.equal(5);
390
+ // await poolManager.close();
391
+ // const statsAfter = poolManager.getStats();
392
+ // expect(statsAfter.totalStreams).to.equal(0);
393
+ // });
394
+ // it('should emit pool-closed event', async () => {
395
+ // let closedEventFired = false;
396
+ // poolManager = await createStreamPoolManager({ poolSize: 3 });
397
+ // poolManager.on(StreamPoolEvent.PoolClosed, () => {
398
+ // closedEventFired = true;
399
+ // });
400
+ // await poolManager.initialize();
401
+ // await poolManager.close();
402
+ // expect(closedEventFired).to.be.true;
403
+ // });
404
+ // it('should be safe to call close() multiple times', async () => {
405
+ // poolManager = await createStreamPoolManager({ poolSize: 3 });
406
+ // await poolManager.initialize();
407
+ // await poolManager.close();
408
+ // await poolManager.close(); // Should not throw
409
+ // const stats = poolManager.getStats();
410
+ // expect(stats.totalStreams).to.equal(0);
411
+ // });
412
+ // it('should prevent getStream() after close()', async () => {
413
+ // poolManager = await createStreamPoolManager({ poolSize: 3 });
414
+ // await poolManager.initialize();
415
+ // await poolManager.close();
416
+ // try {
417
+ // await poolManager.getStream();
418
+ // expect.fail('Should have thrown error');
419
+ // } catch (error: any) {
420
+ // expect(error.message).to.include('not initialized');
421
+ // }
422
+ // });
423
+ // });
424
+ // });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olane/o-node",
3
- "version": "0.7.50",
3
+ "version": "0.7.52",
4
4
  "type": "module",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -40,7 +40,7 @@
40
40
  "devDependencies": {
41
41
  "@eslint/eslintrc": "^3.3.1",
42
42
  "@eslint/js": "^9.29.0",
43
- "@olane/o-test": "0.7.50",
43
+ "@olane/o-test": "0.7.52",
44
44
  "@tsconfig/node20": "^20.1.6",
45
45
  "@types/jest": "^30.0.0",
46
46
  "@types/json5": "^2.2.0",
@@ -60,13 +60,13 @@
60
60
  "typescript": "5.4.5"
61
61
  },
62
62
  "dependencies": {
63
- "@olane/o-config": "0.7.50",
64
- "@olane/o-core": "0.7.50",
65
- "@olane/o-protocol": "0.7.50",
66
- "@olane/o-tool": "0.7.50",
63
+ "@olane/o-config": "0.7.52",
64
+ "@olane/o-core": "0.7.52",
65
+ "@olane/o-protocol": "0.7.52",
66
+ "@olane/o-tool": "0.7.52",
67
67
  "debug": "^4.4.1",
68
68
  "dotenv": "^16.5.0",
69
69
  "json5": "^2.2.3"
70
70
  },
71
- "gitHead": "55f5464185ef16a164fa23dc46c0c08b317419a0"
71
+ "gitHead": "706ee0d5b546e96b6c05270b39035ee7e08dadbd"
72
72
  }
@@ -1,8 +0,0 @@
1
- import { oAddress } from '@olane/o-core';
2
- import { StreamReusePolicy } from '../stream-handler.config';
3
- export interface oNodeConnectionStreamConfig {
4
- direction: 'inbound' | 'outbound';
5
- reusePolicy: StreamReusePolicy;
6
- remoteAddress: oAddress;
7
- }
8
- //# sourceMappingURL=o-node-connection-stream.config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"o-node-connection-stream.config.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/o-node-connection-stream.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,SAAS,GAAG,UAAU,CAAC;IAClC,WAAW,EAAE,iBAAiB,CAAC;IAC/B,aAAa,EAAE,QAAQ,CAAC;CACzB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"o-node-connection-stream.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAuB,OAAO,EAAiB,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,2BAA2B,EAAE,MAAM,iDAAiD,CAAC;AAE9F;;;;;;;;GAQG;AACH,qBAAa,qBAAsB,SAAQ,OAAO;aAI9B,SAAS,EAAE,MAAM;aACjB,MAAM,EAAE,2BAA2B;IAJrD,SAAgB,SAAS,EAAE,MAAM,CAAC;gBAGhB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,2BAA2B;IAOrD,QAAQ;IA6BR;;;;;;;OAOG;IACH,IAAI,OAAO,IAAI,OAAO,CAMrB;IAED;;OAEG;IACH,IAAI,GAAG,IAAI,MAAM,CAEhB;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAgB7B"}
@@ -1,102 +0,0 @@
1
- /// <reference types="node" />
2
- import type { Connection, Stream } from '@libp2p/interface';
3
- import { EventEmitter } from 'events';
4
- import { oRequest, oResponse, Logger } from '@olane/o-core';
5
- import type { oRouterRequest } from '@olane/o-core';
6
- import type { oConnection } from '@olane/o-core';
7
- import type { RunResult } from '@olane/o-tool';
8
- import type { StreamHandlerConfig } from './stream-handler.config.js';
9
- /**
10
- * StreamHandler centralizes all stream-related functionality including:
11
- * - Message type detection (request vs response)
12
- * - Stream lifecycle management (create, reuse, close)
13
- * - Backpressure handling
14
- * - Request/response handling
15
- * - Stream routing for middleware nodes
16
- */
17
- export declare class StreamHandler {
18
- private logger;
19
- constructor(logger?: Logger);
20
- /**
21
- * Detects if a decoded message is a request
22
- * Requests have a 'method' field and no 'result' field
23
- */
24
- isRequest(message: any): boolean;
25
- /**
26
- * Detects if a decoded message is a response
27
- * Responses have a 'result' field and no 'method' field
28
- */
29
- isResponse(message: any): boolean;
30
- /**
31
- * Extracts and parses JSON from various formats including:
32
- * - Already parsed objects
33
- * - Plain JSON
34
- * - Markdown code blocks (```json ... ``` or ``` ... ```)
35
- * - Mixed content with explanatory text
36
- * - JSON5 format (trailing commas, comments, unquoted keys, etc.)
37
- *
38
- * @param decoded - The decoded string that may contain JSON, or an already parsed object
39
- * @returns Parsed JSON object
40
- * @throws Error if JSON parsing fails even with JSON5 fallback
41
- */
42
- private extractAndParseJSON;
43
- /**
44
- * Builds a bidirectional cache key from caller and receiver addresses
45
- * The key is symmetric: A↔B === B↔A
46
- *
47
- * @param callerAddress - The caller's address
48
- * @param receiverAddress - The receiver's address
49
- * @returns Cache key string
50
- */
51
- private buildCacheKey;
52
- /**
53
- * Sends data through a stream using length-prefixed encoding (libp2p v3 best practice)
54
- * Each message is automatically prefixed with a varint indicating the message length
55
- * This ensures proper message boundaries and eliminates concatenation issues
56
- *
57
- * @param stream - The stream to send data through
58
- * @param data - The data to send
59
- * @param config - Configuration for timeout and other options
60
- */
61
- sendLengthPrefixed(stream: Stream, data: Uint8Array, config?: StreamHandlerConfig): Promise<void>;
62
- /**
63
- * Handles an incoming stream on the server side using length-prefixed protocol
64
- * Uses async read loops instead of event listeners (libp2p v3 best practice)
65
- * Processes complete messages with proper boundaries
66
- *
67
- * @param stream - The incoming stream
68
- * @param connection - The connection the stream belongs to
69
- * @param toolExecutor - Function to execute tools for requests
70
- */
71
- handleIncomingStream(stream: Stream, connection: Connection, toolExecutor: (request: oRequest, stream: Stream) => Promise<RunResult>): Promise<void>;
72
- /**
73
- * Handles a request message by executing the tool and sending response
74
- *
75
- * @param message - The decoded request message
76
- * @param stream - The stream to send the response on
77
- * @param toolExecutor - Function to execute the tool
78
- */
79
- private handleRequestMessage;
80
- /**
81
- * Handles an outgoing stream on the client side using length-prefixed protocol
82
- * Uses async read loops to process responses with proper message boundaries
83
- *
84
- * @param stream - The outgoing stream
85
- * @param emitter - Event emitter for chunk events
86
- * @param config - Configuration including abort signal
87
- * @param requestHandler - Optional handler for processing router requests received on this stream
88
- * @param requestId - Optional request ID to filter responses (for stream reuse scenarios)
89
- * @returns Promise that resolves with the final response
90
- */
91
- handleOutgoingStream(stream: Stream, emitter: EventEmitter, config?: StreamHandlerConfig, requestHandler?: (request: oRequest, stream: Stream) => Promise<RunResult>, requestId?: string | number): Promise<oResponse>;
92
- /**
93
- * Forwards a request to the next hop and relays response chunks back
94
- * This implements the middleware/proxy pattern for intermediate nodes
95
- *
96
- * @param request - The router request to forward
97
- * @param incomingStream - The stream to send responses back on
98
- * @param dialFn - Function to dial the next hop connection
99
- */
100
- forwardRequest(request: oRouterRequest, incomingStream: Stream, dialFn: (address: string) => Promise<oConnection>): Promise<void>;
101
- }
102
- //# sourceMappingURL=stream-handler.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stream-handler.d.ts","sourceRoot":"","sources":["../../../src/connection/stream-handler.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EACL,QAAQ,EACR,SAAS,EAIT,MAAM,EAEP,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EACV,mBAAmB,EAEpB,MAAM,4BAA4B,CAAC;AAKpC;;;;;;;GAOG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,CAAC,EAAE,MAAM;IAI3B;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO;IAIhC;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO;IAIjC;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,mBAAmB;IAqC3B;;;;;;;OAOG;IACH,OAAO,CAAC,aAAa;IA0HrB;;;;;;;;OAQG;IACG,kBAAkB,CACtB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,UAAU,EAChB,MAAM,GAAE,mBAAwB,GAC/B,OAAO,CAAC,IAAI,CAAC;IAKhB;;;;;;;;OAQG;IACG,oBAAoB,CACxB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,GACtE,OAAO,CAAC,IAAI,CAAC;IA+BhB;;;;;;OAMG;YACW,oBAAoB;IA6BlC;;;;;;;;;;OAUG;IACG,oBAAoB,CACxB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,YAAY,EACrB,MAAM,GAAE,mBAAwB,EAChC,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,EAC1E,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAC1B,OAAO,CAAC,SAAS,CAAC;IAiErB;;;;;;;OAOG;IACG,cAAc,CAClB,OAAO,EAAE,cAAc,EACvB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,GAChD,OAAO,CAAC,IAAI,CAAC;CAyBjB"}