@olane/o-node 0.7.55 → 0.7.57

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 (54) hide show
  1. package/dist/src/connection/enums/o-node-message-event.d.ts +14 -0
  2. package/dist/src/connection/enums/o-node-message-event.d.ts.map +1 -0
  3. package/dist/src/connection/enums/o-node-message-event.js +5 -0
  4. package/dist/src/connection/index.d.ts +0 -3
  5. package/dist/src/connection/index.d.ts.map +1 -1
  6. package/dist/src/connection/index.js +0 -3
  7. package/dist/src/connection/interfaces/abort-signal.config.d.ts +5 -0
  8. package/dist/src/connection/interfaces/abort-signal.config.d.ts.map +1 -0
  9. package/dist/src/connection/interfaces/o-node-connection-manager.config.d.ts +13 -1
  10. package/dist/src/connection/interfaces/o-node-connection-manager.config.d.ts.map +1 -1
  11. package/dist/src/connection/interfaces/o-node-connection.config.d.ts +18 -5
  12. package/dist/src/connection/interfaces/o-node-connection.config.d.ts.map +1 -1
  13. package/dist/src/connection/interfaces/o-node-stream.config.d.ts +3 -11
  14. package/dist/src/connection/interfaces/o-node-stream.config.d.ts.map +1 -1
  15. package/dist/src/connection/o-node-connection.d.ts +29 -53
  16. package/dist/src/connection/o-node-connection.d.ts.map +1 -1
  17. package/dist/src/connection/o-node-connection.js +102 -149
  18. package/dist/src/connection/o-node-connection.manager.d.ts +12 -8
  19. package/dist/src/connection/o-node-connection.manager.d.ts.map +1 -1
  20. package/dist/src/connection/o-node-connection.manager.js +49 -35
  21. package/dist/src/connection/o-node-stream.d.ts +48 -15
  22. package/dist/src/connection/o-node-stream.d.ts.map +1 -1
  23. package/dist/src/connection/o-node-stream.js +143 -31
  24. package/dist/src/connection/stream-handler.config.d.ts +0 -11
  25. package/dist/src/connection/stream-handler.config.d.ts.map +1 -1
  26. package/dist/src/lib/interfaces/o-node-request-manager.config.d.ts +9 -0
  27. package/dist/src/lib/interfaces/o-node-request-manager.config.d.ts.map +1 -0
  28. package/dist/src/lib/interfaces/o-node-request-manager.config.js +1 -0
  29. package/dist/src/lib/o-node-request-manager.d.ts +46 -0
  30. package/dist/src/lib/o-node-request-manager.d.ts.map +1 -0
  31. package/dist/src/lib/o-node-request-manager.js +173 -0
  32. package/dist/src/managers/o-reconnection.manager.d.ts.map +1 -1
  33. package/dist/src/managers/o-reconnection.manager.js +4 -0
  34. package/dist/src/managers/o-registration.manager.d.ts.map +1 -1
  35. package/dist/src/managers/o-registration.manager.js +9 -4
  36. package/dist/src/o-node.d.ts +6 -7
  37. package/dist/src/o-node.d.ts.map +1 -1
  38. package/dist/src/o-node.js +22 -37
  39. package/dist/src/o-node.tool.d.ts +3 -3
  40. package/dist/src/o-node.tool.d.ts.map +1 -1
  41. package/dist/src/o-node.tool.js +28 -56
  42. package/dist/src/router/o-node.router.d.ts.map +1 -1
  43. package/dist/src/router/o-node.router.js +4 -2
  44. package/dist/test/connection-management.spec.js +3 -0
  45. package/package.json +7 -7
  46. package/dist/src/connection/interfaces/stream-init-message.d.ts +0 -64
  47. package/dist/src/connection/interfaces/stream-init-message.d.ts.map +0 -1
  48. package/dist/src/connection/interfaces/stream-init-message.js +0 -18
  49. package/dist/src/connection/interfaces/stream-manager.config.d.ts +0 -8
  50. package/dist/src/connection/interfaces/stream-manager.config.d.ts.map +0 -1
  51. package/dist/src/connection/o-node-stream.manager.d.ts +0 -210
  52. package/dist/src/connection/o-node-stream.manager.d.ts.map +0 -1
  53. package/dist/src/connection/o-node-stream.manager.js +0 -696
  54. /package/dist/src/connection/interfaces/{stream-manager.config.js → abort-signal.config.js} +0 -0
