@olane/o-node 0.7.54 → 0.7.56

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 (60) 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 +17 -3
  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 +33 -11
  16. package/dist/src/connection/o-node-connection.d.ts.map +1 -1
  17. package/dist/src/connection/o-node-connection.js +113 -58
  18. package/dist/src/connection/o-node-connection.manager.d.ts +17 -62
  19. package/dist/src/connection/o-node-connection.manager.d.ts.map +1 -1
  20. package/dist/src/connection/o-node-connection.manager.js +65 -189
  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 +144 -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/connection/stream-manager.events.d.ts +7 -0
  27. package/dist/src/connection/stream-manager.events.d.ts.map +1 -1
  28. package/dist/src/connection/stream-manager.events.js +1 -0
  29. package/dist/src/lib/interfaces/o-node-request-manager.config.d.ts +9 -0
  30. package/dist/src/lib/interfaces/o-node-request-manager.config.d.ts.map +1 -0
  31. package/dist/src/lib/interfaces/o-node-request-manager.config.js +1 -0
  32. package/dist/src/lib/o-node-request-manager.d.ts +46 -0
  33. package/dist/src/lib/o-node-request-manager.d.ts.map +1 -0
  34. package/dist/src/lib/o-node-request-manager.js +173 -0
  35. package/dist/src/managers/o-reconnection.manager.d.ts.map +1 -1
  36. package/dist/src/managers/o-reconnection.manager.js +4 -0
  37. package/dist/src/managers/o-registration.manager.d.ts.map +1 -1
  38. package/dist/src/managers/o-registration.manager.js +9 -4
  39. package/dist/src/o-node.d.ts +6 -7
  40. package/dist/src/o-node.d.ts.map +1 -1
  41. package/dist/src/o-node.js +22 -37
  42. package/dist/src/o-node.tool.d.ts +3 -3
  43. package/dist/src/o-node.tool.d.ts.map +1 -1
  44. package/dist/src/o-node.tool.js +31 -65
  45. package/dist/src/router/o-node.router.d.ts.map +1 -1
  46. package/dist/src/router/o-node.router.js +4 -2
  47. package/dist/src/utils/connection.utils.d.ts +3 -3
  48. package/dist/src/utils/connection.utils.d.ts.map +1 -1
  49. package/dist/src/utils/connection.utils.js +46 -19
  50. package/dist/test/connection-management.spec.js +3 -0
  51. package/package.json +7 -7
  52. package/dist/src/connection/interfaces/stream-init-message.d.ts +0 -64
  53. package/dist/src/connection/interfaces/stream-init-message.d.ts.map +0 -1
  54. package/dist/src/connection/interfaces/stream-init-message.js +0 -18
  55. package/dist/src/connection/interfaces/stream-manager.config.d.ts +0 -8
  56. package/dist/src/connection/interfaces/stream-manager.config.d.ts.map +0 -1
  57. package/dist/src/connection/o-node-stream.manager.d.ts +0 -200
  58. package/dist/src/connection/o-node-stream.manager.d.ts.map +0 -1
  59. package/dist/src/connection/o-node-stream.manager.js +0 -633
  60. /package/dist/src/connection/interfaces/{stream-manager.config.js → abort-signal.config.js} +0 -0
@@ -0,0 +1,14 @@
1
+ import { oResponse } from '@olane/o-core';
2
+ import { oStreamRequest } from '../o-stream.request.js';
3
+ export declare enum oNodeMessageEvent {
4
+ request = "request",
5
+ response = "response"
6
+ }
7
+ /**
8
+ * Mapped type for type-safe event listeners
9
+ */
10
+ export type oNodeMessageEventData = {
11
+ [oNodeMessageEvent.request]: oStreamRequest;
12
+ [oNodeMessageEvent.response]: oResponse;
13
+ };
14
+ //# sourceMappingURL=o-node-message-event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"o-node-message-event.d.ts","sourceRoot":"","sources":["../../../../src/connection/enums/o-node-message-event.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,SAAS,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,oBAAY,iBAAiB;IAC3B,OAAO,YAAY;IACnB,QAAQ,aAAa;CACtB;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;IAC5C,CAAC,iBAAiB,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACzC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export var oNodeMessageEvent;
2
+ (function (oNodeMessageEvent) {
3
+ oNodeMessageEvent["request"] = "request";
4
+ oNodeMessageEvent["response"] = "response";
5
+ })(oNodeMessageEvent || (oNodeMessageEvent = {}));
@@ -3,10 +3,7 @@ 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
5
  export * from './interfaces/o-node-stream.config.js';
