@labostack/typebridge 0.1.0
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/README.md +62 -0
- package/dist/adapters/decorators.d.ts +11 -0
- package/dist/adapters/decorators.d.ts.map +1 -0
- package/dist/adapters/decorators.js +20 -0
- package/dist/adapters/decorators.js.map +1 -0
- package/dist/adapters/deepkit-adapter.d.ts +11 -0
- package/dist/adapters/deepkit-adapter.d.ts.map +1 -0
- package/dist/adapters/deepkit-adapter.js +39 -0
- package/dist/adapters/deepkit-adapter.js.map +1 -0
- package/dist/adapters/generic-adapter.d.ts +12 -0
- package/dist/adapters/generic-adapter.d.ts.map +1 -0
- package/dist/adapters/generic-adapter.js +28 -0
- package/dist/adapters/generic-adapter.js.map +1 -0
- package/dist/adapters/index.d.ts +5 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +5 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/nest-adapter.d.ts +14 -0
- package/dist/adapters/nest-adapter.d.ts.map +1 -0
- package/dist/adapters/nest-adapter.js +33 -0
- package/dist/adapters/nest-adapter.js.map +1 -0
- package/dist/adapters/tsed-adapter.d.ts +10 -0
- package/dist/adapters/tsed-adapter.d.ts.map +1 -0
- package/dist/adapters/tsed-adapter.js +31 -0
- package/dist/adapters/tsed-adapter.js.map +1 -0
- package/dist/autobarrel/index.d.ts +2 -0
- package/dist/autobarrel/index.d.ts.map +1 -0
- package/dist/autobarrel/index.js +2 -0
- package/dist/autobarrel/index.js.map +1 -0
- package/dist/autobarrel/scanner.d.ts +14 -0
- package/dist/autobarrel/scanner.d.ts.map +1 -0
- package/dist/autobarrel/scanner.js +93 -0
- package/dist/autobarrel/scanner.js.map +1 -0
- package/dist/bridge.d.ts +54 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +151 -0
- package/dist/bridge.js.map +1 -0
- package/dist/discovery/dns.d.ts +10 -0
- package/dist/discovery/dns.d.ts.map +1 -0
- package/dist/discovery/dns.js +19 -0
- package/dist/discovery/dns.js.map +1 -0
- package/dist/discovery/index.d.ts +4 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.js +4 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/discovery/mdns.d.ts +18 -0
- package/dist/discovery/mdns.d.ts.map +1 -0
- package/dist/discovery/mdns.js +49 -0
- package/dist/discovery/mdns.js.map +1 -0
- package/dist/discovery/resolver.d.ts +16 -0
- package/dist/discovery/resolver.d.ts.map +1 -0
- package/dist/discovery/resolver.js +36 -0
- package/dist/discovery/resolver.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/mesh/index.d.ts +2 -0
- package/dist/mesh/index.d.ts.map +1 -0
- package/dist/mesh/index.js +2 -0
- package/dist/mesh/index.js.map +1 -0
- package/dist/mesh/mesh-manager.d.ts +55 -0
- package/dist/mesh/mesh-manager.d.ts.map +1 -0
- package/dist/mesh/mesh-manager.js +179 -0
- package/dist/mesh/mesh-manager.js.map +1 -0
- package/dist/proxy/client-proxy.d.ts +20 -0
- package/dist/proxy/client-proxy.d.ts.map +1 -0
- package/dist/proxy/client-proxy.js +69 -0
- package/dist/proxy/client-proxy.js.map +1 -0
- package/dist/proxy/index.d.ts +2 -0
- package/dist/proxy/index.d.ts.map +1 -0
- package/dist/proxy/index.js +2 -0
- package/dist/proxy/index.js.map +1 -0
- package/dist/reflection/extractor.d.ts +13 -0
- package/dist/reflection/extractor.d.ts.map +1 -0
- package/dist/reflection/extractor.js +62 -0
- package/dist/reflection/extractor.js.map +1 -0
- package/dist/reflection/index.d.ts +2 -0
- package/dist/reflection/index.d.ts.map +1 -0
- package/dist/reflection/index.js +2 -0
- package/dist/reflection/index.js.map +1 -0
- package/dist/registry/index.d.ts +3 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +2 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/method-registry.d.ts +56 -0
- package/dist/registry/method-registry.d.ts.map +1 -0
- package/dist/registry/method-registry.js +84 -0
- package/dist/registry/method-registry.js.map +1 -0
- package/dist/serialization/error-ext.d.ts +38 -0
- package/dist/serialization/error-ext.d.ts.map +1 -0
- package/dist/serialization/error-ext.js +76 -0
- package/dist/serialization/error-ext.js.map +1 -0
- package/dist/serialization/index.d.ts +4 -0
- package/dist/serialization/index.d.ts.map +1 -0
- package/dist/serialization/index.js +3 -0
- package/dist/serialization/index.js.map +1 -0
- package/dist/serialization/msgpack.d.ts +30 -0
- package/dist/serialization/msgpack.d.ts.map +1 -0
- package/dist/serialization/msgpack.js +76 -0
- package/dist/serialization/msgpack.js.map +1 -0
- package/dist/serialization/serializer.d.ts +15 -0
- package/dist/serialization/serializer.d.ts.map +1 -0
- package/dist/serialization/serializer.js +2 -0
- package/dist/serialization/serializer.js.map +1 -0
- package/dist/transport/client.d.ts +38 -0
- package/dist/transport/client.d.ts.map +1 -0
- package/dist/transport/client.js +57 -0
- package/dist/transport/client.js.map +1 -0
- package/dist/transport/connection.d.ts +57 -0
- package/dist/transport/connection.d.ts.map +1 -0
- package/dist/transport/connection.js +212 -0
- package/dist/transport/connection.js.map +1 -0
- package/dist/transport/constants.d.ts +2 -0
- package/dist/transport/constants.d.ts.map +1 -0
- package/dist/transport/constants.js +2 -0
- package/dist/transport/constants.js.map +1 -0
- package/dist/transport/framing.d.ts +54 -0
- package/dist/transport/framing.d.ts.map +1 -0
- package/dist/transport/framing.js +107 -0
- package/dist/transport/framing.js.map +1 -0
- package/dist/transport/index.d.ts +7 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +7 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/peer-manager.d.ts +67 -0
- package/dist/transport/peer-manager.d.ts.map +1 -0
- package/dist/transport/peer-manager.js +172 -0
- package/dist/transport/peer-manager.js.map +1 -0
- package/dist/transport/server.d.ts +37 -0
- package/dist/transport/server.d.ts.map +1 -0
- package/dist/transport/server.js +88 -0
- package/dist/transport/server.js.map +1 -0
- package/dist/types/adapter.d.ts +33 -0
- package/dist/types/adapter.d.ts.map +1 -0
- package/dist/types/adapter.js +2 -0
- package/dist/types/adapter.js.map +1 -0
- package/dist/types/descriptor.d.ts +35 -0
- package/dist/types/descriptor.d.ts.map +1 -0
- package/dist/types/descriptor.js +2 -0
- package/dist/types/descriptor.js.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/options.d.ts +55 -0
- package/dist/types/options.d.ts.map +1 -0
- package/dist/types/options.js +6 -0
- package/dist/types/options.js.map +1 -0
- package/dist/types/protocol.d.ts +94 -0
- package/dist/types/protocol.d.ts.map +1 -0
- package/dist/types/protocol.js +43 -0
- package/dist/types/protocol.js.map +1 -0
- package/dist/types/type-descriptor.d.ts +64 -0
- package/dist/types/type-descriptor.d.ts.map +1 -0
- package/dist/types/type-descriptor.js +2 -0
- package/dist/types/type-descriptor.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type MessageType, FrameFlags } from "./constants.js";
|
|
2
|
+
/**
|
|
3
|
+
* A parsed frame from the wire.
|
|
4
|
+
*
|
|
5
|
+
* Frame layout (Little-Endian, 13 bytes header):
|
|
6
|
+
* [Magic 2B][Version 1B][Flags 1B][PayloadLen 4B][ReqID 4B][MsgType 1B][Payload...]
|
|
7
|
+
*/
|
|
8
|
+
export interface Frame {
|
|
9
|
+
/** Protocol version */
|
|
10
|
+
version: number;
|
|
11
|
+
/** Frame flags (compression, final, etc.) */
|
|
12
|
+
flags: FrameFlags;
|
|
13
|
+
/** Request ID for multiplexing (multiple in-flight requests on one connection) */
|
|
14
|
+
requestId: number;
|
|
15
|
+
/** Message type (Request, Response, Error, Handshake, etc.) */
|
|
16
|
+
messageType: MessageType;
|
|
17
|
+
/** Raw payload bytes (MessagePack-encoded) */
|
|
18
|
+
payload: Buffer;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Encode a Frame into a binary buffer ready for the wire.
|
|
22
|
+
*/
|
|
23
|
+
export declare function encodeFrame(frame: Frame): Buffer;
|
|
24
|
+
/**
|
|
25
|
+
* Result of attempting to decode a frame from a buffer.
|
|
26
|
+
*/
|
|
27
|
+
export interface DecodeResult {
|
|
28
|
+
/** The decoded frame, or null if buffer doesn't contain a complete frame */
|
|
29
|
+
frame: Frame | null;
|
|
30
|
+
/** Number of bytes consumed from the buffer */
|
|
31
|
+
bytesConsumed: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Attempt to decode a single frame from a buffer.
|
|
35
|
+
*
|
|
36
|
+
* Returns null frame if the buffer doesn't contain a complete frame yet
|
|
37
|
+
* (partial read — need to wait for more data).
|
|
38
|
+
*/
|
|
39
|
+
export declare function decodeFrame(buffer: Buffer): DecodeResult;
|
|
40
|
+
/**
|
|
41
|
+
* FrameReader accumulates data from TCP chunks and yields complete frames.
|
|
42
|
+
* Handles partial reads gracefully (TCP can deliver data in arbitrary chunks).
|
|
43
|
+
*/
|
|
44
|
+
export declare class FrameReader {
|
|
45
|
+
private buffer;
|
|
46
|
+
/**
|
|
47
|
+
* Feed raw TCP data into the reader.
|
|
48
|
+
* Returns an array of complete frames parsed from the accumulated buffer.
|
|
49
|
+
*/
|
|
50
|
+
feed(data: Buffer): Frame[];
|
|
51
|
+
/** Reset the internal buffer */
|
|
52
|
+
reset(): void;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=framing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framing.d.ts","sourceRoot":"","sources":["../../src/transport/framing.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,WAAW,EAChB,UAAU,EACX,MAAM,gBAAgB,CAAC;AAExB;;;;;GAKG;AACH,MAAM,WAAW,KAAK;IACpB,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,KAAK,EAAE,UAAU,CAAC;IAClB,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,WAAW,EAAE,WAAW,CAAC;IACzB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CA4BhD;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,+CAA+C;IAC/C,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAyDxD;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA2B;IAEzC;;;OAGG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,EAAE;IAmB3B,gCAAgC;IAChC,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { FRAME_MAGIC, FRAME_HEADER_SIZE, } from "./constants.js";
|
|
2
|
+
/**
|
|
3
|
+
* Encode a Frame into a binary buffer ready for the wire.
|
|
4
|
+
*/
|
|
5
|
+
export function encodeFrame(frame) {
|
|
6
|
+
const header = Buffer.alloc(FRAME_HEADER_SIZE);
|
|
7
|
+
let offset = 0;
|
|
8
|
+
// Magic (2 bytes, Big-Endian for readability in hex dumps)
|
|
9
|
+
header.writeUInt16BE(FRAME_MAGIC, offset);
|
|
10
|
+
offset += 2;
|
|
11
|
+
// Version (1 byte)
|
|
12
|
+
header.writeUInt8(frame.version, offset);
|
|
13
|
+
offset += 1;
|
|
14
|
+
// Flags (1 byte)
|
|
15
|
+
header.writeUInt8(frame.flags, offset);
|
|
16
|
+
offset += 1;
|
|
17
|
+
// Payload length (4 bytes, Little-Endian)
|
|
18
|
+
header.writeUInt32LE(frame.payload.length, offset);
|
|
19
|
+
offset += 4;
|
|
20
|
+
// Request ID (4 bytes, Little-Endian)
|
|
21
|
+
header.writeUInt32LE(frame.requestId, offset);
|
|
22
|
+
offset += 4;
|
|
23
|
+
// Message type (1 byte)
|
|
24
|
+
header.writeUInt8(frame.messageType, offset);
|
|
25
|
+
return Buffer.concat([header, frame.payload]);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Attempt to decode a single frame from a buffer.
|
|
29
|
+
*
|
|
30
|
+
* Returns null frame if the buffer doesn't contain a complete frame yet
|
|
31
|
+
* (partial read — need to wait for more data).
|
|
32
|
+
*/
|
|
33
|
+
export function decodeFrame(buffer) {
|
|
34
|
+
// Not enough bytes for header
|
|
35
|
+
if (buffer.length < FRAME_HEADER_SIZE) {
|
|
36
|
+
return { frame: null, bytesConsumed: 0 };
|
|
37
|
+
}
|
|
38
|
+
let offset = 0;
|
|
39
|
+
// Validate magic
|
|
40
|
+
const magic = buffer.readUInt16BE(offset);
|
|
41
|
+
offset += 2;
|
|
42
|
+
if (magic !== FRAME_MAGIC) {
|
|
43
|
+
throw new Error(`Invalid frame magic: expected 0x${FRAME_MAGIC.toString(16)}, got 0x${magic.toString(16)}`);
|
|
44
|
+
}
|
|
45
|
+
// Version
|
|
46
|
+
const version = buffer.readUInt8(offset);
|
|
47
|
+
offset += 1;
|
|
48
|
+
// Flags
|
|
49
|
+
const flags = buffer.readUInt8(offset);
|
|
50
|
+
offset += 1;
|
|
51
|
+
// Payload length
|
|
52
|
+
const payloadLength = buffer.readUInt32LE(offset);
|
|
53
|
+
offset += 4;
|
|
54
|
+
// Request ID
|
|
55
|
+
const requestId = buffer.readUInt32LE(offset);
|
|
56
|
+
offset += 4;
|
|
57
|
+
// Message type
|
|
58
|
+
const messageType = buffer.readUInt8(offset);
|
|
59
|
+
offset += 1;
|
|
60
|
+
// Check if we have the full payload
|
|
61
|
+
const totalFrameSize = FRAME_HEADER_SIZE + payloadLength;
|
|
62
|
+
if (buffer.length < totalFrameSize) {
|
|
63
|
+
return { frame: null, bytesConsumed: 0 };
|
|
64
|
+
}
|
|
65
|
+
// Extract payload
|
|
66
|
+
const payload = buffer.subarray(FRAME_HEADER_SIZE, totalFrameSize);
|
|
67
|
+
return {
|
|
68
|
+
frame: {
|
|
69
|
+
version,
|
|
70
|
+
flags,
|
|
71
|
+
requestId,
|
|
72
|
+
messageType,
|
|
73
|
+
payload: Buffer.from(payload), // copy to avoid buffer reuse issues
|
|
74
|
+
},
|
|
75
|
+
bytesConsumed: totalFrameSize,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* FrameReader accumulates data from TCP chunks and yields complete frames.
|
|
80
|
+
* Handles partial reads gracefully (TCP can deliver data in arbitrary chunks).
|
|
81
|
+
*/
|
|
82
|
+
export class FrameReader {
|
|
83
|
+
buffer = Buffer.alloc(0);
|
|
84
|
+
/**
|
|
85
|
+
* Feed raw TCP data into the reader.
|
|
86
|
+
* Returns an array of complete frames parsed from the accumulated buffer.
|
|
87
|
+
*/
|
|
88
|
+
feed(data) {
|
|
89
|
+
this.buffer = Buffer.concat([this.buffer, data]);
|
|
90
|
+
const frames = [];
|
|
91
|
+
while (this.buffer.length >= FRAME_HEADER_SIZE) {
|
|
92
|
+
const result = decodeFrame(this.buffer);
|
|
93
|
+
if (result.frame === null) {
|
|
94
|
+
// Incomplete frame — wait for more data
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
frames.push(result.frame);
|
|
98
|
+
this.buffer = this.buffer.subarray(result.bytesConsumed);
|
|
99
|
+
}
|
|
100
|
+
return frames;
|
|
101
|
+
}
|
|
102
|
+
/** Reset the internal buffer */
|
|
103
|
+
reset() {
|
|
104
|
+
this.buffer = Buffer.alloc(0);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=framing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framing.js","sourceRoot":"","sources":["../../src/transport/framing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { TransportServer, type TransportServerOptions } from "./server.js";
|
|
2
|
+
export { TransportClient, type TransportClientOptions } from "./client.js";
|
|
3
|
+
export { Connection } from "./connection.js";
|
|
4
|
+
export { PeerManager, PeerConnection } from "./peer-manager.js";
|
|
5
|
+
export { encodeFrame, decodeFrame, FrameReader, type Frame, type DecodeResult, } from "./framing.js";
|
|
6
|
+
export { FRAME_MAGIC, PROTOCOL_VERSION, FRAME_HEADER_SIZE, MessageType, FrameFlags, } from "./constants.js";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,KAAK,KAAK,EACV,KAAK,YAAY,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,UAAU,GACX,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { TransportServer } from "./server.js";
|
|
2
|
+
export { TransportClient } from "./client.js";
|
|
3
|
+
export { Connection } from "./connection.js";
|
|
4
|
+
export { PeerManager, PeerConnection } from "./peer-manager.js";
|
|
5
|
+
export { encodeFrame, decodeFrame, FrameReader, } from "./framing.js";
|
|
6
|
+
export { FRAME_MAGIC, PROTOCOL_VERSION, FRAME_HEADER_SIZE, MessageType, FrameFlags, } from "./constants.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAA+B,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,eAAe,EAA+B,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,GAGZ,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,UAAU,GACX,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import type { Connection } from "./connection.js";
|
|
3
|
+
import type { MethodRegistry } from "../registry/method-registry.js";
|
|
4
|
+
import type { PeerTarget } from "../types/options.js";
|
|
5
|
+
/**
|
|
6
|
+
* Manages outbound peer connections with:
|
|
7
|
+
* - Lazy connect (no network call until first RPC)
|
|
8
|
+
* - Retry with exponential backoff
|
|
9
|
+
* - Auto-reconnect on drop
|
|
10
|
+
* - Connection caching
|
|
11
|
+
*/
|
|
12
|
+
export declare class PeerManager {
|
|
13
|
+
/** Local registry — so incoming requests on peer connections can be handled */
|
|
14
|
+
private readonly localRegistry;
|
|
15
|
+
/** Local node name — sent during handshake */
|
|
16
|
+
private readonly localName;
|
|
17
|
+
private peers;
|
|
18
|
+
constructor(
|
|
19
|
+
/** Local registry — so incoming requests on peer connections can be handled */
|
|
20
|
+
localRegistry: MethodRegistry,
|
|
21
|
+
/** Local node name — sent during handshake */
|
|
22
|
+
localName: string);
|
|
23
|
+
/**
|
|
24
|
+
* Get or create a PeerConnection for a given target.
|
|
25
|
+
*/
|
|
26
|
+
getPeer(nameOrOptions: string | PeerTarget): PeerConnection;
|
|
27
|
+
/**
|
|
28
|
+
* Close all peer connections.
|
|
29
|
+
*/
|
|
30
|
+
closeAll(): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A single peer connection with retry logic.
|
|
34
|
+
*/
|
|
35
|
+
export declare class PeerConnection extends EventEmitter {
|
|
36
|
+
private readonly target;
|
|
37
|
+
private readonly localRegistry;
|
|
38
|
+
private readonly localName;
|
|
39
|
+
private connection;
|
|
40
|
+
private connectingPromise;
|
|
41
|
+
private client;
|
|
42
|
+
private closed;
|
|
43
|
+
/** Backoff config */
|
|
44
|
+
private readonly minDelay;
|
|
45
|
+
private readonly maxDelay;
|
|
46
|
+
private readonly backoffFactor;
|
|
47
|
+
constructor(target: string | PeerTarget, localRegistry: MethodRegistry, localName: string);
|
|
48
|
+
/**
|
|
49
|
+
* Ensure a connection is established.
|
|
50
|
+
* If not connected, connects with retry + exponential backoff.
|
|
51
|
+
* Returns the active connection.
|
|
52
|
+
*/
|
|
53
|
+
ensureConnected(): Promise<Connection>;
|
|
54
|
+
/**
|
|
55
|
+
* Connect with exponential backoff retry.
|
|
56
|
+
*/
|
|
57
|
+
private connectWithRetry;
|
|
58
|
+
/**
|
|
59
|
+
* Single connection attempt.
|
|
60
|
+
*/
|
|
61
|
+
private doConnect;
|
|
62
|
+
/**
|
|
63
|
+
* Close this peer connection.
|
|
64
|
+
*/
|
|
65
|
+
close(): Promise<void>;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=peer-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-manager.d.ts","sourceRoot":"","sources":["../../src/transport/peer-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAErE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD;;;;;;GAMG;AACH,qBAAa,WAAW;IAIpB,+EAA+E;IAC/E,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,8CAA8C;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS;IAN5B,OAAO,CAAC,KAAK,CAAqC;;IAGhD,+EAA+E;IAC9D,aAAa,EAAE,cAAc;IAC9C,8CAA8C;IAC7B,SAAS,EAAE,MAAM;IAGpC;;OAEG;IACH,OAAO,CAAC,aAAa,EAAE,MAAM,GAAG,UAAU,GAAG,cAAc;IAa3D;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAKhC;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAY5C,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAb5B,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,iBAAiB,CAAoC;IAC7D,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,MAAM,CAAS;IAEvB,qBAAqB;IACrB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAO;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAK;gBAGhB,MAAM,EAAE,MAAM,GAAG,UAAU,EAC3B,aAAa,EAAE,cAAc,EAC7B,SAAS,EAAE,MAAM;IAKpC;;;;OAIG;IACG,eAAe,IAAI,OAAO,CAAC,UAAU,CAAC;IA0B5C;;OAEG;YACW,gBAAgB;IAsB9B;;OAEG;YACW,SAAS;IAmDvB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAM7B"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import { TransportClient } from "./client.js";
|
|
3
|
+
import { resolveService } from "../discovery/resolver.js";
|
|
4
|
+
/**
|
|
5
|
+
* Manages outbound peer connections with:
|
|
6
|
+
* - Lazy connect (no network call until first RPC)
|
|
7
|
+
* - Retry with exponential backoff
|
|
8
|
+
* - Auto-reconnect on drop
|
|
9
|
+
* - Connection caching
|
|
10
|
+
*/
|
|
11
|
+
export class PeerManager {
|
|
12
|
+
localRegistry;
|
|
13
|
+
localName;
|
|
14
|
+
peers = new Map();
|
|
15
|
+
constructor(
|
|
16
|
+
/** Local registry — so incoming requests on peer connections can be handled */
|
|
17
|
+
localRegistry,
|
|
18
|
+
/** Local node name — sent during handshake */
|
|
19
|
+
localName) {
|
|
20
|
+
this.localRegistry = localRegistry;
|
|
21
|
+
this.localName = localName;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get or create a PeerConnection for a given target.
|
|
25
|
+
*/
|
|
26
|
+
getPeer(nameOrOptions) {
|
|
27
|
+
const key = typeof nameOrOptions === "string"
|
|
28
|
+
? nameOrOptions
|
|
29
|
+
: `${nameOrOptions.host}:${nameOrOptions.port}`;
|
|
30
|
+
let peer = this.peers.get(key);
|
|
31
|
+
if (!peer) {
|
|
32
|
+
peer = new PeerConnection(nameOrOptions, this.localRegistry, this.localName);
|
|
33
|
+
this.peers.set(key, peer);
|
|
34
|
+
}
|
|
35
|
+
return peer;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Close all peer connections.
|
|
39
|
+
*/
|
|
40
|
+
async closeAll() {
|
|
41
|
+
const closeTasks = Array.from(this.peers.values()).map((p) => p.close());
|
|
42
|
+
await Promise.allSettled(closeTasks);
|
|
43
|
+
this.peers.clear();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* A single peer connection with retry logic.
|
|
48
|
+
*/
|
|
49
|
+
export class PeerConnection extends EventEmitter {
|
|
50
|
+
target;
|
|
51
|
+
localRegistry;
|
|
52
|
+
localName;
|
|
53
|
+
connection = null;
|
|
54
|
+
connectingPromise = null;
|
|
55
|
+
client = null;
|
|
56
|
+
closed = false;
|
|
57
|
+
/** Backoff config */
|
|
58
|
+
minDelay = 100;
|
|
59
|
+
maxDelay = 5000;
|
|
60
|
+
backoffFactor = 2;
|
|
61
|
+
constructor(target, localRegistry, localName) {
|
|
62
|
+
super();
|
|
63
|
+
this.target = target;
|
|
64
|
+
this.localRegistry = localRegistry;
|
|
65
|
+
this.localName = localName;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Ensure a connection is established.
|
|
69
|
+
* If not connected, connects with retry + exponential backoff.
|
|
70
|
+
* Returns the active connection.
|
|
71
|
+
*/
|
|
72
|
+
async ensureConnected() {
|
|
73
|
+
if (this.closed) {
|
|
74
|
+
throw new Error("PeerConnection is closed");
|
|
75
|
+
}
|
|
76
|
+
// Already connected and socket is alive
|
|
77
|
+
if (this.connection && !this.connection.isClosed) {
|
|
78
|
+
return this.connection;
|
|
79
|
+
}
|
|
80
|
+
// Another caller is already connecting — wait for it
|
|
81
|
+
if (this.connectingPromise) {
|
|
82
|
+
return this.connectingPromise;
|
|
83
|
+
}
|
|
84
|
+
// Start a new connection attempt
|
|
85
|
+
this.connectingPromise = this.connectWithRetry();
|
|
86
|
+
try {
|
|
87
|
+
const conn = await this.connectingPromise;
|
|
88
|
+
return conn;
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
this.connectingPromise = null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Connect with exponential backoff retry.
|
|
96
|
+
*/
|
|
97
|
+
async connectWithRetry() {
|
|
98
|
+
let delay = this.minDelay;
|
|
99
|
+
let attempt = 0;
|
|
100
|
+
while (!this.closed) {
|
|
101
|
+
try {
|
|
102
|
+
return await this.doConnect();
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
attempt++;
|
|
106
|
+
if (this.closed) {
|
|
107
|
+
throw new Error("PeerConnection closed during connect");
|
|
108
|
+
}
|
|
109
|
+
// Wait with exponential backoff
|
|
110
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
111
|
+
delay = Math.min(delay * this.backoffFactor, this.maxDelay);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
throw new Error("PeerConnection closed");
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Single connection attempt.
|
|
118
|
+
*/
|
|
119
|
+
async doConnect() {
|
|
120
|
+
// Resolve the target
|
|
121
|
+
const resolved = await resolveService(this.target);
|
|
122
|
+
// Create client and connect
|
|
123
|
+
this.client = new TransportClient({
|
|
124
|
+
host: resolved.host,
|
|
125
|
+
port: resolved.port,
|
|
126
|
+
});
|
|
127
|
+
const connection = await this.client.connect();
|
|
128
|
+
// Send handshake with our name
|
|
129
|
+
connection.sendHandshake({ name: this.localName, version: 1 });
|
|
130
|
+
// Wait for handshake ack
|
|
131
|
+
await new Promise((resolve, reject) => {
|
|
132
|
+
const timer = setTimeout(() => {
|
|
133
|
+
reject(new Error("Handshake timeout"));
|
|
134
|
+
}, 10_000);
|
|
135
|
+
connection.on("handshake-ack", () => {
|
|
136
|
+
clearTimeout(timer);
|
|
137
|
+
resolve();
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
// Wire incoming requests (bidirectional: peer can call our methods too)
|
|
141
|
+
connection.on("request", async (reqId, method, args) => {
|
|
142
|
+
try {
|
|
143
|
+
const [controllerName, methodName] = method.split(".");
|
|
144
|
+
if (!controllerName || !methodName) {
|
|
145
|
+
throw new Error(`Invalid method format: "${method}"`);
|
|
146
|
+
}
|
|
147
|
+
const result = await this.localRegistry.invoke(controllerName, methodName, args);
|
|
148
|
+
connection.sendResponse(reqId, result);
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
connection.sendError(reqId, error);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
// Handle disconnection — clear connection so next call reconnects
|
|
155
|
+
connection.on("close", () => {
|
|
156
|
+
this.connection = null;
|
|
157
|
+
});
|
|
158
|
+
this.connection = connection;
|
|
159
|
+
this.emit("connected", connection);
|
|
160
|
+
return connection;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Close this peer connection.
|
|
164
|
+
*/
|
|
165
|
+
async close() {
|
|
166
|
+
this.closed = true;
|
|
167
|
+
this.client?.close();
|
|
168
|
+
this.connection = null;
|
|
169
|
+
this.client = null;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=peer-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-manager.js","sourceRoot":"","sources":["../../src/transport/peer-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import type { Serializer } from "../serialization/serializer.js";
|
|
3
|
+
export interface TransportServerOptions {
|
|
4
|
+
/** Port to listen on. 0 = auto-assign. Default: 4242 */
|
|
5
|
+
port?: number;
|
|
6
|
+
/** Host to bind to. Default: "0.0.0.0" */
|
|
7
|
+
host?: string;
|
|
8
|
+
/** Serializer to use. Default: MsgPackSerializer */
|
|
9
|
+
serializer?: Serializer;
|
|
10
|
+
/** Request timeout in ms. Default: 30000 */
|
|
11
|
+
timeout?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* TCP transport server — listens for incoming connections and handles RPC.
|
|
15
|
+
*/
|
|
16
|
+
export declare class TransportServer extends EventEmitter {
|
|
17
|
+
private server;
|
|
18
|
+
private readonly connections;
|
|
19
|
+
private readonly serializer;
|
|
20
|
+
private readonly serverPort;
|
|
21
|
+
private readonly serverHost;
|
|
22
|
+
private readonly timeout;
|
|
23
|
+
private actualPort;
|
|
24
|
+
constructor(options?: TransportServerOptions);
|
|
25
|
+
/** The port the server is actually listening on (resolved after listen()) */
|
|
26
|
+
get port(): number;
|
|
27
|
+
/**
|
|
28
|
+
* Start listening for connections.
|
|
29
|
+
*/
|
|
30
|
+
listen(): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Gracefully close the server and all connections.
|
|
33
|
+
*/
|
|
34
|
+
close(): Promise<void>;
|
|
35
|
+
private handleConnection;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/transport/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAIjE,MAAM,WAAW,sBAAsB;IACrC,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;IACrD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,UAAU,CAAa;gBAEnB,OAAO,GAAE,sBAA2B;IAQhD,6EAA6E;IAC7E,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB7B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB5B,OAAO,CAAC,gBAAgB;CAuBzB"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { createServer } from "node:net";
|
|
2
|
+
import { EventEmitter } from "node:events";
|
|
3
|
+
import { Connection } from "./connection.js";
|
|
4
|
+
import { MsgPackSerializer } from "../serialization/msgpack.js";
|
|
5
|
+
import { DEFAULT_PORT } from "../types/options.js";
|
|
6
|
+
/**
|
|
7
|
+
* TCP transport server — listens for incoming connections and handles RPC.
|
|
8
|
+
*/
|
|
9
|
+
export class TransportServer extends EventEmitter {
|
|
10
|
+
server = null;
|
|
11
|
+
connections = new Set();
|
|
12
|
+
serializer;
|
|
13
|
+
serverPort;
|
|
14
|
+
serverHost;
|
|
15
|
+
timeout;
|
|
16
|
+
actualPort = 0;
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
super();
|
|
19
|
+
this.serializer = options.serializer ?? new MsgPackSerializer();
|
|
20
|
+
this.serverPort = options.port ?? DEFAULT_PORT;
|
|
21
|
+
this.serverHost = options.host ?? "0.0.0.0";
|
|
22
|
+
this.timeout = options.timeout ?? 30_000;
|
|
23
|
+
}
|
|
24
|
+
/** The port the server is actually listening on (resolved after listen()) */
|
|
25
|
+
get port() {
|
|
26
|
+
return this.actualPort;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Start listening for connections.
|
|
30
|
+
*/
|
|
31
|
+
async listen() {
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
this.server = createServer((socket) => {
|
|
34
|
+
this.handleConnection(socket);
|
|
35
|
+
});
|
|
36
|
+
this.server.on("error", (err) => {
|
|
37
|
+
this.emit("error", err);
|
|
38
|
+
reject(err);
|
|
39
|
+
});
|
|
40
|
+
this.server.listen(this.serverPort, this.serverHost, () => {
|
|
41
|
+
const addr = this.server.address();
|
|
42
|
+
if (addr && typeof addr === "object") {
|
|
43
|
+
this.actualPort = addr.port;
|
|
44
|
+
}
|
|
45
|
+
this.emit("listening", this.actualPort);
|
|
46
|
+
resolve();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Gracefully close the server and all connections.
|
|
52
|
+
*/
|
|
53
|
+
async close() {
|
|
54
|
+
// Close all active connections
|
|
55
|
+
for (const conn of this.connections) {
|
|
56
|
+
conn.close();
|
|
57
|
+
}
|
|
58
|
+
this.connections.clear();
|
|
59
|
+
// Close the server
|
|
60
|
+
return new Promise((resolve) => {
|
|
61
|
+
if (this.server) {
|
|
62
|
+
this.server.close(() => resolve());
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
resolve();
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
handleConnection(socket) {
|
|
70
|
+
const connection = new Connection(socket, this.serializer, this.timeout);
|
|
71
|
+
this.connections.add(connection);
|
|
72
|
+
connection.on("close", () => {
|
|
73
|
+
this.connections.delete(connection);
|
|
74
|
+
});
|
|
75
|
+
// Forward events
|
|
76
|
+
connection.on("request", (requestId, method, args) => {
|
|
77
|
+
this.emit("request", connection, requestId, method, args);
|
|
78
|
+
});
|
|
79
|
+
connection.on("handshake", (data) => {
|
|
80
|
+
this.emit("handshake", connection, data);
|
|
81
|
+
});
|
|
82
|
+
connection.on("error", (err) => {
|
|
83
|
+
this.emit("connection-error", connection, err);
|
|
84
|
+
});
|
|
85
|
+
this.emit("connection", connection);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/transport/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { MethodDescriptor } from "./descriptor.js";
|
|
2
|
+
/**
|
|
3
|
+
* FrameworkAdapter — Thin adapter layer for each framework.
|
|
4
|
+
*
|
|
5
|
+
* Each adapter knows how to:
|
|
6
|
+
* 1. Identify whether a class is a controller (via decorators or naming convention)
|
|
7
|
+
* 2. Extract method descriptors from a controller class
|
|
8
|
+
* 3. Optionally resolve a controller instance (e.g., from a DI container)
|
|
9
|
+
*/
|
|
10
|
+
export interface FrameworkAdapter {
|
|
11
|
+
/** Human-readable adapter name (e.g., "NestJS", "Ts.ED", "Generic") */
|
|
12
|
+
readonly name: string;
|
|
13
|
+
/**
|
|
14
|
+
* Check whether a given class/constructor is a controller in this framework.
|
|
15
|
+
* Used during autobarrel discovery and registration filtering.
|
|
16
|
+
*/
|
|
17
|
+
isController(target: unknown): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Extract all callable method descriptors from a controller class.
|
|
20
|
+
* The adapter inspects the class prototype (and optionally decorator metadata)
|
|
21
|
+
* to build a list of MethodDescriptors.
|
|
22
|
+
*/
|
|
23
|
+
extractMethods(controller: unknown): MethodDescriptor[];
|
|
24
|
+
/**
|
|
25
|
+
* Optionally resolve a live instance of the controller.
|
|
26
|
+
* Useful for frameworks with DI containers (NestJS, Ts.ED) where the controller
|
|
27
|
+
* class itself isn't directly instantiable.
|
|
28
|
+
*
|
|
29
|
+
* If not provided, TypeBridge will instantiate the class with `new`.
|
|
30
|
+
*/
|
|
31
|
+
resolveInstance?(controller: unknown): unknown;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/types/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC;IAEvC;;;;OAIG;IACH,cAAc,CAAC,UAAU,EAAE,OAAO,GAAG,gBAAgB,EAAE,CAAC;IAExD;;;;;;OAMG;IACH,eAAe,CAAC,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAAC;CAChD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/types/adapter.ts"],"names":[],"mappings":""}
|