@@ -1,64 +0,0 @@
1
- /**
2
- * Message sent by limited connection clients to identify their dedicated persistent streams
3
- * This allows the receiver to identify which streams to use for bidirectional communication
4
- */
5
- export interface StreamInitMessage {
6
- /**
7
- * Message type identifier
8
- */
9
- type: 'stream-init';
10
- /**
11
- * Role of this stream
12
- * - 'reader': Dedicated reader stream for receiving requests from receiver
13
- * - 'writer': Dedicated writer stream for sending responses back to receiver
14
- * - 'standard': Standard request-response stream
15
- */
16
- role: 'reader' | 'writer' | 'standard';
17
- /**
18
- * Timestamp when the stream was created
19
- */
20
- timestamp: number;
21
- /**
22
- * Optional connection identifier for correlation
23
- */
24
- connectionId?: string;
25
- }
26
- /**
27
- * Type guard to check if a message is a StreamInitMessage
28
- */
29
- export declare function isStreamInitMessage(message: any): message is StreamInitMessage;
30
- /**
31
- * Acknowledgment message sent by receiver in response to stream-init
32
- * This confirms that the receiver has processed and registered the stream
33
- */
34
- export interface StreamInitAckMessage {
35
- /**
36
- * Message type identifier
37
- */
38
- type: 'stream-init-ack';
39
- /**
40
- * Status of the initialization
41
- */
42
- status: 'success' | 'error';
43
- /**
44
- * The stream ID that was registered
45
- */
46
- streamId: string;
47
- /**
48
- * The role that was registered
49
- */
50
- role: 'reader' | 'writer' | 'standard';
51
- /**
52
- * Optional error message if status is 'error'
53
- */
54
- error?: string;
55
- /**
56
- * Timestamp when the ack was sent
57
- */
58
- timestamp: number;
59
- }
60
- /**
61
- * Type guard to check if a message is a StreamInitAckMessage
62
- */
63
- export declare function isStreamInitAckMessage(message: any): message is StreamInitAckMessage;
64
- //# sourceMappingURL=stream-init-message.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stream-init-message.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/stream-init-message.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,IAAI,EAAE,aAAa,CAAC;IAEpB;;;;;OAKG;IACH,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;IAEvC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,IAAI,iBAAiB,CAM9E;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,IAAI,EAAE,iBAAiB,CAAC;IAExB;;OAEG;IACH,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAE5B;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;IAEvC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,GAAG,GACX,OAAO,IAAI,oBAAoB,CAQjC"}
@@ -1,18 +0,0 @@
1
- /**
2
- * Type guard to check if a message is a StreamInitMessage
3
- */
4
- export function isStreamInitMessage(message) {
5
- return (message?.type === 'stream-init' &&
6
- (message.role === 'reader' || message.role === 'writer' || message.role === 'standard') &&
7
- typeof message.timestamp === 'number');
8
- }
9
- /**
10
- * Type guard to check if a message is a StreamInitAckMessage
11
- */
12
- export function isStreamInitAckMessage(message) {
13
- return (message?.type === 'stream-init-ack' &&
14
- (message.status === 'success' || message.status === 'error') &&
15
- typeof message.streamId === 'string' &&
16
- (message.role === 'reader' || message.role === 'writer' || message.role === 'standard') &&
17
- typeof message.timestamp === 'number');
18
- }
@@ -1,8 +0,0 @@
1
- import type { Connection } from '@libp2p/interface';
2
- export interface StreamManagerConfig {
3
- /**
4
- * The libp2p connection this manager handles streams for
5
- */
6
- p2pConnection: Connection;
7
- }
8
- //# sourceMappingURL=stream-manager.config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stream-manager.config.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/stream-manager.config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,aAAa,EAAE,UAAU,CAAC;CAC3B"}
@@ -1,210 +0,0 @@
1
- /// <reference types="node" />
2
- import { EventEmitter } from 'events';
3
- import type { Connection, Stream } from '@libp2p/interface';
4
- import { oObject, oRequest, oResponse } from '@olane/o-core';
5
- import type { oRouterRequest, oConnection } from '@olane/o-core';
6
- import { oNodeStream } from './o-node-stream.js';
7
- import { StreamManagerConfig } from './interfaces/stream-manager.config.js';
8
- import type { StreamHandlerConfig } from './stream-handler.config.js';
9
- import { StreamManagerEvent, StreamManagerEventData } from './stream-manager.events.js';
10
- import { StreamInitMessage } from './interfaces/stream-init-message.js';
11
- /**
12
- * oNodeStreamManager handles the lifecycle and tracking of streams for a single connection.
13
- * Features:
14
- * - Tracks all streams by ID
15
- * - Creates new streams on demand
16
- * - Manages stream lifecycle (cleanup after use)
17
- * - Provides events for monitoring
18
- * - No reuse at base layer (extensible in subclasses)
19
- */
20
- export declare class oNodeStreamManager extends oObject {
21
- readonly config: StreamManagerConfig;
22
- private streams;
23
- protected eventEmitter: EventEmitter;
24
- isInitialized: boolean;
25
- private p2pConnection;
26
- private activeStreamHandlers;
27
- protected callerReaderStream?: Stream;
28
- protected callerWriterStream?: Stream;
29
- private streamMonitoringIntervals;
30
- private id;
31
- constructor(config: StreamManagerConfig);
32
- /**
33
- * Initialize the stream manager
34
- */
35
- initialize(): Promise<void>;
36
- /**
37
- * Gets or creates a stream for the connection
38
- * Always creates a new stream (no reuse at base layer)
39
- *
40
- * For limited connections (where caller has identified a reader stream):
41
- * - If callerReaderStream exists, wrap and return it for sending requests
42
- * - Otherwise, create new stream as normal
43
- *
44
- * @param protocol - The protocol string for the stream
45
- * @param remoteAddress - The remote address for the stream
46
- * @param config - Stream handler configuration
47
- * @returns Wrapped stream
48
- */
49
- getOrCreateStream(protocol: string, remoteAddress: any, config?: StreamHandlerConfig): Promise<oNodeStream>;
50
- /**
51
- * Creates a new stream from the connection
52
- *
53
- * @param protocol - The protocol string for the stream
54
- * @param remoteAddress - The remote address for the stream
55
- * @param config - Stream handler configuration
56
- * @returns Wrapped stream
57
- */
58
- createStream(protocol: string, remoteAddress: any, config?: StreamHandlerConfig): Promise<oNodeStream>;
59
- /**
60
- * Releases and cleans up a stream
61
- *
62
- * @param streamId - The ID of the stream to release
63
- */
64
- releaseStream(streamId: string): Promise<void>;
65
- /**
66
- * Gets all tracked streams
67
- *
68
- * @returns Array of wrapped streams
69
- */
70
- getAllStreams(): oNodeStream[];
71
- /**
72
- * Gets a stream by its ID
73
- * Checks persistent caller streams (reader/writer) and tracked streams
74
- *
75
- * @param streamId - The ID of the stream to retrieve
76
- * @returns The libp2p Stream or undefined if not found
77
- */
78
- getStreamById(streamId: string): Stream | undefined;
79
- /**
80
- * Sets up monitoring for stream closure and emits events when detected
81
- * Periodically checks stream status and cleans up when stream closes
82
- *
83
- * @param stream - The stream to monitor
84
- * @param role - The role of the stream ('reader' or 'writer')
85
- */
86
- private setupStreamCloseMonitoring;
87
- /**
88
- * Emits an async event and waits for the first listener to return a result
89
- * This enables event-based request handling with async responses
90
- */
91
- private emitAsync;
92
- /**
93
- * Detects if a decoded message is a request
94
- * Requests have a 'method' field and no 'result' field
95
- */
96
- isRequest(message: any): boolean;
97
- /**
98
- * Detects if a decoded message is a response
99
- * Responses have a 'result' field and no 'method' field
100
- */
101
- isResponse(message: any): boolean;
102
- /**
103
- * Detects if a decoded message is a stream initialization message
104
- * Uses the imported type guard from stream-init-message.ts
105
- */
106
- isStreamInit(message: any): message is StreamInitMessage;
107
- /**
108
- * Handles a stream initialization message
109
- * Stores reference to caller's reader stream for bidirectional communication
110
- * Sends acknowledgment back to confirm stream registration
111
- *
112
- * @param message - The decoded stream init message
113
- * @param stream - The stream that sent the message
114
- */
115
- protected handleStreamInitMessage(message: StreamInitMessage, stream: Stream): Promise<void>;
116
- /**
117
- * Extracts and parses JSON from various formats including:
118
- * - Already parsed objects
119
- * - Plain JSON
120
- * - Markdown code blocks (```json ... ``` or ``` ... ```)
121
- * - Mixed content with explanatory text
122
- * - JSON5 format (trailing commas, comments, unquoted keys, etc.)
123
- *
124
- * @param decoded - The decoded string that may contain JSON, or an already parsed object
125
- * @returns Parsed JSON object
126
- * @throws Error if JSON parsing fails even with JSON5 fallback
127
- */
128
- protected extractAndParseJSON(decoded: string | any): any;
129
- /**
130
- * Sends data through a stream using length-prefixed encoding (libp2p v3 best practice)
131
- * Each message is automatically prefixed with a varint indicating the message length
132
- * This ensures proper message boundaries and eliminates concatenation issues
133
- *
134
- * @param stream - The stream to send data through
135
- * @param data - The data to send
136
- * @param config - Configuration for timeout and other options
137
- */
138
- sendLengthPrefixed(stream: Stream, data: Uint8Array, config?: StreamHandlerConfig): Promise<void>;
139
- /**
140
- * Tracks an active stream handler
141
- */
142
- private trackStreamHandler;
143
- /**
144
- * Untracks a stream handler
145
- */
146
- private untrackStreamHandler;
147
- /**
148
- * Handles an incoming stream on the server side using length-prefixed protocol
149
- * Uses async read loops instead of event listeners (libp2p v3 best practice)
150
- * Processes complete messages with proper boundaries
151
- *
152
- * @param stream - The incoming stream
153
- * @param connection - The connection the stream belongs to
154
- */
155
- handleIncomingStream(stream: Stream, connection: Connection): Promise<void>;
156
- /**
157
- * Determines which stream to use for sending the response
158
- * Checks for _streamId in request params and routes accordingly
159
- *
160
- * @param request - The incoming request
161
- * @param defaultStream - The stream the request came on (fallback)
162
- * @returns The stream to use for the response
163
- */
164
- protected getResponseStream(request: oRequest, defaultStream: Stream): Stream;
165
- /**
166
- * Handles a request message by emitting an event and sending response
167
- *
168
- * @param message - The decoded request message
169
- * @param stream - The stream to send the response on
170
- * @param connection - The connection the stream belongs to
171
- */
172
- protected handleRequestMessage(message: any, stream: Stream, connection: Connection): Promise<void>;
173
- /**
174
- * Handles an outgoing stream on the client side using length-prefixed protocol
175
- * Uses async read loops to process responses with proper message boundaries
176
- *
177
- * @param stream - The outgoing stream
178
- * @param emitter - Event emitter for chunk events
179
- * @param config - Configuration including abort signal
180
- * @param requestId - Optional request ID to filter responses (for stream reuse scenarios)
181
- * @returns Promise that resolves with the final response
182
- */
183
- handleOutgoingStream(stream: Stream, emitter: EventEmitter, config?: StreamHandlerConfig, requestId?: string | number): Promise<oResponse>;
184
- /**
185
- * Forwards a request to the next hop and relays response chunks back
186
- * This implements the middleware/proxy pattern for intermediate nodes
187
- *
188
- * @param request - The router request to forward
189
- * @param incomingStream - The stream to send responses back on
190
- * @param dialFn - Function to dial the next hop connection
191
- */
192
- forwardRequest(request: oRouterRequest, incomingStream: Stream, dialFn: (address: string) => Promise<oConnection>): Promise<void>;
193
- /**
194
- * Close the stream manager and cleanup resources
195
- */
196
- close(): Promise<void>;
197
- /**
198
- * Add event listener
199
- */
200
- on<K extends StreamManagerEvent>(event: K | string, listener: (data: StreamManagerEventData[K]) => void): void;
201
- /**
202
- * Remove event listener
203
- */
204
- off<K extends StreamManagerEvent>(event: K | string, listener: (data: StreamManagerEventData[K]) => void): void;
205
- /**
206
- * Emit event
207
- */
208
- private emit;
209
- }
210
- //# sourceMappingURL=o-node-stream.manager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"o-node-stream.manager.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-stream.manager.ts"],"names":[],"mappings":"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"}