6
- export * from './interfaces/stream-manager.config.js';
7
- export * from './interfaces/stream-init-message.js';
8
6
  export * from './o-node-stream.js';
9
7
  export * from './stream-handler.config.js';
10
- export * from './o-node-stream.manager.js';
11
8
  export * from './stream-manager.events.js';
12
9
  //# 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;AACjE,cAAc,sCAAsC,CAAC;AACrD,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AACpD,cAAc,oBAAoB,CAAC;AACnC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,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,sCAAsC,CAAC;AACrD,cAAc,oBAAoB,CAAC;AACnC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC"}
@@ -3,9 +3,6 @@ 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
5
  export * from './interfaces/o-node-stream.config.js';
6
- export * from './interfaces/stream-manager.config.js';
7
- export * from './interfaces/stream-init-message.js';
8
6
  export * from './o-node-stream.js';
9
7
  export * from './stream-handler.config.js';
10
- export * from './o-node-stream.manager.js';
11
8
  export * from './stream-manager.events.js';
@@ -0,0 +1,5 @@
1
+ /// <reference types="node" />
2
+ export interface AbortSignalConfig {
3
+ abortSignal?: AbortSignal;
4
+ }
5
+ //# sourceMappingURL=abort-signal.config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abort-signal.config.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/abort-signal.config.ts"],"names":[],"mappings":";AAAA,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B"}
@@ -3,6 +3,18 @@ import { Libp2p } from '@olane/o-config';
3
3
  export interface oNodeConnectionManagerConfig extends oConnectionManagerConfig {
4
4
  p2pNode: Libp2p;
5
5
  runOnLimitedConnection?: boolean;
6
- originAddress?: string;
6
+ callerAddress?: string;
7
+ /**
8
+ * Default timeout in milliseconds for reading response data from a stream.
9
+ * Can be overridden per connection.
10
+ * Default: 120000 (2 minutes)
11
+ */
12
+ defaultReadTimeoutMs?: number;
13
+ /**
14
+ * Default timeout in milliseconds for waiting for stream buffer to drain when backpressure occurs.
15
+ * Can be overridden per connection.
16
+ * Default: 30000 (30 seconds)
17
+ */
18
+ defaultDrainTimeoutMs?: number;
7
19
  }
8
20
  //# sourceMappingURL=o-node-connection-manager.config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"o-node-connection-manager.config.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/o-node-connection-manager.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,MAAM,WAAW,4BAA6B,SAAQ,wBAAwB;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
1
+ {"version":3,"file":"o-node-connection-manager.config.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/o-node-connection-manager.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,MAAM,WAAW,4BAA6B,SAAQ,wBAAwB;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC"}
@@ -1,9 +1,23 @@
1
+ /// <reference types="node" />
1
2
  import { Connection } from '@olane/o-config';
2
3
  import { oConnectionConfig } from '@olane/o-core';
3
- import type { StreamReusePolicy } from '../stream-handler.config.js';
4
+ import { oNodeAddress } from '../../router';
4
5
  export interface oNodeConnectionConfig extends oConnectionConfig {
5
- p2pConnection: Connection;
6
+ nextHopAddress: oNodeAddress;
7
+ callerAddress?: oNodeAddress;
8
+ targetAddress: oNodeAddress;
9
+ p2pConnection?: Connection;
6
10
  runOnLimitedConnection?: boolean;
7
- reusePolicy?: StreamReusePolicy;
11
+ /**
12
+ * Timeout in milliseconds for waiting for stream buffer to drain when backpressure occurs.
13
+ * Default: 30000 (30 seconds)
14
+ */
15
+ drainTimeoutMs?: number;
16
+ abortSignal?: AbortSignal;
17
+ /**
18
+ * Timeout in milliseconds for reading response data from a stream.
19
+ * Default: 120000 (2 minutes)
20
+ */
21
+ readTimeoutMs?: number;
8
22
  }
9
23
  //# sourceMappingURL=o-node-connection.config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"o-node-connection.config.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/o-node-connection.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC9D,aAAa,EAAE,UAAU,CAAC;IAC1B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,WAAW,CAAC,EAAE,iBAAiB,CAAC;CACjC"}
