@olane/o-node 0.7.39 → 0.7.41
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/src/connection/index.d.ts +2 -0
- package/dist/src/connection/index.d.ts.map +1 -1
- package/dist/src/connection/index.js +2 -0
- package/dist/src/connection/interfaces/o-node-connection-stream.config.d.ts +8 -0
- package/dist/src/connection/interfaces/o-node-connection-stream.config.d.ts.map +1 -0
- package/dist/src/connection/interfaces/o-node-connection-stream.config.js +1 -0
- package/dist/src/connection/o-node-connection-stream.d.ts +34 -0
- package/dist/src/connection/o-node-connection-stream.d.ts.map +1 -0
- package/dist/src/connection/o-node-connection-stream.js +68 -0
- package/dist/src/connection/o-node-connection.d.ts +10 -4
- package/dist/src/connection/o-node-connection.d.ts.map +1 -1
- package/dist/src/connection/o-node-connection.js +51 -26
- package/dist/src/connection/o-node-connection.manager.d.ts +4 -0
- package/dist/src/connection/o-node-connection.manager.d.ts.map +1 -1
- package/dist/src/connection/o-node-connection.manager.js +24 -0
- package/dist/src/connection/stream-handler.config.d.ts +11 -0
- package/dist/src/connection/stream-handler.config.d.ts.map +1 -1
- package/dist/src/connection/stream-handler.d.ts +6 -12
- package/dist/src/connection/stream-handler.d.ts.map +1 -1
- package/dist/src/connection/stream-handler.js +112 -62
- package/dist/src/o-node.tool.d.ts +3 -1
- package/dist/src/o-node.tool.d.ts.map +1 -1
- package/dist/src/o-node.tool.js +44 -6
- package/dist/src/router/o-node.address.d.ts +1 -0
- package/dist/src/router/o-node.address.d.ts.map +1 -1
- package/dist/src/router/o-node.address.js +4 -0
- package/dist/src/utils/connection.utils.d.ts +9 -0
- package/dist/src/utils/connection.utils.d.ts.map +1 -0
- package/dist/src/utils/connection.utils.js +26 -0
- package/dist/src/utils/index.d.ts +1 -0
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +1 -0
- package/dist/test/astream-reuse.spec.d.ts +2 -0
- package/dist/test/astream-reuse.spec.d.ts.map +1 -0
- package/dist/test/astream-reuse.spec.js +107 -0
- package/dist/test/connection-management.spec.js +1 -0
- package/dist/test/helpers/network-builder.d.ts.map +1 -1
- package/package.json +7 -7
|
@@ -2,4 +2,6 @@ export * from './o-node-connection.js';
|
|
|
2
2
|
export * from './o-node-connection.manager.js';
|
|
3
3
|
export * from './interfaces/o-node-connection.config.js';
|
|
4
4
|
export * from './interfaces/o-node-connection-manager.config.js';
|
|
5
|
+
export * from './o-node-connection-stream.js';
|
|
6
|
+
export * from './stream-handler.config.js';
|
|
5
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/connection/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0CAA0C,CAAC;AACzD,cAAc,kDAAkD,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/connection/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0CAA0C,CAAC;AACzD,cAAc,kDAAkD,CAAC;AACjE,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC"}
|
|
@@ -2,3 +2,5 @@ export * from './o-node-connection.js';
|
|
|
2
2
|
export * from './o-node-connection.manager.js';
|
|
3
3
|
export * from './interfaces/o-node-connection.config.js';
|
|
4
4
|
export * from './interfaces/o-node-connection-manager.config.js';
|
|
5
|
+
export * from './o-node-connection-stream.js';
|
|
6
|
+
export * from './stream-handler.config.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Stream } from '@libp2p/interface';
|
|
2
|
+
import { oObject } from '@olane/o-core';
|
|
3
|
+
import { oNodeConnectionStreamConfig } from './interfaces/o-node-connection-stream.config.js';
|
|
4
|
+
/**
|
|
5
|
+
* oNodeConnectionStream wraps a libp2p Stream with caller/receiver address metadata
|
|
6
|
+
* to enable proper stream reuse based on address pairs rather than protocol only.
|
|
7
|
+
*
|
|
8
|
+
* Key features:
|
|
9
|
+
* - Bidirectional cache keys: A↔B === B↔A
|
|
10
|
+
* - Automatic reusability checking
|
|
11
|
+
* - Idle time tracking for cleanup
|
|
12
|
+
*/
|
|
13
|
+
export declare class oNodeConnectionStream extends oObject {
|
|
14
|
+
readonly p2pStream: Stream;
|
|
15
|
+
readonly config: oNodeConnectionStreamConfig;
|
|
16
|
+
readonly createdAt: number;
|
|
17
|
+
constructor(p2pStream: Stream, config: oNodeConnectionStreamConfig);
|
|
18
|
+
validate(): void;
|
|
19
|
+
/**
|
|
20
|
+
* Checks if the stream is in a valid state:
|
|
21
|
+
* - Stream status is 'open'
|
|
22
|
+
* - Write status is 'writable'
|
|
23
|
+
* - Remote read status is 'readable'
|
|
24
|
+
*
|
|
25
|
+
* @returns true if stream can be used
|
|
26
|
+
*/
|
|
27
|
+
get isValid(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Gets the age of the stream in milliseconds
|
|
30
|
+
*/
|
|
31
|
+
get age(): number;
|
|
32
|
+
close(): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=o-node-connection-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { oError, oErrorCodes, oObject } from '@olane/o-core';
|
|
2
|
+
/**
|
|
3
|
+
* oNodeConnectionStream wraps a libp2p Stream with caller/receiver address metadata
|
|
4
|
+
* to enable proper stream reuse based on address pairs rather than protocol only.
|
|
5
|
+
*
|
|
6
|
+
* Key features:
|
|
7
|
+
* - Bidirectional cache keys: A↔B === B↔A
|
|
8
|
+
* - Automatic reusability checking
|
|
9
|
+
* - Idle time tracking for cleanup
|
|
10
|
+
*/
|
|
11
|
+
export class oNodeConnectionStream extends oObject {
|
|
12
|
+
constructor(p2pStream, config) {
|
|
13
|
+
super();
|
|
14
|
+
this.p2pStream = p2pStream;
|
|
15
|
+
this.config = config;
|
|
16
|
+
this.createdAt = Date.now();
|
|
17
|
+
}
|
|
18
|
+
// callable pattern to disrupt flow if not in valid state
|
|
19
|
+
validate() {
|
|
20
|
+
// do nothing
|
|
21
|
+
if (!this.p2pStream ||
|
|
22
|
+
(this.p2pStream.status !== 'open' && this.p2pStream.status !== 'reset')) {
|
|
23
|
+
throw new oError(oErrorCodes.FAILED_TO_DIAL_TARGET, 'Failed to dial target');
|
|
24
|
+
}
|
|
25
|
+
if (this.p2pStream.status === 'reset') {
|
|
26
|
+
this.logger.debug('P2P stream failed to create, status:', this.p2pStream.status);
|
|
27
|
+
throw new oError(oErrorCodes.CONNECTION_LIMIT_REACHED, 'Connection limit reached or configuration prevented stream creation');
|
|
28
|
+
}
|
|
29
|
+
if (!this.isValid) {
|
|
30
|
+
throw new oError(oErrorCodes.INVALID_STATE, 'Session is not in a valid state');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Checks if the stream is in a valid state:
|
|
35
|
+
* - Stream status is 'open'
|
|
36
|
+
* - Write status is 'writable'
|
|
37
|
+
* - Remote read status is 'readable'
|
|
38
|
+
*
|
|
39
|
+
* @returns true if stream can be used
|
|
40
|
+
*/
|
|
41
|
+
get isValid() {
|
|
42
|
+
return (this.p2pStream.status === 'open' &&
|
|
43
|
+
this.p2pStream.writeStatus === 'writable' &&
|
|
44
|
+
this.p2pStream.remoteReadStatus === 'readable');
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Gets the age of the stream in milliseconds
|
|
48
|
+
*/
|
|
49
|
+
get age() {
|
|
50
|
+
return Date.now() - this.createdAt;
|
|
51
|
+
}
|
|
52
|
+
async close() {
|
|
53
|
+
// Don't close if reuse policy is enabled
|
|
54
|
+
if (this.config.reusePolicy === 'reuse') {
|
|
55
|
+
this.logger.debug('Stream reuse enabled, not closing stream');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (this.p2pStream.status === 'open') {
|
|
59
|
+
try {
|
|
60
|
+
// force the close for now until we can implement a proper close
|
|
61
|
+
await this.p2pStream.abort(new Error('Stream closed'));
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
this.logger.debug('Error closing stream:', error.message);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -1,18 +1,24 @@
|
|
|
1
|
-
import { Connection
|
|
1
|
+
import { Connection } from '@olane/o-config';
|
|
2
2
|
import { oConnection, oRequest, oResponse } from '@olane/o-core';
|
|
3
3
|
import { oNodeConnectionConfig } from './interfaces/o-node-connection.config.js';
|
|
4
4
|
import { StreamHandler } from './stream-handler.js';
|
|
5
5
|
import type { StreamReusePolicy } from './stream-handler.config.js';
|
|
6
|
+
import { oNodeAddress } from '../router/o-node.address.js';
|
|
7
|
+
import { oNodeConnectionStream } from './o-node-connection-stream.js';
|
|
6
8
|
export declare class oNodeConnection extends oConnection {
|
|
7
9
|
protected readonly config: oNodeConnectionConfig;
|
|
8
10
|
p2pConnection: Connection;
|
|
9
11
|
protected streamHandler: StreamHandler;
|
|
10
12
|
protected reusePolicy: StreamReusePolicy;
|
|
11
13
|
constructor(config: oNodeConnectionConfig);
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
get remotePeerId(): import("@olane/o-config").PeerId;
|
|
15
|
+
get remoteAddr(): import("@olane/o-config").Multiaddr;
|
|
16
|
+
supportsAddress(address: oNodeAddress): boolean;
|
|
17
|
+
getOrCreateStream(): Promise<oNodeConnectionStream>;
|
|
18
|
+
createStream(): Promise<oNodeConnectionStream>;
|
|
19
|
+
get streams(): oNodeConnectionStream[];
|
|
14
20
|
transmit(request: oRequest): Promise<oResponse>;
|
|
15
|
-
postTransmit(stream:
|
|
21
|
+
postTransmit(stream: oNodeConnectionStream): Promise<void>;
|
|
16
22
|
abort(error: Error): Promise<void>;
|
|
17
23
|
close(): Promise<void>;
|
|
18
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"o-node-connection.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"o-node-connection.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAU,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAEL,WAAW,EAGX,QAAQ,EACR,SAAS,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAGtE,qBAAa,eAAgB,SAAQ,WAAW;IAKlC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB;IAJrD,aAAa,EAAE,UAAU,CAAC;IACjC,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;IACvC,SAAS,CAAC,WAAW,EAAE,iBAAiB,CAAC;gBAEV,MAAM,EAAE,qBAAqB;IAO5D,IAAI,YAAY,qCAEf;IAED,IAAI,UAAU,wCAEb;IAED,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO;IAMzC,iBAAiB,IAAI,OAAO,CAAC,qBAAqB,CAAC;IAanD,YAAY,IAAI,OAAO,CAAC,qBAAqB,CAAC;IA6BpD,IAAI,OAAO,IAAI,qBAAqB,EAAE,CAcrC;IAEK,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IA6C/C,YAAY,CAAC,MAAM,EAAE,qBAAqB;IAI1C,KAAK,CAAC,KAAK,EAAE,KAAK;IAMlB,KAAK;CAKZ"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { oConnection, oError, oErrorCodes, } from '@olane/o-core';
|
|
2
2
|
import { StreamHandler } from './stream-handler.js';
|
|
3
|
+
import { oNodeConnectionStream } from './o-node-connection-stream.js';
|
|
3
4
|
export class oNodeConnection extends oConnection {
|
|
4
5
|
constructor(config) {
|
|
5
6
|
super(config);
|
|
@@ -8,37 +9,64 @@ export class oNodeConnection extends oConnection {
|
|
|
8
9
|
this.streamHandler = new StreamHandler(this.logger);
|
|
9
10
|
this.reusePolicy = config.reusePolicy ?? 'none';
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
12
|
+
get remotePeerId() {
|
|
13
|
+
return this.p2pConnection.remotePeer;
|
|
14
|
+
}
|
|
15
|
+
get remoteAddr() {
|
|
16
|
+
return this.p2pConnection.remoteAddr;
|
|
17
|
+
}
|
|
18
|
+
supportsAddress(address) {
|
|
19
|
+
return address.libp2pTransports.some((transport) => {
|
|
20
|
+
return transport.toString() === this.remoteAddr.toString();
|
|
21
|
+
});
|
|
22
22
|
}
|
|
23
23
|
async getOrCreateStream() {
|
|
24
|
-
|
|
24
|
+
if (this.reusePolicy === 'reuse' && this.streams.length > 0) {
|
|
25
|
+
this.logger.debug('Returning reuse stream: ', this.streams[0].p2pStream.protocol);
|
|
26
|
+
// search for streams that allow re-use
|
|
27
|
+
return this.streams[0];
|
|
28
|
+
}
|
|
29
|
+
return this.createStream();
|
|
30
|
+
}
|
|
31
|
+
async createStream() {
|
|
32
|
+
const protocol = this.nextHopAddress.protocol +
|
|
33
|
+
(this.reusePolicy === 'reuse' ? '/reuse' : ''); // connect specifically to the reuse protocol version if desired
|
|
34
|
+
this.logger.debug('Creating stream for protocol:', protocol);
|
|
35
|
+
const stream = await this.p2pConnection.newStream(protocol, {
|
|
25
36
|
signal: this.abortSignal,
|
|
26
37
|
maxOutboundStreams: process.env.MAX_OUTBOUND_STREAMS
|
|
27
38
|
? parseInt(process.env.MAX_OUTBOUND_STREAMS)
|
|
28
39
|
: 1000,
|
|
29
40
|
runOnLimitedConnection: this.config.runOnLimitedConnection ?? true,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
41
|
+
});
|
|
42
|
+
const managedStream = new oNodeConnectionStream(stream, {
|
|
43
|
+
direction: stream.direction,
|
|
44
|
+
reusePolicy: this.config.reusePolicy ?? 'none', // default to no re-use stream
|
|
45
|
+
remoteAddress: this.nextHopAddress,
|
|
46
|
+
});
|
|
47
|
+
// print the num streams
|
|
48
|
+
const numStreams = this.streams.map((s) => s.isValid).length;
|
|
49
|
+
this.logger.debug(`Connection spawned new stream: ${stream.id}. Connection now has ${numStreams} total streams open`);
|
|
50
|
+
return managedStream;
|
|
51
|
+
}
|
|
52
|
+
get streams() {
|
|
53
|
+
return (this.p2pConnection?.streams
|
|
54
|
+
?.filter((s) => {
|
|
55
|
+
return s.protocol.includes('/o/');
|
|
56
|
+
})
|
|
57
|
+
.map((s) => {
|
|
58
|
+
return new oNodeConnectionStream(s, {
|
|
59
|
+
direction: s.direction,
|
|
60
|
+
reusePolicy: this.config.reusePolicy ?? 'none', // default to no re-use stream
|
|
61
|
+
remoteAddress: this.nextHopAddress,
|
|
62
|
+
});
|
|
63
|
+
}) || []);
|
|
34
64
|
}
|
|
35
65
|
async transmit(request) {
|
|
36
66
|
try {
|
|
37
|
-
// if (this.config.runOnLimitedConnection) {
|
|
38
|
-
// this.logger.debug('Running on limited connection...');
|
|
39
|
-
// }
|
|
40
67
|
const stream = await this.getOrCreateStream();
|
|
41
|
-
|
|
68
|
+
// ensure stream is valid
|
|
69
|
+
stream.validate();
|
|
42
70
|
const streamConfig = {
|
|
43
71
|
signal: this.abortSignal,
|
|
44
72
|
drainTimeoutMs: this.config.drainTimeoutMs,
|
|
@@ -46,11 +74,11 @@ export class oNodeConnection extends oConnection {
|
|
|
46
74
|
};
|
|
47
75
|
// Send the request with backpressure handling
|
|
48
76
|
const data = new TextEncoder().encode(request.toString());
|
|
49
|
-
await this.streamHandler.sendLengthPrefixed(stream, data, streamConfig);
|
|
77
|
+
await this.streamHandler.sendLengthPrefixed(stream.p2pStream, data, streamConfig);
|
|
50
78
|
// Handle response using StreamHandler
|
|
51
79
|
// Pass request handler if configured to enable bidirectional stream processing
|
|
52
80
|
// Pass request ID to enable proper response correlation on shared streams
|
|
53
|
-
const response = await this.streamHandler.handleOutgoingStream(stream, this.emitter, streamConfig, this.config.requestHandler, request.id);
|
|
81
|
+
const response = await this.streamHandler.handleOutgoingStream(stream.p2pStream, this.emitter, streamConfig, this.config.requestHandler, request.id);
|
|
54
82
|
// Handle cleanup of the stream
|
|
55
83
|
await this.postTransmit(stream);
|
|
56
84
|
return response;
|
|
@@ -63,10 +91,7 @@ export class oNodeConnection extends oConnection {
|
|
|
63
91
|
}
|
|
64
92
|
}
|
|
65
93
|
async postTransmit(stream) {
|
|
66
|
-
|
|
67
|
-
reusePolicy: this.reusePolicy,
|
|
68
|
-
};
|
|
69
|
-
await this.streamHandler.close(stream, streamConfig);
|
|
94
|
+
await stream.close();
|
|
70
95
|
}
|
|
71
96
|
async abort(error) {
|
|
72
97
|
this.logger.debug('Aborting connection');
|
|
@@ -30,6 +30,10 @@ export declare class oNodeConnectionManager extends oConnectionManager {
|
|
|
30
30
|
private getPeerIdFromAddress;
|
|
31
31
|
getOrCreateConnection(nextHopAddress: oAddress, address: oAddress): Promise<Connection>;
|
|
32
32
|
private performDial;
|
|
33
|
+
answer(config: oConnectionConfig & {
|
|
34
|
+
p2pConnection: Connection;
|
|
35
|
+
reuse?: boolean;
|
|
36
|
+
}): Promise<oNodeConnection>;
|
|
33
37
|
/**
|
|
34
38
|
* Connect to a given address, reusing libp2p connections when possible
|
|
35
39
|
* @param config - Connection configuration
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"o-node-connection.manager.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAU,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,kDAAkD,CAAC;AAEhG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,qBAAa,sBAAuB,SAAQ,kBAAkB;IAQhD,QAAQ,CAAC,MAAM,EAAE,4BAA4B;IAPzD,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,oBAAoB,CAAC,CAAS;IACtC,OAAO,CAAC,qBAAqB,CAAC,CAAS;IACvC,OAAO,CAAC,yBAAyB,CAAsC;IACvE,OAAO,CAAC,0BAA0B,CACtB;gBAES,MAAM,EAAE,4BAA4B;IAWzD;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAsBhC;;;;;;OAMG;IACH,OAAO,CAAC,0BAA0B;IAiBlC;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAatB,qBAAqB,CACzB,cAAc,EAAE,QAAQ,EACxB,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,UAAU,CAAC;YA+DR,WAAW;
|
|
1
|
+
{"version":3,"file":"o-node-connection.manager.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAU,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,kDAAkD,CAAC;AAEhG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,qBAAa,sBAAuB,SAAQ,kBAAkB;IAQhD,QAAQ,CAAC,MAAM,EAAE,4BAA4B;IAPzD,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,oBAAoB,CAAC,CAAS;IACtC,OAAO,CAAC,qBAAqB,CAAC,CAAS;IACvC,OAAO,CAAC,yBAAyB,CAAsC;IACvE,OAAO,CAAC,0BAA0B,CACtB;gBAES,MAAM,EAAE,4BAA4B;IAWzD;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAsBhC;;;;;;OAMG;IACH,OAAO,CAAC,0BAA0B;IAiBlC;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAatB,qBAAqB,CACzB,cAAc,EAAE,QAAQ,EACxB,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,UAAU,CAAC;YA+DR,WAAW;IAwBnB,MAAM,CACV,MAAM,EAAE,iBAAiB,GAAG;QAAE,aAAa,EAAE,UAAU,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GACzE,OAAO,CAAC,eAAe,CAAC;IAmC3B;;;;OAIG;IACG,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC;IA8BlE;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO;IAwCpC;;;;OAIG;IACH,yBAAyB,CAAC,OAAO,EAAE,QAAQ,GAAG,UAAU,GAAG,IAAI;IA+C/D;;;OAGG;IACH,aAAa,IAAI;QACf,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;QACrB,iBAAiB,EAAE,KAAK,CAAC;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC9D;IAaD;;;OAGG;IACH,uBAAuB,IAAI,MAAM;CAgBlC"}
|
|
@@ -130,6 +130,30 @@ export class oNodeConnectionManager extends oConnectionManager {
|
|
|
130
130
|
});
|
|
131
131
|
return connection;
|
|
132
132
|
}
|
|
133
|
+
async answer(config) {
|
|
134
|
+
const { address, nextHopAddress, callerAddress, readTimeoutMs, drainTimeoutMs, p2pConnection, reuse, } = config;
|
|
135
|
+
const connection = new oNodeConnection({
|
|
136
|
+
nextHopAddress: nextHopAddress,
|
|
137
|
+
address: address,
|
|
138
|
+
p2pConnection: p2pConnection,
|
|
139
|
+
callerAddress: callerAddress,
|
|
140
|
+
readTimeoutMs: readTimeoutMs ?? this.defaultReadTimeoutMs,
|
|
141
|
+
drainTimeoutMs: drainTimeoutMs ?? this.defaultDrainTimeoutMs,
|
|
142
|
+
isStream: config.isStream ?? false,
|
|
143
|
+
abortSignal: config.abortSignal,
|
|
144
|
+
runOnLimitedConnection: this.config.runOnLimitedConnection ?? false,
|
|
145
|
+
requestHandler: config.requestHandler ?? undefined,
|
|
146
|
+
reusePolicy: reuse ? 'reuse' : 'none',
|
|
147
|
+
});
|
|
148
|
+
const transportKey = this.getTransportKeyFromAddress(nextHopAddress);
|
|
149
|
+
if (transportKey) {
|
|
150
|
+
this.connectionsByTransportKey.set(transportKey, p2pConnection);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
this.logger.error('Should not happen! Failed to generate a transport key for address:', nextHopAddress);
|
|
154
|
+
}
|
|
155
|
+
return connection;
|
|
156
|
+
}
|
|
133
157
|
/**
|
|
134
158
|
* Connect to a given address, reusing libp2p connections when possible
|
|
135
159
|
* @param config - Connection configuration
|
|
@@ -34,6 +34,17 @@ export interface StreamHandlerConfig {
|
|
|
34
34
|
* AbortSignal for cancellation
|
|
35
35
|
*/
|
|
36
36
|
signal?: AbortSignal;
|
|
37
|
+
/**
|
|
38
|
+
* Maximum number of streams to cache
|
|
39
|
+
* Older streams will be evicted when limit is reached
|
|
40
|
+
* @default unlimited
|
|
41
|
+
*/
|
|
42
|
+
maxCachedStreams?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Time in milliseconds after which idle cached streams are closed
|
|
45
|
+
* @default unlimited (streams remain cached until closed by peer)
|
|
46
|
+
*/
|
|
47
|
+
streamIdleTimeout?: number;
|
|
37
48
|
}
|
|
38
49
|
/**
|
|
39
50
|
* Context for stream lifecycle operations
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-handler.config.d.ts","sourceRoot":"","sources":["../../../src/connection/stream-handler.config.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAEhC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"stream-handler.config.d.ts","sourceRoot":"","sources":["../../../src/connection/stream-handler.config.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAEhC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IAErB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,mBAAmB,CAAC;CAC7B"}
|
|
@@ -41,13 +41,14 @@ export declare class StreamHandler {
|
|
|
41
41
|
*/
|
|
42
42
|
private extractAndParseJSON;
|
|
43
43
|
/**
|
|
44
|
-
*
|
|
44
|
+
* Builds a bidirectional cache key from caller and receiver addresses
|
|
45
|
+
* The key is symmetric: A↔B === B↔A
|
|
45
46
|
*
|
|
46
|
-
* @param
|
|
47
|
-
* @param
|
|
48
|
-
* @
|
|
47
|
+
* @param callerAddress - The caller's address
|
|
48
|
+
* @param receiverAddress - The receiver's address
|
|
49
|
+
* @returns Cache key string
|
|
49
50
|
*/
|
|
50
|
-
|
|
51
|
+
private buildCacheKey;
|
|
51
52
|
/**
|
|
52
53
|
* Sends data through a stream using length-prefixed encoding (libp2p v3 best practice)
|
|
53
54
|
* Each message is automatically prefixed with a varint indicating the message length
|
|
@@ -58,13 +59,6 @@ export declare class StreamHandler {
|
|
|
58
59
|
* @param config - Configuration for timeout and other options
|
|
59
60
|
*/
|
|
60
61
|
sendLengthPrefixed(stream: Stream, data: Uint8Array, config?: StreamHandlerConfig): Promise<void>;
|
|
61
|
-
/**
|
|
62
|
-
* Closes a stream safely with error handling
|
|
63
|
-
*
|
|
64
|
-
* @param stream - The stream to close
|
|
65
|
-
* @param config - Configuration including reuse policy
|
|
66
|
-
*/
|
|
67
|
-
close(stream: Stream, config?: StreamHandlerConfig): Promise<void>;
|
|
68
62
|
/**
|
|
69
63
|
* Handles an incoming stream on the server side using length-prefixed protocol
|
|
70
64
|
* Uses async read loops instead of event listeners (libp2p v3 best practice)
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
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"}
|
|
@@ -72,49 +72,121 @@ export class StreamHandler {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
/**
|
|
75
|
-
*
|
|
75
|
+
* Builds a bidirectional cache key from caller and receiver addresses
|
|
76
|
+
* The key is symmetric: A↔B === B↔A
|
|
76
77
|
*
|
|
77
|
-
* @param
|
|
78
|
-
* @param
|
|
79
|
-
* @
|
|
78
|
+
* @param callerAddress - The caller's address
|
|
79
|
+
* @param receiverAddress - The receiver's address
|
|
80
|
+
* @returns Cache key string
|
|
80
81
|
*/
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
remoteAddr: connection.remoteAddr.toString(),
|
|
85
|
-
streamCount: connection.streams.length,
|
|
86
|
-
reusePolicy: config.reusePolicy ?? 'none',
|
|
87
|
-
});
|
|
88
|
-
if (connection.status !== 'open') {
|
|
89
|
-
throw new oError(oErrorCodes.INVALID_STATE, 'Connection not open');
|
|
90
|
-
}
|
|
91
|
-
const reusePolicy = config.reusePolicy ?? 'none';
|
|
92
|
-
this.logger.debug('Checking for existing reusable stream', connection.streams.map((s) => ({
|
|
93
|
-
status: s.status,
|
|
94
|
-
protocol: s.protocol,
|
|
95
|
-
writeStatus: s.writeStatus,
|
|
96
|
-
remoteReadStatus: s.remoteReadStatus,
|
|
97
|
-
id: s.id,
|
|
98
|
-
})));
|
|
99
|
-
// Check for existing stream if reuse is enabled
|
|
100
|
-
if (reusePolicy === 'reuse') {
|
|
101
|
-
const existingStream = connection.streams.find((stream) => stream.status === 'open' &&
|
|
102
|
-
stream.protocol === protocol &&
|
|
103
|
-
stream.writeStatus === 'writable' &&
|
|
104
|
-
stream.remoteReadStatus === 'readable');
|
|
105
|
-
if (existingStream) {
|
|
106
|
-
this.logger.debug('Reusing existing stream', existingStream.id, existingStream.direction);
|
|
107
|
-
return existingStream;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
// Create new stream
|
|
111
|
-
const stream = await connection.newStream(protocol, {
|
|
112
|
-
signal: config.signal,
|
|
113
|
-
maxOutboundStreams: config.maxOutboundStreams ?? 1000,
|
|
114
|
-
runOnLimitedConnection: config.runOnLimitedConnection ?? false,
|
|
115
|
-
});
|
|
116
|
-
return stream;
|
|
82
|
+
buildCacheKey(callerAddress, receiverAddress) {
|
|
83
|
+
const addresses = [callerAddress.value, receiverAddress.value].sort();
|
|
84
|
+
return `${addresses[0]}↔${addresses[1]}`;
|
|
117
85
|
}
|
|
86
|
+
// /**
|
|
87
|
+
// * Gets an existing open stream or creates a new one based on reuse policy
|
|
88
|
+
// *
|
|
89
|
+
// * @param connection - The libp2p connection
|
|
90
|
+
// * @param protocol - The protocol to use for the stream
|
|
91
|
+
// * @param config - Stream handler configuration
|
|
92
|
+
// * @param streamAddresses - Optional addresses for address-based stream reuse
|
|
93
|
+
// */
|
|
94
|
+
// async getOrCreateStream(
|
|
95
|
+
// connection: Connection,
|
|
96
|
+
// protocol: string,
|
|
97
|
+
// config: StreamHandlerConfig = {},
|
|
98
|
+
// streamAddresses?: {
|
|
99
|
+
// callerAddress: oAddress;
|
|
100
|
+
// receiverAddress: oAddress;
|
|
101
|
+
// direction: 'inbound' | 'outbound';
|
|
102
|
+
// },
|
|
103
|
+
// ): Promise<Stream> {
|
|
104
|
+
// this.logger.debug(
|
|
105
|
+
// `Getting or creating stream for protocol: ${protocol}, connection`,
|
|
106
|
+
// {
|
|
107
|
+
// status: connection.status,
|
|
108
|
+
// remoteAddr: connection.remoteAddr.toString(),
|
|
109
|
+
// streamCount: connection.streams.length,
|
|
110
|
+
// reusePolicy: config.reusePolicy ?? 'none',
|
|
111
|
+
// hasAddresses: !!streamAddresses,
|
|
112
|
+
// },
|
|
113
|
+
// );
|
|
114
|
+
// if (connection.status !== 'open') {
|
|
115
|
+
// throw new oError(oErrorCodes.INVALID_STATE, 'Connection not open');
|
|
116
|
+
// }
|
|
117
|
+
// const reusePolicy = config.reusePolicy ?? 'none';
|
|
118
|
+
// // Check address-based cache if reuse is enabled and addresses provided
|
|
119
|
+
// if (reusePolicy === 'reuse' && streamAddresses) {
|
|
120
|
+
// const cacheKey = this.buildCacheKey(
|
|
121
|
+
// streamAddresses.callerAddress,
|
|
122
|
+
// streamAddresses.receiverAddress,
|
|
123
|
+
// );
|
|
124
|
+
// const cachedStream = this.streamCache.get(cacheKey);
|
|
125
|
+
// if (cachedStream?.isReusable) {
|
|
126
|
+
// this.logger.debug('Reusing cached stream by address', {
|
|
127
|
+
// cacheKey,
|
|
128
|
+
// streamId: cachedStream.stream.id,
|
|
129
|
+
// direction: cachedStream.direction,
|
|
130
|
+
// });
|
|
131
|
+
// cachedStream.updateLastUsed();
|
|
132
|
+
// return cachedStream.stream;
|
|
133
|
+
// } else if (cachedStream) {
|
|
134
|
+
// // Stream exists but not reusable, remove from cache
|
|
135
|
+
// this.logger.debug('Removing non-reusable stream from cache', {
|
|
136
|
+
// cacheKey,
|
|
137
|
+
// status: cachedStream.stream.status,
|
|
138
|
+
// });
|
|
139
|
+
// this.streamCache.delete(cacheKey);
|
|
140
|
+
// }
|
|
141
|
+
// }
|
|
142
|
+
// this.logger.debug(
|
|
143
|
+
// 'No reusable cached stream found, checking connection streams',
|
|
144
|
+
// connection.streams.map((s) => ({
|
|
145
|
+
// status: s.status,
|
|
146
|
+
// protocol: s.protocol,
|
|
147
|
+
// writeStatus: s.writeStatus,
|
|
148
|
+
// remoteReadStatus: s.remoteReadStatus,
|
|
149
|
+
// id: s.id,
|
|
150
|
+
// })),
|
|
151
|
+
// );
|
|
152
|
+
// // Fallback to protocol-based check (legacy behavior)
|
|
153
|
+
// if (reusePolicy === 'reuse' && !streamAddresses) {
|
|
154
|
+
// const existingStream = connection.streams.find(
|
|
155
|
+
// (stream) =>
|
|
156
|
+
// stream.status === 'open' &&
|
|
157
|
+
// stream.protocol === protocol &&
|
|
158
|
+
// stream.writeStatus === 'writable' &&
|
|
159
|
+
// stream.remoteReadStatus === 'readable',
|
|
160
|
+
// );
|
|
161
|
+
// if (existingStream) {
|
|
162
|
+
// this.logger.debug(
|
|
163
|
+
// 'Reusing existing stream by protocol (legacy)',
|
|
164
|
+
// existingStream.id,
|
|
165
|
+
// existingStream.direction,
|
|
166
|
+
// );
|
|
167
|
+
// return existingStream;
|
|
168
|
+
// }
|
|
169
|
+
// }
|
|
170
|
+
// // Create new stream
|
|
171
|
+
// this.logger.debug('Creating new stream', { protocol });
|
|
172
|
+
// const stream = await connection.newStream(protocol, {
|
|
173
|
+
// signal: config.signal,
|
|
174
|
+
// maxOutboundStreams: config.maxOutboundStreams ?? 1000,
|
|
175
|
+
// runOnLimitedConnection: config.runOnLimitedConnection ?? false,
|
|
176
|
+
// });
|
|
177
|
+
// // Cache the stream if reuse is enabled and addresses are provided
|
|
178
|
+
// if (reusePolicy === 'reuse' && streamAddresses) {
|
|
179
|
+
// const managedStream = new oNodeConnectionStream(
|
|
180
|
+
// stream,
|
|
181
|
+
// streamAddresses.callerAddress,
|
|
182
|
+
// streamAddresses.receiverAddress,
|
|
183
|
+
// streamAddresses.direction,
|
|
184
|
+
// );
|
|
185
|
+
// this.cacheStream(managedStream);
|
|
186
|
+
// this.setupStreamCleanup(stream);
|
|
187
|
+
// }
|
|
188
|
+
// return stream;
|
|
189
|
+
// }
|
|
118
190
|
/**
|
|
119
191
|
* Sends data through a stream using length-prefixed encoding (libp2p v3 best practice)
|
|
120
192
|
* Each message is automatically prefixed with a varint indicating the message length
|
|
@@ -128,28 +200,6 @@ export class StreamHandler {
|
|
|
128
200
|
const lp = lpStream(stream);
|
|
129
201
|
await lp.write(data, { signal: config.signal });
|
|
130
202
|
}
|
|
131
|
-
/**
|
|
132
|
-
* Closes a stream safely with error handling
|
|
133
|
-
*
|
|
134
|
-
* @param stream - The stream to close
|
|
135
|
-
* @param config - Configuration including reuse policy
|
|
136
|
-
*/
|
|
137
|
-
async close(stream, config = {}) {
|
|
138
|
-
// Don't close if reuse policy is enabled
|
|
139
|
-
if (config.reusePolicy === 'reuse') {
|
|
140
|
-
this.logger.debug('Stream reuse enabled, not closing stream');
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
if (stream.status === 'open') {
|
|
144
|
-
try {
|
|
145
|
-
// force the close for now until we can implement a proper close
|
|
146
|
-
await stream.abort(new Error('Stream closed'));
|
|
147
|
-
}
|
|
148
|
-
catch (error) {
|
|
149
|
-
this.logger.debug('Error closing stream:', error.message);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
203
|
/**
|
|
154
204
|
* Handles an incoming stream on the server side using length-prefixed protocol
|
|
155
205
|
* Uses async read loops instead of event listeners (libp2p v3 best practice)
|
|
@@ -9,9 +9,11 @@ declare const oNodeTool_base: typeof oServerNode;
|
|
|
9
9
|
*/
|
|
10
10
|
export declare class oNodeTool extends oNodeTool_base {
|
|
11
11
|
private streamHandler;
|
|
12
|
+
handleProtocolReuse(address: oAddress): Promise<void>;
|
|
12
13
|
handleProtocol(address: oAddress): Promise<void>;
|
|
13
14
|
initialize(): Promise<void>;
|
|
14
|
-
|
|
15
|
+
handleStreamReuse(stream: Stream, connection: Connection): Promise<void>;
|
|
16
|
+
handleStream(stream: Stream, connection: Connection, reuse?: boolean): Promise<void>;
|
|
15
17
|
_tool_identify(): Promise<any>;
|
|
16
18
|
_tool_child_register(request: oRequest): Promise<any>;
|
|
17
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"o-node.tool.d.ts","sourceRoot":"","sources":["../../src/o-node.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAoB,MAAM,eAAe,CAAC;AAErE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;;
|
|
1
|
+
{"version":3,"file":"o-node.tool.d.ts","sourceRoot":"","sources":["../../src/o-node.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAoB,MAAM,eAAe,CAAC;AAErE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;;AAMrD;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,cAAkB;IAC/C,OAAO,CAAC,aAAa,CAAiB;IAEhC,mBAAmB,CAAC,OAAO,EAAE,QAAQ;IAgBrC,cAAc,CAAC,OAAO,EAAE,QAAQ;IAoBhC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B,iBAAiB,CACrB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,IAAI,CAAC;IAIV,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,EACtB,KAAK,CAAC,EAAE,OAAO,GACd,OAAO,CAAC,IAAI,CAAC;IAwCV,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC;IAQ9B,oBAAoB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;CAgC5D"}
|
package/dist/src/o-node.tool.js
CHANGED
|
@@ -4,25 +4,46 @@ import { oServerNode } from './nodes/server.node.js';
|
|
|
4
4
|
import { oNodeTransport } from './router/o-node.transport.js';
|
|
5
5
|
import { oNodeAddress } from './router/o-node.address.js';
|
|
6
6
|
import { StreamHandler } from './connection/stream-handler.js';
|
|
7
|
+
import { ConnectionUtils } from './utils/connection.utils.js';
|
|
7
8
|
/**
|
|
8
9
|
* oTool is a mixin that extends the base class and implements the oTool interface
|
|
9
10
|
* @param Base - The base class to extend
|
|
10
11
|
* @returns A new class that extends the base class and implements the oTool interface
|
|
11
12
|
*/
|
|
12
13
|
export class oNodeTool extends oTool(oServerNode) {
|
|
14
|
+
async handleProtocolReuse(address) {
|
|
15
|
+
const reuseProtocol = address.protocol + '/reuse';
|
|
16
|
+
const protocols = this.p2pNode.getProtocols();
|
|
17
|
+
if (protocols.find((p) => p === reuseProtocol)) {
|
|
18
|
+
// already handling
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const maxOutboundsStreams = process.env.MAX_OUTBOUND_STREAMS
|
|
22
|
+
? parseInt(process.env.MAX_OUTBOUND_STREAMS)
|
|
23
|
+
: 1000;
|
|
24
|
+
await this.p2pNode.handle(reuseProtocol, this.handleStream.bind(this), {
|
|
25
|
+
maxInboundStreams: 10000,
|
|
26
|
+
maxOutboundStreams: maxOutboundsStreams,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
13
29
|
async handleProtocol(address) {
|
|
14
30
|
const protocols = this.p2pNode.getProtocols();
|
|
15
31
|
if (protocols.find((p) => p === address.protocol)) {
|
|
16
32
|
// already handling
|
|
17
33
|
return;
|
|
18
34
|
}
|
|
19
|
-
|
|
35
|
+
const maxOutboundsStreams = process.env.MAX_OUTBOUND_STREAMS
|
|
36
|
+
? parseInt(process.env.MAX_OUTBOUND_STREAMS)
|
|
37
|
+
: 1000;
|
|
38
|
+
this.logger.debug('Handling protocol: ' + address.protocol, {
|
|
39
|
+
maxInboundStreams: 10000,
|
|
40
|
+
maxOutboundStreams: maxOutboundsStreams,
|
|
41
|
+
});
|
|
20
42
|
await this.p2pNode.handle(address.protocol, this.handleStream.bind(this), {
|
|
21
43
|
maxInboundStreams: 10000,
|
|
22
|
-
maxOutboundStreams:
|
|
23
|
-
? parseInt(process.env.MAX_OUTBOUND_STREAMS)
|
|
24
|
-
: 1000,
|
|
44
|
+
maxOutboundStreams: maxOutboundsStreams,
|
|
25
45
|
});
|
|
46
|
+
await this.handleProtocolReuse(address);
|
|
26
47
|
}
|
|
27
48
|
async initialize() {
|
|
28
49
|
await super.initialize();
|
|
@@ -33,7 +54,25 @@ export class oNodeTool extends oTool(oServerNode) {
|
|
|
33
54
|
await this.handleProtocol(this.staticAddress);
|
|
34
55
|
}
|
|
35
56
|
}
|
|
36
|
-
async
|
|
57
|
+
async handleStreamReuse(stream, connection) {
|
|
58
|
+
return this.handleStream(stream, connection, true);
|
|
59
|
+
}
|
|
60
|
+
async handleStream(stream, connection, reuse) {
|
|
61
|
+
if (reuse) {
|
|
62
|
+
this.logger.debug('Handle stream with reuse = true');
|
|
63
|
+
}
|
|
64
|
+
// record inbound connection to manager
|
|
65
|
+
const remoteAddress = await ConnectionUtils.addressFromConnection({
|
|
66
|
+
currentNode: this,
|
|
67
|
+
connection: connection,
|
|
68
|
+
});
|
|
69
|
+
this.connectionManager.answer({
|
|
70
|
+
nextHopAddress: remoteAddress,
|
|
71
|
+
address: remoteAddress,
|
|
72
|
+
callerAddress: this.address,
|
|
73
|
+
p2pConnection: connection,
|
|
74
|
+
reuse,
|
|
75
|
+
});
|
|
37
76
|
// Use StreamHandler for consistent stream handling
|
|
38
77
|
// This follows libp2p v3 best practices for length-prefixed streaming
|
|
39
78
|
await this.streamHandler.handleIncomingStream(stream, connection, async (request, stream) => {
|
|
@@ -56,7 +95,6 @@ export class oNodeTool extends oTool(oServerNode) {
|
|
|
56
95
|
};
|
|
57
96
|
}
|
|
58
97
|
async _tool_child_register(request) {
|
|
59
|
-
this.logger.debug('Child register: ', request.params);
|
|
60
98
|
const { address, transports } = request.params;
|
|
61
99
|
const childAddress = new oNodeAddress(address, transports.map((t) => new oNodeTransport(t)));
|
|
62
100
|
// Add child to hierarchy
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"o-node.address.d.ts","sourceRoot":"","sources":["../../../src/router/o-node.address.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAa,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"o-node.address.d.ts","sourceRoot":"","sources":["../../../src/router/o-node.address.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAa,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAiB,MAAM,eAAe,CAAC;AAExD,qBAAa,YAAa,SAAQ,QAAQ;aAItB,KAAK,EAAE,MAAM;IAHxB,UAAU,EAAE,cAAc,EAAE,CAAM;gBAGvB,KAAK,EAAE,MAAM,EAC7B,UAAU,GAAE,cAAc,EAAO;IAMnC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;KACpC,GAAG,YAAY;IAShB,IAAI,gBAAgB,IAAI,cAAc,EAAE,CAEvC;IAED,IAAI,gBAAgB,IAAI,cAAc,EAAE,CAEvC;IAED,QAAQ,IAAI,MAAM;IAIlB,WAAW,IAAI,SAAS;IAIxB,MAAM,CAAC,aAAa,CAAC,EAAE,EAAE,SAAS,GAAG,QAAQ;IAI7C,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ;CAIhD"}
|
|
@@ -26,4 +26,8 @@ export class oNodeAddress extends oAddress {
|
|
|
26
26
|
static fromMultiaddr(ma) {
|
|
27
27
|
return new oAddress(ma.toString().replace('/o/', 'o://'));
|
|
28
28
|
}
|
|
29
|
+
static fromProtocol(protocol) {
|
|
30
|
+
const addressInput = protocol.replace('/o/', 'o://');
|
|
31
|
+
return new oAddress(addressInput);
|
|
32
|
+
}
|
|
29
33
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Connection } from '@olane/o-config';
|
|
2
|
+
import { oObject } from '@olane/o-core';
|
|
3
|
+
export declare class ConnectionUtils extends oObject {
|
|
4
|
+
static addressFromConnection(options: {
|
|
5
|
+
currentNode: any;
|
|
6
|
+
connection: Connection;
|
|
7
|
+
}): Promise<import("@olane/o-core").oAddress>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=connection.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.utils.d.ts","sourceRoot":"","sources":["../../../src/utils/connection.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAGxC,qBAAa,eAAgB,SAAQ,OAAO;WACtB,qBAAqB,CAAC,OAAO,EAAE;QACjD,WAAW,EAAE,GAAG,CAAC;QACjB,UAAU,EAAE,UAAU,CAAC;KACxB;CAsCF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { oObject } from '@olane/o-core';
|
|
2
|
+
import { oNodeAddress } from '../router/o-node.address.js';
|
|
3
|
+
export class ConnectionUtils extends oObject {
|
|
4
|
+
static async addressFromConnection(options) {
|
|
5
|
+
const { currentNode, connection } = options;
|
|
6
|
+
const p2pNode = currentNode.p2pNode;
|
|
7
|
+
// Extract the actual olane address from the peer store
|
|
8
|
+
const peers = await p2pNode.peerStore.all();
|
|
9
|
+
const remotePeer = peers.find((peer) => peer.id.toString() === connection.remotePeer.toString());
|
|
10
|
+
if (!remotePeer) {
|
|
11
|
+
console.log('Failed to find peer:', remotePeer);
|
|
12
|
+
throw new Error(`Failed to extract remote address, peer ${connection.remotePeer.toString()} not found in peer store.`);
|
|
13
|
+
}
|
|
14
|
+
// Get origin address for comparison
|
|
15
|
+
const originAddress = currentNode.address?.value;
|
|
16
|
+
if (!originAddress) {
|
|
17
|
+
throw new Error('Origin address is not configured');
|
|
18
|
+
}
|
|
19
|
+
const originProtocol = originAddress.toString();
|
|
20
|
+
const oProtocol = remotePeer.protocols.find((p) => p.startsWith('/o/') && p.startsWith(originProtocol) === false);
|
|
21
|
+
if (!oProtocol) {
|
|
22
|
+
throw new Error('Failed to extract remote address, could not find o-protocol in peer protocols.');
|
|
23
|
+
}
|
|
24
|
+
return oNodeAddress.fromProtocol(oProtocol);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC"}
|
package/dist/src/utils/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"astream-reuse.spec.d.ts","sourceRoot":"","sources":["../../test/astream-reuse.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { TestEnvironment } from './helpers/index.js';
|
|
3
|
+
import { NetworkTopologies, } from './helpers/network-builder.js';
|
|
4
|
+
import { oNodeAddress } from '../src/router/o-node.address.js';
|
|
5
|
+
describe('Stream Reuse', () => {
|
|
6
|
+
const env = new TestEnvironment();
|
|
7
|
+
let builder;
|
|
8
|
+
afterEach(async () => {
|
|
9
|
+
if (builder) {
|
|
10
|
+
await builder.cleanup();
|
|
11
|
+
}
|
|
12
|
+
await env.cleanup();
|
|
13
|
+
});
|
|
14
|
+
describe('Stream Reuse with reusePolicy="reuse"', () => {
|
|
15
|
+
it('should reuse the same stream across multiple requests', async () => {
|
|
16
|
+
builder = await NetworkTopologies.twoNode();
|
|
17
|
+
const leader = builder.getNode('o://leader');
|
|
18
|
+
const child = builder.getNode('o://child');
|
|
19
|
+
// Track stream IDs
|
|
20
|
+
const streamIds = [];
|
|
21
|
+
// Make first request
|
|
22
|
+
const response1 = await leader.use(new oNodeAddress(child.address.toString(), child.address.libp2pTransports), {
|
|
23
|
+
method: 'echo',
|
|
24
|
+
params: { message: 'first' },
|
|
25
|
+
});
|
|
26
|
+
expect(response1.result.success).to.be.true;
|
|
27
|
+
// Get active connection to inspect streams
|
|
28
|
+
const connectionManager = leader.connectionManager;
|
|
29
|
+
const connection = connectionManager.getCachedLibp2pConnection(child.address);
|
|
30
|
+
connection.reusePolicy;
|
|
31
|
+
if (connection) {
|
|
32
|
+
// Store initial stream count and first stream ID
|
|
33
|
+
const initialStreamCount = connection.streams.length;
|
|
34
|
+
if (connection.streams.length > 0) {
|
|
35
|
+
streamIds.push(connection.streams[0].id);
|
|
36
|
+
}
|
|
37
|
+
// Make second request
|
|
38
|
+
const response2 = await leader.use(new oNodeAddress(child.address.toString(), child.address.libp2pTransports), {
|
|
39
|
+
method: 'echo',
|
|
40
|
+
params: { message: 'second' },
|
|
41
|
+
});
|
|
42
|
+
expect(response2.result.success).to.be.true;
|
|
43
|
+
// Get stream count after second request
|
|
44
|
+
const finalStreamCount = connection.streams.length;
|
|
45
|
+
if (connection.streams.length > 0) {
|
|
46
|
+
streamIds.push(connection.streams[0].id);
|
|
47
|
+
}
|
|
48
|
+
// With default behavior (reusePolicy='none'), new streams are created
|
|
49
|
+
// This test verifies current behavior
|
|
50
|
+
expect(streamIds.length).to.be.greaterThan(0);
|
|
51
|
+
expect(finalStreamCount).to.be.greaterThan(0);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
describe('Stream Creation with reusePolicy="none"', () => {
|
|
56
|
+
it('should create new streams for each request', async () => {
|
|
57
|
+
builder = await NetworkTopologies.twoNode();
|
|
58
|
+
const leader = builder.getNode('o://leader');
|
|
59
|
+
const child = builder.getNode('o://child');
|
|
60
|
+
// Make multiple requests
|
|
61
|
+
for (let i = 0; i < 3; i++) {
|
|
62
|
+
const response = await leader.use(new oNodeAddress(child.address.toString(), child.address.libp2pTransports), {
|
|
63
|
+
method: 'echo',
|
|
64
|
+
params: { message: `request-${i}` },
|
|
65
|
+
});
|
|
66
|
+
expect(response.result.success).to.be.true;
|
|
67
|
+
}
|
|
68
|
+
// Get connection to verify stream behavior
|
|
69
|
+
const connectionManager = leader.connectionManager;
|
|
70
|
+
const connection = connectionManager.getCachedLibp2pConnection(child.address);
|
|
71
|
+
// With default reusePolicy='none', streams are closed after each request
|
|
72
|
+
// So we expect minimal open streams
|
|
73
|
+
expect(connection).to.exist;
|
|
74
|
+
if (connection) {
|
|
75
|
+
// The number of open streams should be limited since old ones are closed
|
|
76
|
+
expect(connection.streams.length).to.be.lessThan(10);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
describe('Stream Persistence After Transmission', () => {
|
|
81
|
+
it('should close streams after transmission with reusePolicy="none"', async () => {
|
|
82
|
+
builder = await NetworkTopologies.twoNode();
|
|
83
|
+
const leader = builder.getNode('o://leader');
|
|
84
|
+
const child = builder.getNode('o://child');
|
|
85
|
+
// Make a request
|
|
86
|
+
const response = await leader.use(new oNodeAddress(child.address.toString(), child.address.libp2pTransports), {
|
|
87
|
+
method: 'echo',
|
|
88
|
+
params: { message: 'test' },
|
|
89
|
+
});
|
|
90
|
+
expect(response.result.success).to.be.true;
|
|
91
|
+
// Get connection
|
|
92
|
+
const connectionManager = leader.connectionManager;
|
|
93
|
+
const connection = connectionManager.getCachedLibp2pConnection(child.address);
|
|
94
|
+
expect(connection).to.exist;
|
|
95
|
+
if (connection) {
|
|
96
|
+
// Make another request to verify new stream can be created
|
|
97
|
+
const response2 = await leader.use(new oNodeAddress(child.address.toString(), child.address.libp2pTransports), {
|
|
98
|
+
method: 'echo',
|
|
99
|
+
params: { message: 'test2' },
|
|
100
|
+
});
|
|
101
|
+
expect(response2.result.success).to.be.true;
|
|
102
|
+
// Verify connection is still functional
|
|
103
|
+
expect(connection.status).to.equal('open');
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
@@ -16,6 +16,7 @@ describe('Connection Management', () => {
|
|
|
16
16
|
describe('Connection Pooling', () => {
|
|
17
17
|
it('should cache and reuse connections', async () => {
|
|
18
18
|
builder = await NetworkTopologies.twoNode();
|
|
19
|
+
console.log('Built the 2 node network, starting test');
|
|
19
20
|
const leader = builder.getNode('o://leader');
|
|
20
21
|
const child = builder.getNode('o://child');
|
|
21
22
|
const spy = createConnectionSpy(leader);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network-builder.d.ts","sourceRoot":"","sources":["../../../test/helpers/network-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAC7E,OAAO,EAAY,QAAQ,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;GAEG;AACH,qBAAa,QAAS,SAAQ,SAAS;IAC9B,SAAS,SAAK;gBAET,MAAM,EAAE,eAAe,GAAG;QAAE,OAAO,EAAE,YAAY,CAAA;KAAE;IAIzD,SAAS,IAAI,OAAO,CAAC,YAAY,CAAC;IAelC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"network-builder.d.ts","sourceRoot":"","sources":["../../../test/helpers/network-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAC7E,OAAO,EAAY,QAAQ,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;GAEG;AACH,qBAAa,QAAS,SAAQ,SAAS;IAC9B,SAAS,SAAK;gBAET,MAAM,EAAE,eAAe,GAAG;QAAE,OAAO,EAAE,YAAY,CAAA;KAAE;IAIzD,SAAS,IAAI,OAAO,CAAC,YAAY,CAAC;IAelC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAuC/B,UAAU,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAS3C,cAAc,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAS9C,YAAY,CAAC,OAAO,EAAE,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC;CAY5D;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,YAAY,CAA0B;IAE9C;;;OAGG;IACG,OAAO,CACX,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,GAAE,OAAO,CAAC,UAAU,CAAM,GAC/B,OAAO,CAAC,QAAQ,CAAC;IAqCpB;;OAEG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB/C;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc9C;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAU9B;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAI9C;;OAEG;IACH,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC;IAIpC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAyC7B;;OAEG;YACW,iBAAiB;IAkB/B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAK/B;AAED;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B;;;OAGG;WACU,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;IAO/C;;;OAGG;WACU,SAAS,IAAI,OAAO,CAAC,cAAc,CAAC;IAQjD;;;;OAIG;WACU,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC;IAUhD;;OAEG;WACU,aAAa,IAAI,OAAO,CAAC,cAAc,CAAC;IAOrD;;;;;OAKG;WACU,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;CAmBhD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olane/o-node",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.41",
|
|
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.
|
|
43
|
+
"@olane/o-test": "0.7.41",
|
|
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.
|
|
64
|
-
"@olane/o-core": "0.7.
|
|
65
|
-
"@olane/o-protocol": "0.7.
|
|
66
|
-
"@olane/o-tool": "0.7.
|
|
63
|
+
"@olane/o-config": "0.7.41",
|
|
64
|
+
"@olane/o-core": "0.7.41",
|
|
65
|
+
"@olane/o-protocol": "0.7.41",
|
|
66
|
+
"@olane/o-tool": "0.7.41",
|
|
67
67
|
"debug": "^4.4.1",
|
|
68
68
|
"dotenv": "^16.5.0",
|
|
69
69
|
"json5": "^2.2.3"
|
|
70
70
|
},
|
|
71
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "f705ab1099e0df6220c8f1d9a44e5b6cd09eb224"
|
|
72
72
|
}
|