1
+ {"version":3,"file":"o-node-connection.config.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/o-node-connection.config.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAU,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC9D,cAAc,EAAE,YAAY,CAAC;IAC7B,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,aAAa,EAAE,YAAY,CAAC;IAC5B,aAAa,CAAC,EAAE,UAAU,CAAC;IAC3B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
@@ -1,16 +1,8 @@
1
+ /// <reference types="node" />
1
2
  import { oAddress } from '@olane/o-core';
2
- import { StreamReusePolicy } from '../stream-handler.config';
3
- /**
4
- * Stream type defines the role and usage pattern of a stream:
5
- * - 'dedicated-reader': Stream exclusively used for reading incoming requests (background reader)
6
- * - 'request-response': Stream used for outgoing request-response cycles
7
- * - 'general': Stream with no specific role (default, backward compatible)
8
- */
9
- export type StreamType = 'dedicated-reader' | 'request-response' | 'general';
10
3
  export interface oNodeStreamConfig {
11
- direction: 'inbound' | 'outbound';
12
- reusePolicy: StreamReusePolicy;
13
4
  remoteAddress: oAddress;
14
- streamType?: StreamType;
5
+ abortSignal?: AbortSignal;
6
+ limited?: boolean;
15
7
  }
16
8
  //# sourceMappingURL=o-node-stream.config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"o-node-stream.config.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/o-node-stream.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,kBAAkB,GAAG,kBAAkB,GAAG,SAAS,CAAC;AAE7E,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,SAAS,GAAG,UAAU,CAAC;IAClC,WAAW,EAAE,iBAAiB,CAAC;IAC/B,aAAa,EAAE,QAAQ,CAAC;IACxB,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB"}
1
+ {"version":3,"file":"o-node-stream.config.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/o-node-stream.config.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,QAAQ,CAAC;IACxB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
@@ -1,27 +1,49 @@
1
- import { Connection } from '@olane/o-config';
2
- import { oConnection, oRequest, oResponse } from '@olane/o-core';
1
+ /// <reference types="node" />
2
+ import { Connection, Multiaddr } from '@olane/o-config';
3
+ import { oAddress, oConnection, oRequest } from '@olane/o-core';
3
4
  import { oNodeConnectionConfig } from './interfaces/o-node-connection.config.js';
4
- import type { StreamReusePolicy } from './stream-handler.config.js';
5
- import { oNodeAddress } from '../router/o-node.address.js';
6
5
  import { oNodeStream } from './o-node-stream.js';
7
- import { oNodeStreamManager } from './o-node-stream.manager.js';
6
+ import { oNodeStreamConfig } from './interfaces/o-node-stream.config.js';
7
+ import { AbortSignalConfig } from './interfaces/abort-signal.config.js';
8
+ import { EventEmitter } from 'events';
9
+ import { oNodeMessageEvent, oNodeMessageEventData } from './enums/o-node-message-event.js';
8
10
  export declare class oNodeConnection extends oConnection {
9
11
  protected readonly config: oNodeConnectionConfig;
10
12
  p2pConnection: Connection;
11
- protected reusePolicy: StreamReusePolicy;
12
- streamManager: oNodeStreamManager;
13
+ protected streams: Map<string, oNodeStream>;
14
+ protected runOnLimitedConnection: boolean;
15
+ eventEmitter: EventEmitter;
13
16
  constructor(config: oNodeConnectionConfig);
17
+ listenForClose(): void;
18
+ get isOpen(): boolean;
14
19
  get remotePeerId(): import("@olane/o-config").PeerId;
15
- get remoteAddr(): import("@olane/o-config").Multiaddr;
20
+ get remoteAddr(): Multiaddr;
16
21
  /**
17
22
  * Get the connection configuration for compatibility checking.
18
23
  */
19
24
  get connectionConfig(): oNodeConnectionConfig;
20
- supportsAddress(address: oNodeAddress): boolean;
21
- get streams(): oNodeStream[];
22
- transmit(request: oRequest): Promise<oResponse>;
25
+ get address(): oAddress;
26
+ get nextHopAddress(): oAddress;
27
+ get callerAddress(): oAddress | undefined;
28
+ newStream(config: oNodeStreamConfig): Promise<oNodeStream>;
29
+ listenForMessages(stream: oNodeStream, options: AbortSignalConfig): Promise<void>;
30
+ trackStream(stream: oNodeStream, options: AbortSignalConfig): void;
31
+ protected doSend(request: oRequest, options: AbortSignalConfig): Promise<oNodeStream>;
32
+ transmit(request: oRequest, options: AbortSignalConfig): Promise<oNodeStream>;
23
33
  postTransmit(stream: oNodeStream): Promise<void>;
24
34
  abort(error: Error): Promise<void>;
25
35
  close(): Promise<void>;
36
+ /**
37
+ * Add event listener
38
+ */
39
+ on<K extends oNodeMessageEvent>(event: K | string, listener: (data: oNodeMessageEventData[K]) => void): void;
40
+ /**
41
+ * Remove event listener
42
+ */
43
+ off<K extends oNodeMessageEvent>(event: K | string, listener: (data: oNodeMessageEventData[K]) => void): void;
44
+ /**
45
+ * Emit event
46
+ */
47
+ private emit;
26
48
  }
27
49
  //# sourceMappingURL=o-node-connection.d.ts.map
@@ -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,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,KAAK,EAEV,iBAAiB,EAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,qBAAa,eAAgB,SAAQ,WAAW;IAKlC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB;IAJrD,aAAa,EAAE,UAAU,CAAC;IACjC,SAAS,CAAC,WAAW,EAAE,iBAAiB,CAAC;IAClC,aAAa,EAAE,kBAAkB,CAAC;gBAEV,MAAM,EAAE,qBAAqB;IAW5D,IAAI,YAAY,qCAEf;IAED,IAAI,UAAU,wCAEb;IAED;;OAEG;IACH,IAAI,gBAAgB,IAAI,qBAAqB,CAE5C;IAED,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO;IAM/C,IAAI,OAAO,IAAI,WAAW,EAAE,CAE3B;IAEK,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAkF/C,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhD,KAAK,CAAC,KAAK,EAAE,KAAK;IAMlB,KAAK;CASZ"}
1
+ {"version":3,"file":"o-node-connection.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAU,SAAS,EAAU,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAEL,QAAQ,EACR,WAAW,EAGX,QAAQ,EAET,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AAGjF,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,iCAAiC,CAAC;AAYzC,qBAAa,eAAgB,SAAQ,WAAW;IAMlC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB;IALrD,aAAa,EAAE,UAAU,CAAC;IACjC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAkC;IAC7E,SAAS,CAAC,sBAAsB,EAAE,OAAO,CAAC;IAC1C,YAAY,EAAE,YAAY,CAAsB;gBAEjB,MAAM,EAAE,qBAAqB;IAQ5D,cAAc;IAMd,IAAI,MAAM,YAET;IAED,IAAI,YAAY,qCAEf;IAED,IAAI,UAAU,cAEb;IAED;;OAEG;IACH,IAAI,gBAAgB,IAAI,qBAAqB,CAE5C;IAED,IAAI,OAAO,IAAI,QAAQ,CAEtB;IAED,IAAI,cAAc,IAAI,QAAQ,CAK7B;IAED,IAAI,aAAa,IAAI,QAAQ,GAAG,SAAS,CAMxC;IAEK,SAAS,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC;IA2B1D,iBAAiB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB;IAyBvE,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB;cAO3C,MAAM,CACpB,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,WAAW,CAAC;IAsBjB,QAAQ,CACZ,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,WAAW,CAAC;IAoBjB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,KAAK,CAAC,KAAK,EAAE,KAAK;IAMlB,KAAK;IAOX;;OAEG;IACH,EAAE,CAAC,CAAC,SAAS,iBAAiB,EAC5B,KAAK,EAAE,CAAC,GAAG,MAAM,EACjB,QAAQ,EAAE,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC,CAAC,KAAK,IAAI,GACjD,IAAI;IAIP;;OAEG;IACH,GAAG,CAAC,CAAC,SAAS,iBAAiB,EAC7B,KAAK,EAAE,CAAC,GAAG,MAAM,EACjB,QAAQ,EAAE,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC,CAAC,KAAK,IAAI,GACjD,IAAI;IAIP;;OAEG;IACH,OAAO,CAAC,IAAI;CAMb"}
@@ -1,16 +1,25 @@
1
1
  import { oConnection, oError, oErrorCodes, } from '@olane/o-core';
2
- import { oNodeStreamManager } from './o-node-stream.manager.js';
2
+ import { oNodeStream } from './o-node-stream.js';
3
+ import { EventEmitter } from 'events';
4
+ import { oNodeMessageEvent, } from './enums/o-node-message-event.js';
3
5
  export class oNodeConnection extends oConnection {
4
6
  constructor(config) {
5
7
  super(config);
6
8
  this.config = config;
9
+ this.streams = new Map();
10
+ this.eventEmitter = new EventEmitter();
7
11
  this.p2pConnection = config.p2pConnection;
8
- this.reusePolicy = config.reusePolicy ?? 'none';
9
- // Initialize oNodeStreamManager (stream lifecycle and protocol management)
10
- this.streamManager = new oNodeStreamManager({
11
- p2pConnection: this.p2pConnection,
12
+ this.runOnLimitedConnection = config.runOnLimitedConnection ?? false;
13
+ this.listenForClose();
14
+ }
15
+ listenForClose() {
16
+ this.p2pConnection.addEventListener('close', () => {
17
+ this.close();
12
18
  });
13
19
  }
20
+ get isOpen() {
21
+ return this.p2pConnection.status === 'open';
22
+ }
14
23
  get remotePeerId() {
15
24
  return this.p2pConnection.remotePeer;
16
25
  }
@@ -23,61 +32,92 @@ export class oNodeConnection extends oConnection {
23
32
  get connectionConfig() {
24
33
  return this.config;
25
34
  }
26
- supportsAddress(address) {
27
- return address.libp2pTransports.some((transport) => {
28
- return transport.toString() === this.remoteAddr.toString();
35
+ get address() {
36
+ return this.config.targetAddress;
37
+ }
38
+ get nextHopAddress() {
39
+ if (this.config.nextHopAddress.value === 'o://unknown') {
40
+ return this.address;
41
+ }
42
+ return this.config.nextHopAddress;
43
+ }
44
+ get callerAddress() {
45
+ if (this.p2pConnection.direction === 'inbound') {
46
+ return this.address;
47
+ }
48
+ return this.config.callerAddress;
49
+ }
50
+ async newStream(config) {
51
+ const protocol = config.remoteAddress.protocol;
52
+ this.logger.debug('Creating new stream', {
53
+ protocol,
54
+ currentStreamCount: this.streams.size,
55
+ });
56
+ // Create stream from libp2p connection
57
+ const stream = await this.p2pConnection.newStream(protocol, {
58
+ signal: config.abortSignal,
59
+ maxOutboundStreams: 1000,
60
+ runOnLimitedConnection: this.runOnLimitedConnection,
29
61
  });
62
+ // Wrap in oNodeStream with metadata
63
+ const wrappedStream = new oNodeStream(stream, config);
64
+ this.logger.debug('Stream created', {
65
+ streamId: stream.id,
66
+ protocol,
67
+ totalStreams: this.streams.size,
68
+ });
69
+ return wrappedStream;
70
+ }
71
+ // bubble up the messages to the request handler
72
+ async listenForMessages(stream, options) {
73
+ try {
74
+ stream.on(oNodeMessageEvent.request, (data) => {
75
+ this.emit(oNodeMessageEvent.request, data);
76
+ });
77
+ stream.on(oNodeMessageEvent.response, (data) => {
78
+ this.emit(oNodeMessageEvent.response, data);
79
+ });
80
+ stream.p2pStream.addEventListener('close', () => {
81
+ if (this.streams.has(stream.id)) {
82
+ this.streams.delete(stream.id);
83
+ }
84
+ });
85
+ await stream.listen(options);
86
+ }
87
+ catch (err) {
88
+ this.logger.warn('Stream errored out when listening for key messages:', err?.message);
89
+ }
90
+ }
91
+ trackStream(stream, options) {
92
+ this.streams.set(stream.id, stream);
93
+ this.logger.debug('Stream count: ' + this.streams.size);
94
+ // persistent listener
95
+ this.listenForMessages(stream, options);
30
96
  }
31
- get streams() {
32
- return this.streamManager.getAllStreams();
97
+ async doSend(request, options) {
98
+ try {
99
+ // create a new stream and send the payload
100
+ const wrappedStream = await this.newStream({
101
+ remoteAddress: this.nextHopAddress,
102
+ limited: this.runOnLimitedConnection,
103
+ ...options,
104
+ });
105
+ this.trackStream(wrappedStream, options);
106
+ await wrappedStream.send(request, options);
107
+ return wrappedStream;
108
+ }
109
+ catch (err) {
110
+ this.logger.error('Failed to send request over stream.', err);
111
+ throw new oError(oErrorCodes.SEND_FAILED, 'Failed to send request over stream.', { request: request.toJSON() });
112
+ }
33
113
  }
34
- async transmit(request) {
114
+ async transmit(request, options) {
35
115
  try {
36
- // Build protocol string
37
- const protocol = this.nextHopAddress.protocol +
38
- (this.reusePolicy === 'reuse' ? '/reuse' : '');
39
116
  this.logger.debug('Transmitting request on limited connection?', this.config.runOnLimitedConnection);
40
- const streamConfig = {
41
- signal: this.abortSignal,
42
- drainTimeoutMs: this.config.drainTimeoutMs,
43
- reusePolicy: this.reusePolicy,
44
- maxOutboundStreams: process.env.MAX_OUTBOUND_STREAMS
45
- ? parseInt(process.env.MAX_OUTBOUND_STREAMS)
46
- : 1000,
47
- runOnLimitedConnection: this.config.runOnLimitedConnection ?? false,
48
- };
49
- // Get stream from StreamManager
50
- const wrappedStream = await this.streamManager.getOrCreateStream(protocol, this.nextHopAddress, streamConfig);
51
- // Ensure stream is valid
52
- wrappedStream.validate();
53
- const stream = wrappedStream.p2pStream;
54
- // Send the request with backpressure handling
55
- const data = new TextEncoder().encode(request.toString());
56
- await this.streamManager.sendLengthPrefixed(stream, data, streamConfig);
57
- // Determine which stream to wait for response on
58
- // If _streamId is specified, use that stream (for limited connections with persistent writer stream)
59
- let responseStream = stream;
60
- if (request.params._streamId) {
61
- const specifiedStream = this.streamManager.getStreamById(request.params._streamId);
62
- if (specifiedStream) {
63
- responseStream = specifiedStream;
64
- this.logger.debug('Using specified stream for response', {
65
- requestStreamId: stream.id,
66
- responseStreamId: specifiedStream.id,
67
- });
68
- }
69
- else {
70
- this.logger.warn('Specified response stream not found, using request stream', {
71
- streamId: request.params._streamId,
72
- });
73
- }
74
- }
75
- // Handle response using StreamManager
76
- // Pass request ID to enable proper response correlation on shared streams
77
- const response = await this.streamManager.handleOutgoingStream(responseStream, this.emitter, streamConfig, request.id);
117
+ const stream = await this.doSend(request, options);
78
118
  // Handle cleanup of the stream
79
- await this.postTransmit(wrappedStream);
80
- return response;
119
+ await this.postTransmit(stream);
120
+ return stream;
81
121
  }
82
122
  catch (error) {
83
123
  if (error?.name === 'UnsupportedProtocolError') {
@@ -87,8 +127,7 @@ export class oNodeConnection extends oConnection {
87
127
  }
88
128
  }
89
129
  async postTransmit(stream) {
90
- // Always cleanup streams (no reuse at base layer)
91
- await this.streamManager.releaseStream(stream.p2pStream.id);
130
+ // after transmit, let's just leave this connection open for now
92
131
  }
93
132
  async abort(error) {
94
133
  this.logger.debug('Aborting connection');
@@ -97,9 +136,25 @@ export class oNodeConnection extends oConnection {
97
136
  }
98
137
  async close() {
99
138
  this.logger.debug('Closing connection');
100
- // Close stream manager (handles all stream cleanup)
101
- await this.streamManager.close();
102
139
  await this.p2pConnection.close();
103
140
  this.logger.debug('Connection closed');
104
141
  }
142
+ /**
143
+ * Add event listener
144
+ */
145
+ on(event, listener) {
146
+ this.eventEmitter.on(event, listener);
147
+ }
148
+ /**
149
+ * Remove event listener
150
+ */
151
+ off(event, listener) {
152
+ this.eventEmitter.off(event, listener);
153
+ }
154
+ /**
155
+ * Emit event
156
+ */
157
+ emit(event, data) {
158
+ this.eventEmitter.emit(event, data);
159
+ }
105
160
  }
@@ -1,100 +1,55 @@
1
- import { oAddress, oConnectionConfig, oConnectionManager } from '@olane/o-core';
2
- import { Libp2p, Connection } from '@olane/o-config';
1
+ /// <reference types="node" />
2
+ import { oAddress, oConnectionManager } from '@olane/o-core';
3
+ import { Libp2p, Connection, Stream } from '@olane/o-config';
3
4
  import { oNodeConnectionManagerConfig } from './interfaces/o-node-connection-manager.config.js';
5
+ import { oNodeAddress } from '../router/o-node.address.js';
4
6
  import { oNodeConnection } from './o-node-connection.js';
7
+ import { EventEmitter } from 'events';
8
+ import { oNodeConnectionConfig } from './interfaces/o-node-connection.config.js';
9
+ /**
10
+ * Manages oNodeConnection instances, reusing connections when possible.
11
+ */
5
12
  export declare class oNodeConnectionManager extends oConnectionManager {
6
13
  readonly config: oNodeConnectionManagerConfig;
7
14
  protected p2pNode: Libp2p;
8
15
  protected defaultReadTimeoutMs?: number;
9
16
  protected defaultDrainTimeoutMs?: number;
10
17
  /** Single cache of oNodeConnection instances keyed by address */
11
- protected cachedConnections: Map<string, oNodeConnection[]>;
18
+ protected cachedConnections: Map<string, oNodeConnection>;
12
19
  protected pendingDialsByAddress: Map<string, Promise<Connection>>;
20
+ protected eventEmitter: EventEmitter;
13
21
  constructor(config: oNodeConnectionManagerConfig);
14
22
  /**
15
23
  * Set up listeners to maintain connection cache state
16
24
  */
17
25
  protected setupConnectionListeners(): void;
18
- /**
19
- * Build a stable cache key from an address.
20
- *
21
- * We key the cache by address value (e.g., "o://my-tool") to maintain
22
- * a simple one-to-one mapping between addresses and connections.
23
- */
24
- protected getAddressKey(address: oAddress): string | null;
25
26
  /**
26
27
  * Extract peer ID string from an address
27
28
  * @param address - The address to extract peer ID from
28
29
  * @returns The peer ID string or null if not found
29
30
  */
30
31
  protected getPeerIdFromAddress(address: oAddress): string | null;
31
- /**
32
- * Get the first valid (open) connection for the given address key.
33
- * Cleans up stale connections from the cache automatically.
34
- *
35
- * @param addressKey - The address key to look up
36
- * @returns A valid oNodeConnection or null if none found
37
- */
38
- protected getValidConnection(addressKey: string): oNodeConnection | null;
39
32
  /**
40
33
  * Cache an oNodeConnection by its address key.
41
34
  * @param conn - The oNodeConnection to cache
42
35
  * @param addressKey - The address key to cache under
43
36
  */
44
- protected cacheConnection(conn: oNodeConnection, addressKey: string): void;
45
- /**
46
- * Get oNodeConnection by libp2p Connection reference
47
- * Used to find the correct oNodeConnection for incoming streams
48
- * @param p2pConnection - The libp2p connection to search for
49
- * @returns The oNodeConnection or undefined if not found
50
- */
51
- getConnectionByP2pConnection(p2pConnection: Connection): oNodeConnection | undefined;
37
+ protected cacheConnection(conn: oNodeConnection): void;
52
38
  /**
53
39
  * Get or create a raw p2p connection to the given address.
54
40
  * Subclasses can override connect() and use this method to get the underlying p2p connection.
55
41
  */
56
42
  protected getOrCreateP2pConnection(nextHopAddress: oAddress, addressKey: string): Promise<Connection>;
57
43
  protected performDial(nextHopAddress: oAddress, addressKey: string): Promise<Connection>;
58
- answer(config: oConnectionConfig & {
59
- p2pConnection: Connection;
60
- reuse?: boolean;
61
- }): Promise<oNodeConnection>;
44
+ createConnection(config: oNodeConnectionConfig): Promise<oNodeConnection>;
45
+ answer(config: oNodeConnectionConfig, stream: Stream): Promise<oNodeConnection>;
62
46
  /**
63
47
  * Connect to a given address, reusing oNodeConnection when possible
64
48
  * @param config - Connection configuration
65
49
  * @returns The connection object
66
50
  */
67
- connect(config: oConnectionConfig): Promise<oNodeConnection>;
68
- /**
69
- * Check if we have an active connection to the target peer
70
- * @param address - The address to check
71
- * @returns true if an active connection exists
72
- */
73
- isCached(address: oAddress): boolean;
74
- /**
75
- * Get an existing cached oNodeConnection for the target address
76
- * @param address - The address to get a connection for
77
- * @returns The oNodeConnection or null if not found
78
- */
79
- getCachedConnection(address: oAddress): oNodeConnection | null;
80
- /**
81
- * Get cache statistics for monitoring and debugging
82
- * @returns Object containing cache statistics
83
- */
84
- getCacheStats(): {
85
- cachedAddresses: number;
86
- totalCachedConnections: number;
87
- pendingDials: number;
88
- connectionsByPeer: Array<{
89
- peerId: string;
90
- status: string;
91
- addressKey: string;
92
- }>;
93
- };
94
- /**
95
- * Clean up all stale (non-open) connections from cache
96
- * @returns Number of connections removed
97
- */
98
- cleanupStaleConnections(): number;
51
+ connect(config: oNodeConnectionConfig): Promise<oNodeConnection>;
52
+ getCachedConnectionFromAddress(address: oNodeAddress): oNodeConnection | null;
53
+ get connectionCount(): number;
99
54
  }
100
55
  //# sourceMappingURL=o-node-connection.manager.d.ts.map
@@ -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,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,4BAA4B,EAAE,MAAM,kDAAkD,CAAC;AAEhG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,qBAAa,sBAAuB,SAAQ,kBAAkB;IAQhD,QAAQ,CAAC,MAAM,EAAE,4BAA4B;IAPzD,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACxC,SAAS,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IACzC,iEAAiE;IACjE,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAa;IACxE,SAAS,CAAC,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAa;gBAEzD,MAAM,EAAE,4BAA4B;IAWzD;;OAEG;IACH,SAAS,CAAC,wBAAwB,IAAI,IAAI;IA+B1C;;;;;OAKG;IACH,SAAS,CAAC,aAAa,CAAC,OAAO,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI;IASzD;;;;OAIG;IACH,SAAS,CAAC,oBAAoB,CAAC,OAAO,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI;IAahE;;;;;;OAMG;IACH,SAAS,CAAC,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAkBxE;;;;OAIG;IACH,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAY1E;;;;;OAKG;IACH,4BAA4B,CAC1B,aAAa,EAAE,UAAU,GACxB,eAAe,GAAG,SAAS;IAa9B;;;OAGG;cACa,wBAAwB,CACtC,cAAc,EAAE,QAAQ,EACxB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,CAAC;cAoCN,WAAW,CACzB,cAAc,EAAE,QAAQ,EACxB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,CAAC;IAqBhB,MAAM,CACV,MAAM,EAAE,iBAAiB,GAAG;QAAE,aAAa,EAAE,UAAU,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GACzE,OAAO,CAAC,eAAe,CAAC;IA4D3B;;;;OAIG;IACG,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC;IAwDlE;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO;IAcpC;;;;OAIG;IACH,mBAAmB,CAAC,OAAO,EAAE,QAAQ,GAAG,eAAe,GAAG,IAAI;IAc9D;;;OAGG;IACH,aAAa,IAAI;QACf,eAAe,EAAE,MAAM,CAAC;QACxB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,YAAY,EAAE,MAAM,CAAC;QACrB,iBAAiB,EAAE,KAAK,CAAC;YACvB,MAAM,EAAE,MAAM,CAAC;YACf,MAAM,EAAE,MAAM,CAAC;YACf,UAAU,EAAE,MAAM,CAAC;SACpB,CAAC,CAAC;KACJ;IAyBD;;;OAGG;IACH,uBAAuB,IAAI,MAAM;CAuBlC"}
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,EAAqB,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,kDAAkD,CAAC;AAChG,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AAGjF;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,kBAAkB;IAShD,QAAQ,CAAC,MAAM,EAAE,4BAA4B;IARzD,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACxC,SAAS,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IACzC,iEAAiE;IACjE,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAa;IACtE,SAAS,CAAC,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAa;IAC9E,SAAS,CAAC,YAAY,EAAE,YAAY,CAAsB;gBAErC,MAAM,EAAE,4BAA4B;IAWzD;;OAEG;IACH,SAAS,CAAC,wBAAwB,IAAI,IAAI;IAY1C;;;;OAIG;IACH,SAAS,CAAC,oBAAoB,CAAC,OAAO,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI;IAahE;;;;OAIG;IACH,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI;IAWtD;;;OAGG;cACa,wBAAwB,CACtC,cAAc,EAAE,QAAQ,EACxB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,CAAC;cAoBN,WAAW,CACzB,cAAc,EAAE,QAAQ,EACxB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,CAAC;IAqBhB,gBAAgB,CACpB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,eAAe,CAAC;IAIrB,MAAM,CACV,MAAM,EAAE,qBAAqB,EAC7B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,eAAe,CAAC;IAgE3B;;;;OAIG;IACG,OAAO,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC;IAyDtE,8BAA8B,CAC5B,OAAO,EAAE,YAAY,GACpB,eAAe,GAAG,IAAI;IAezB,IAAI,eAAe,WAElB;CACF"}