@source-repo/rpc 3.0.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/LICENSE +21 -0
- package/README.md +1208 -0
- package/dist/Logging/ILogger.d.ts +7 -0
- package/dist/Logging/ILogger.d.ts.map +1 -0
- package/dist/Logging/ILogger.js +2 -0
- package/dist/Logging/ILogger.js.map +1 -0
- package/dist/NodeRpcServer.d.ts +55 -0
- package/dist/NodeRpcServer.d.ts.map +1 -0
- package/dist/NodeRpcServer.js +46 -0
- package/dist/NodeRpcServer.js.map +1 -0
- package/dist/RPC/Auth.d.ts +98 -0
- package/dist/RPC/Auth.d.ts.map +1 -0
- package/dist/RPC/Auth.js +14 -0
- package/dist/RPC/Auth.js.map +1 -0
- package/dist/RPC/Codec.d.ts +24 -0
- package/dist/RPC/Codec.d.ts.map +1 -0
- package/dist/RPC/Codec.js +21 -0
- package/dist/RPC/Codec.js.map +1 -0
- package/dist/RPC/Compatibility.d.ts +39 -0
- package/dist/RPC/Compatibility.d.ts.map +1 -0
- package/dist/RPC/Compatibility.js +195 -0
- package/dist/RPC/Compatibility.js.map +1 -0
- package/dist/RPC/Core.d.ts +188 -0
- package/dist/RPC/Core.d.ts.map +1 -0
- package/dist/RPC/Core.js +354 -0
- package/dist/RPC/Core.js.map +1 -0
- package/dist/RPC/Expose.d.ts +90 -0
- package/dist/RPC/Expose.d.ts.map +1 -0
- package/dist/RPC/Expose.js +110 -0
- package/dist/RPC/Expose.js.map +1 -0
- package/dist/RPC/Idempotency.d.ts +90 -0
- package/dist/RPC/Idempotency.d.ts.map +1 -0
- package/dist/RPC/Idempotency.js +46 -0
- package/dist/RPC/Idempotency.js.map +1 -0
- package/dist/RPC/Introspection.d.ts +92 -0
- package/dist/RPC/Introspection.d.ts.map +1 -0
- package/dist/RPC/Introspection.js +188 -0
- package/dist/RPC/Introspection.js.map +1 -0
- package/dist/RPC/Introspection.types.json +1093 -0
- package/dist/RPC/Messages.d.ts +108 -0
- package/dist/RPC/Messages.d.ts.map +1 -0
- package/dist/RPC/Messages.js +30 -0
- package/dist/RPC/Messages.js.map +1 -0
- package/dist/RPC/Rpc.d.ts +51 -0
- package/dist/RPC/Rpc.d.ts.map +1 -0
- package/dist/RPC/Rpc.js +54 -0
- package/dist/RPC/Rpc.js.map +1 -0
- package/dist/RPC/RpcClientHandler.d.ts +129 -0
- package/dist/RPC/RpcClientHandler.d.ts.map +1 -0
- package/dist/RPC/RpcClientHandler.js +267 -0
- package/dist/RPC/RpcClientHandler.js.map +1 -0
- package/dist/RPC/RpcServerHandler.d.ts +226 -0
- package/dist/RPC/RpcServerHandler.d.ts.map +1 -0
- package/dist/RPC/RpcServerHandler.js +676 -0
- package/dist/RPC/RpcServerHandler.js.map +1 -0
- package/dist/RPC/Schema.d.ts +150 -0
- package/dist/RPC/Schema.d.ts.map +1 -0
- package/dist/RPC/Schema.js +198 -0
- package/dist/RPC/Schema.js.map +1 -0
- package/dist/RPC/Signing.d.ts +118 -0
- package/dist/RPC/Signing.d.ts.map +1 -0
- package/dist/RPC/Signing.js +171 -0
- package/dist/RPC/Signing.js.map +1 -0
- package/dist/RPC/Tokens.d.ts +49 -0
- package/dist/RPC/Tokens.d.ts.map +1 -0
- package/dist/RPC/Tokens.js +45 -0
- package/dist/RPC/Tokens.js.map +1 -0
- package/dist/RpcClient.d.ts +91 -0
- package/dist/RpcClient.d.ts.map +1 -0
- package/dist/RpcClient.js +145 -0
- package/dist/RpcClient.js.map +1 -0
- package/dist/RpcServer.d.ts +191 -0
- package/dist/RpcServer.d.ts.map +1 -0
- package/dist/RpcServer.js +293 -0
- package/dist/RpcServer.js.map +1 -0
- package/dist/Transports/Mqtt5Frame.d.ts +107 -0
- package/dist/Transports/Mqtt5Frame.d.ts.map +1 -0
- package/dist/Transports/Mqtt5Frame.js +162 -0
- package/dist/Transports/Mqtt5Frame.js.map +1 -0
- package/dist/Transports/MqttTransport.d.ts +279 -0
- package/dist/Transports/MqttTransport.d.ts.map +1 -0
- package/dist/Transports/MqttTransport.js +843 -0
- package/dist/Transports/MqttTransport.js.map +1 -0
- package/dist/Transports/Presence.d.ts +68 -0
- package/dist/Transports/Presence.d.ts.map +1 -0
- package/dist/Transports/Presence.js +21 -0
- package/dist/Transports/Presence.js.map +1 -0
- package/dist/Transports/SocketIoClientTransport.d.ts +89 -0
- package/dist/Transports/SocketIoClientTransport.d.ts.map +1 -0
- package/dist/Transports/SocketIoClientTransport.js +280 -0
- package/dist/Transports/SocketIoClientTransport.js.map +1 -0
- package/dist/Transports/SocketIoServerTransport.d.ts +135 -0
- package/dist/Transports/SocketIoServerTransport.d.ts.map +1 -0
- package/dist/Transports/SocketIoServerTransport.js +505 -0
- package/dist/Transports/SocketIoServerTransport.js.map +1 -0
- package/dist/Utilities/Converters.d.ts +22 -0
- package/dist/Utilities/Converters.d.ts.map +1 -0
- package/dist/Utilities/Converters.js +58 -0
- package/dist/Utilities/Converters.js.map +1 -0
- package/dist/Utilities/Filter.d.ts +7 -0
- package/dist/Utilities/Filter.d.ts.map +1 -0
- package/dist/Utilities/Filter.js +14 -0
- package/dist/Utilities/Filter.js.map +1 -0
- package/dist/Utilities/ReadableName.d.ts +38 -0
- package/dist/Utilities/ReadableName.d.ts.map +1 -0
- package/dist/Utilities/ReadableName.js +58 -0
- package/dist/Utilities/ReadableName.js.map +1 -0
- package/dist/Utilities/Switch.d.ts +21 -0
- package/dist/Utilities/Switch.d.ts.map +1 -0
- package/dist/Utilities/Switch.js +70 -0
- package/dist/Utilities/Switch.js.map +1 -0
- package/dist/Utilities/TryCatch.d.ts +11 -0
- package/dist/Utilities/TryCatch.d.ts.map +1 -0
- package/dist/Utilities/TryCatch.js +13 -0
- package/dist/Utilities/TryCatch.js.map +1 -0
- package/dist/index-web.d.ts +25 -0
- package/dist/index-web.d.ts.map +1 -0
- package/dist/index-web.js +28 -0
- package/dist/index-web.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { RpcIdentity } from './Auth.js';
|
|
3
|
+
import { FrameCodec } from './Codec.js';
|
|
4
|
+
/**
|
|
5
|
+
* Upper bound on the framed header, in bytes, including the delimiter.
|
|
6
|
+
*
|
|
7
|
+
* It has to fit the largest header this library builds: two 128-character peer names, a timestamp,
|
|
8
|
+
* a sequence number, a hop count, a 24-character nonce and an 88-character Ed25519 signature come
|
|
9
|
+
* to roughly 470 bytes. The old value of 256 was under that, and since the receiver stopped looking
|
|
10
|
+
* for the delimiter at the limit, every frame with a header past it was dropped without a word -
|
|
11
|
+
* signed frames from peers whose names were merely descriptive, at around 34 characters each.
|
|
12
|
+
*/
|
|
13
|
+
export declare const MAX_HEADER_LENGTH = 1024;
|
|
14
|
+
export declare const HEADER_DELIMITER = "$";
|
|
15
|
+
/**
|
|
16
|
+
* Lifecycle events emitted by transports. Transports are EventEmitters, so anything above them
|
|
17
|
+
* can react to the link coming and going rather than discovering it via a call timeout.
|
|
18
|
+
*
|
|
19
|
+
* connected/disconnected are emitted by client-side transports on every transition, including
|
|
20
|
+
* reconnects. peerGone is emitted by server-side transports when an identified peer's connection
|
|
21
|
+
* drops, and peerOnline when one announces itself, which is how a peer is discovered at all.
|
|
22
|
+
* rejected is emitted when an inbound frame fails an authentication check. unroutable is emitted
|
|
23
|
+
* when a frame cannot be delivered to its target. peerDisplaced is emitted when a new connection
|
|
24
|
+
* announces a name another live connection already holds, and takes the route over.
|
|
25
|
+
*
|
|
26
|
+
* relayed is the one that is not about the link: it reports a frame this server is passing between
|
|
27
|
+
* two other peers, which is the only place traffic nobody here sent or received can be observed.
|
|
28
|
+
* It fires once per relayed frame, so it is emitted only when something is listening - see the
|
|
29
|
+
* guard at the call site.
|
|
30
|
+
*/
|
|
31
|
+
export declare const TransportEvent: {
|
|
32
|
+
readonly connected: 'connected';
|
|
33
|
+
readonly disconnected: 'disconnected';
|
|
34
|
+
readonly peerOnline: 'peerOnline';
|
|
35
|
+
readonly peerGone: 'peerGone';
|
|
36
|
+
readonly peerDisplaced: 'peerDisplaced';
|
|
37
|
+
readonly rejected: 'rejected';
|
|
38
|
+
readonly unroutable: 'unroutable';
|
|
39
|
+
readonly transportError: 'transportError';
|
|
40
|
+
readonly relayed: 'relayed';
|
|
41
|
+
};
|
|
42
|
+
/** A frame passing through this server on its way between two other peers. */
|
|
43
|
+
export interface RelayedFrame {
|
|
44
|
+
source: string;
|
|
45
|
+
target: string;
|
|
46
|
+
message: Message;
|
|
47
|
+
}
|
|
48
|
+
export interface IGenericModule<I = unknown, IP = unknown, O = unknown, OP = unknown> {
|
|
49
|
+
readyFlag: boolean;
|
|
50
|
+
pipe(target: IGenericModule): void;
|
|
51
|
+
receive(message: I, source: string, target?: string): Promise<void>;
|
|
52
|
+
receivePayload(payload: IP, source: string, target?: string): Promise<void>;
|
|
53
|
+
send(message: O, source: string, target?: string): Promise<void>;
|
|
54
|
+
sendPayload(payload: OP, messageType: MessageType, source: string, target?: string): Promise<void>;
|
|
55
|
+
ready(): Promise<boolean>;
|
|
56
|
+
getName(): string;
|
|
57
|
+
targetExists(name: string, level?: number): IGenericModule | undefined;
|
|
58
|
+
isTransport(): boolean;
|
|
59
|
+
close(): Promise<void>;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Which module a peer name was last seen on, so a reply can be routed back out of the transport
|
|
63
|
+
* its request arrived on.
|
|
64
|
+
*
|
|
65
|
+
* This was a static on GenericModule, which meant every client and server in one process shared a
|
|
66
|
+
* single map keyed by names supplied by remote peers. Two graphs using the same peer name routed
|
|
67
|
+
* into each other's transports, entries were never removed, and it grew for the life of the
|
|
68
|
+
* process. One registry is now shared by one connected set of modules and nothing wider.
|
|
69
|
+
*/
|
|
70
|
+
export declare class PeerRegistry {
|
|
71
|
+
/** Upper bound, since the keys come off the wire. Least recently seen entries go first. */
|
|
72
|
+
maxPeers: number;
|
|
73
|
+
private peers;
|
|
74
|
+
constructor(
|
|
75
|
+
/** Upper bound, since the keys come off the wire. Least recently seen entries go first. */
|
|
76
|
+
maxPeers?: number);
|
|
77
|
+
set(source: string, module: IGenericModule): void;
|
|
78
|
+
get(source: string): IGenericModule<unknown, unknown, unknown, unknown> | undefined;
|
|
79
|
+
delete(source: string): boolean;
|
|
80
|
+
clear(): void;
|
|
81
|
+
get size(): number;
|
|
82
|
+
/** Every peer currently routed through one module, which is how a bridge lists what it can reach. */
|
|
83
|
+
namesFor(module: IGenericModule): string[];
|
|
84
|
+
names(): string[];
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* A module that owns its wire format. RpcClient and RpcServer drive these directly rather than
|
|
88
|
+
* through a converter, so a transport whose framing is structured can see the message itself.
|
|
89
|
+
*/
|
|
90
|
+
export type Transport = GenericModule<Message, unknown, Message, unknown> & {
|
|
91
|
+
codec: FrameCodec;
|
|
92
|
+
};
|
|
93
|
+
export interface MessageHeader {
|
|
94
|
+
source: string;
|
|
95
|
+
target: string;
|
|
96
|
+
time: number;
|
|
97
|
+
seq: number;
|
|
98
|
+
/** How many relays this frame has already passed through. Absent means none. */
|
|
99
|
+
hops?: number;
|
|
100
|
+
/** Present on signed frames: single-use value that makes a captured frame unreplayable. */
|
|
101
|
+
nonce?: string;
|
|
102
|
+
/** Present on signed frames: base64 signature over the fields above plus the payload. */
|
|
103
|
+
sig?: string;
|
|
104
|
+
}
|
|
105
|
+
export declare class GenericModule<I = unknown, IP = unknown, O = unknown, OP = unknown> extends EventEmitter implements IGenericModule<I, IP, O, OP> {
|
|
106
|
+
name: string;
|
|
107
|
+
destinations: {
|
|
108
|
+
id: string;
|
|
109
|
+
target: IGenericModule;
|
|
110
|
+
}[];
|
|
111
|
+
/**
|
|
112
|
+
* Shared with the other modules in this graph by usePeerRegistry(). A module built on its own
|
|
113
|
+
* gets a private one, so it still routes correctly without leaking into anyone else's.
|
|
114
|
+
*/
|
|
115
|
+
peerRegistry: PeerRegistry;
|
|
116
|
+
readyFlag: boolean;
|
|
117
|
+
seq: number;
|
|
118
|
+
constructor(name: string, sources?: IGenericModule<unknown, unknown, I, IP>[]);
|
|
119
|
+
/**
|
|
120
|
+
* Waits for this module to come up, and gives up rather than waiting forever.
|
|
121
|
+
*
|
|
122
|
+
* The loop used to have no way out: a module that never became ready - one that failed to
|
|
123
|
+
* start, or was closed while something still awaited it - spun on a 10 ms timer for the life of
|
|
124
|
+
* the process, which is also long enough to keep the process alive with nothing left to do.
|
|
125
|
+
* Returning false says what happened; the overrides in RpcClient and RpcServer throw with the
|
|
126
|
+
* startup error instead, which is more than a bare module knows.
|
|
127
|
+
*/
|
|
128
|
+
ready(timeout?: number): Promise<boolean>;
|
|
129
|
+
open(): Promise<void>;
|
|
130
|
+
close(): Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Build the header a frame will carry. Separate from framing so a transport that signs can
|
|
133
|
+
* see the exact field values before they are serialised, and add its signature to them.
|
|
134
|
+
*/
|
|
135
|
+
buildHeader(source: string, target: string, extra?: Partial<MessageHeader>): MessageHeader;
|
|
136
|
+
prependHeader(source: string, target: string, message: string | Uint8Array): string | Uint8Array;
|
|
137
|
+
/**
|
|
138
|
+
* Throws when the header will not fit the frame, rather than emitting one no receiver can read.
|
|
139
|
+
* The sender is the only party that can do anything about an over-long peer name, and it learns
|
|
140
|
+
* nothing from a frame that leaves correctly and is discarded at the far end.
|
|
141
|
+
*/
|
|
142
|
+
frameMessage(header: MessageHeader, message: string | Uint8Array): string | Uint8Array;
|
|
143
|
+
/**
|
|
144
|
+
* Split a frame into its header and payload. Never throws: every frame here came off the
|
|
145
|
+
* network, and one malformed frame from one peer must not take down a process serving the rest.
|
|
146
|
+
* The third element says why nothing was extracted, so a dropped frame can be diagnosed instead
|
|
147
|
+
* of merely disappearing.
|
|
148
|
+
*/
|
|
149
|
+
extractHeader(message: string | Uint8Array): [MessageHeader | undefined, string | Uint8Array, string?];
|
|
150
|
+
getName(): string;
|
|
151
|
+
targetExists(name: string, level?: number): IGenericModule<unknown, unknown, unknown, unknown> | undefined;
|
|
152
|
+
pipe(target: IGenericModule<O, OP, unknown, unknown>): () => void;
|
|
153
|
+
receive(message: I, source: string, target: string): Promise<void>;
|
|
154
|
+
receivePayload(message: IP, source: string, target: string): Promise<void>;
|
|
155
|
+
send(message: O, source: string, target: string): Promise<void>;
|
|
156
|
+
setKnownSource(source: string): void;
|
|
157
|
+
/** Route peer lookups for this module through a registry shared with the rest of its graph. */
|
|
158
|
+
usePeerRegistry(registry: PeerRegistry): this;
|
|
159
|
+
/**
|
|
160
|
+
* The authenticated identity bound to a peer name, for transports that authenticate.
|
|
161
|
+
* Undefined means this transport cannot vouch for the peer, not that the peer is untrusted.
|
|
162
|
+
*/
|
|
163
|
+
getIdentity(source: string): RpcIdentity | undefined;
|
|
164
|
+
sendPayload(payload: OP, messageType: MessageType, source: string, target: string): Promise<void>;
|
|
165
|
+
isTransport(): boolean;
|
|
166
|
+
}
|
|
167
|
+
export declare enum MessageType {
|
|
168
|
+
RequestMessage = "REQUEST",
|
|
169
|
+
ResponseMessage = "RESPONSE",
|
|
170
|
+
ErrorMessage = "ERROR",
|
|
171
|
+
EventMessage = "EVENT",
|
|
172
|
+
UnknownMessage = "UNKNOWN"
|
|
173
|
+
}
|
|
174
|
+
export interface Payload {
|
|
175
|
+
}
|
|
176
|
+
export declare class Message<P = Payload> {
|
|
177
|
+
type?: MessageType;
|
|
178
|
+
payload?: P;
|
|
179
|
+
}
|
|
180
|
+
export declare class MessageModule<I extends Message<IP>, IP extends Payload, O extends Message<OP>, OP extends Payload> extends GenericModule<I, IP, O, OP> {
|
|
181
|
+
name: string;
|
|
182
|
+
constructor(name: string, sources?: IGenericModule<Message, unknown, I, IP>[]);
|
|
183
|
+
pipe(target: IGenericModule<O, OP, Message, unknown>): () => void;
|
|
184
|
+
receive(message: I, source: string, target: string): Promise<void>;
|
|
185
|
+
send(message: O, source: string, target?: string): Promise<void>;
|
|
186
|
+
sendPayload(payload: OP, messageType: MessageType, source: string, target?: string): Promise<void>;
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=Core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Core.d.ts","sourceRoot":"","sources":["../../src/RPC/Core.ts"],"names":[],"mappings":"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"}
|
package/dist/RPC/Core.js
ADDED
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { stringToUint8Array, uint8ArrayToString } from 'uint8array-extras';
|
|
3
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
4
|
+
/**
|
|
5
|
+
* Upper bound on the framed header, in bytes, including the delimiter.
|
|
6
|
+
*
|
|
7
|
+
* It has to fit the largest header this library builds: two 128-character peer names, a timestamp,
|
|
8
|
+
* a sequence number, a hop count, a 24-character nonce and an 88-character Ed25519 signature come
|
|
9
|
+
* to roughly 470 bytes. The old value of 256 was under that, and since the receiver stopped looking
|
|
10
|
+
* for the delimiter at the limit, every frame with a header past it was dropped without a word -
|
|
11
|
+
* signed frames from peers whose names were merely descriptive, at around 34 characters each.
|
|
12
|
+
*/
|
|
13
|
+
export const MAX_HEADER_LENGTH = 1024;
|
|
14
|
+
export const HEADER_DELIMITER = '$';
|
|
15
|
+
const CHAR = { openBrace: 0x7b, closeBrace: 0x7d, quote: 0x22, backslash: 0x5c, delimiter: 0x24 };
|
|
16
|
+
/**
|
|
17
|
+
* Index of the delimiter that ends the header, or -1 when there is no header to be found.
|
|
18
|
+
*
|
|
19
|
+
* Deliberately not indexOf('$'): the header is JSON, and a peer name containing a '$' puts one
|
|
20
|
+
* inside a quoted string where it is data rather than punctuation. Splitting on the first one cut
|
|
21
|
+
* the header mid-string, and the JSON.parse that followed threw - on the MQTT path, into an
|
|
22
|
+
* unhandled rejection. Reading with JSON's own quoting rules makes the split unambiguous, so a name
|
|
23
|
+
* can never reshape the frame it travels in.
|
|
24
|
+
*
|
|
25
|
+
* Scans code units rather than decoded text because every character it looks for is ASCII, and
|
|
26
|
+
* UTF-8 never produces those bytes inside a multi-byte sequence. A payload cut mid-character
|
|
27
|
+
* therefore cannot confuse it, which the previous decode-the-first-256-bytes approach could.
|
|
28
|
+
*/
|
|
29
|
+
const findHeaderEnd = (at, length) => {
|
|
30
|
+
if (length === 0 || at(0) !== CHAR.openBrace)
|
|
31
|
+
return -1;
|
|
32
|
+
const limit = Math.min(length, MAX_HEADER_LENGTH);
|
|
33
|
+
let depth = 0;
|
|
34
|
+
let inString = false;
|
|
35
|
+
let escaped = false;
|
|
36
|
+
for (let index = 0; index < limit; index++) {
|
|
37
|
+
const code = at(index);
|
|
38
|
+
if (inString) {
|
|
39
|
+
if (escaped)
|
|
40
|
+
escaped = false;
|
|
41
|
+
else if (code === CHAR.backslash)
|
|
42
|
+
escaped = true;
|
|
43
|
+
else if (code === CHAR.quote)
|
|
44
|
+
inString = false;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (code === CHAR.quote)
|
|
48
|
+
inString = true;
|
|
49
|
+
else if (code === CHAR.openBrace)
|
|
50
|
+
depth++;
|
|
51
|
+
else if (code === CHAR.closeBrace && --depth === 0) {
|
|
52
|
+
// The delimiter has to be the very next byte, or this is not a framed message.
|
|
53
|
+
const delimiter = index + 1;
|
|
54
|
+
return delimiter < limit && at(delimiter) === CHAR.delimiter ? delimiter : -1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return -1;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Lifecycle events emitted by transports. Transports are EventEmitters, so anything above them
|
|
61
|
+
* can react to the link coming and going rather than discovering it via a call timeout.
|
|
62
|
+
*
|
|
63
|
+
* connected/disconnected are emitted by client-side transports on every transition, including
|
|
64
|
+
* reconnects. peerGone is emitted by server-side transports when an identified peer's connection
|
|
65
|
+
* drops, and peerOnline when one announces itself, which is how a peer is discovered at all.
|
|
66
|
+
* rejected is emitted when an inbound frame fails an authentication check. unroutable is emitted
|
|
67
|
+
* when a frame cannot be delivered to its target. peerDisplaced is emitted when a new connection
|
|
68
|
+
* announces a name another live connection already holds, and takes the route over.
|
|
69
|
+
*
|
|
70
|
+
* relayed is the one that is not about the link: it reports a frame this server is passing between
|
|
71
|
+
* two other peers, which is the only place traffic nobody here sent or received can be observed.
|
|
72
|
+
* It fires once per relayed frame, so it is emitted only when something is listening - see the
|
|
73
|
+
* guard at the call site.
|
|
74
|
+
*/
|
|
75
|
+
export const TransportEvent = {
|
|
76
|
+
connected: 'connected',
|
|
77
|
+
disconnected: 'disconnected',
|
|
78
|
+
peerOnline: 'peerOnline',
|
|
79
|
+
peerGone: 'peerGone',
|
|
80
|
+
peerDisplaced: 'peerDisplaced',
|
|
81
|
+
rejected: 'rejected',
|
|
82
|
+
unroutable: 'unroutable',
|
|
83
|
+
transportError: 'transportError',
|
|
84
|
+
relayed: 'relayed'
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Which module a peer name was last seen on, so a reply can be routed back out of the transport
|
|
88
|
+
* its request arrived on.
|
|
89
|
+
*
|
|
90
|
+
* This was a static on GenericModule, which meant every client and server in one process shared a
|
|
91
|
+
* single map keyed by names supplied by remote peers. Two graphs using the same peer name routed
|
|
92
|
+
* into each other's transports, entries were never removed, and it grew for the life of the
|
|
93
|
+
* process. One registry is now shared by one connected set of modules and nothing wider.
|
|
94
|
+
*/
|
|
95
|
+
export class PeerRegistry {
|
|
96
|
+
maxPeers;
|
|
97
|
+
peers = new Map();
|
|
98
|
+
constructor(
|
|
99
|
+
/** Upper bound, since the keys come off the wire. Least recently seen entries go first. */
|
|
100
|
+
maxPeers = 10000) {
|
|
101
|
+
this.maxPeers = maxPeers;
|
|
102
|
+
}
|
|
103
|
+
set(source, module) {
|
|
104
|
+
// Re-inserting moves the entry to the end, which is what makes eviction least-recent-first.
|
|
105
|
+
this.peers.delete(source);
|
|
106
|
+
this.peers.set(source, module);
|
|
107
|
+
while (this.peers.size > this.maxPeers) {
|
|
108
|
+
const oldest = this.peers.keys().next();
|
|
109
|
+
if (oldest.done)
|
|
110
|
+
break;
|
|
111
|
+
this.peers.delete(oldest.value);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
get(source) {
|
|
115
|
+
return this.peers.get(source);
|
|
116
|
+
}
|
|
117
|
+
delete(source) {
|
|
118
|
+
return this.peers.delete(source);
|
|
119
|
+
}
|
|
120
|
+
clear() {
|
|
121
|
+
this.peers.clear();
|
|
122
|
+
}
|
|
123
|
+
get size() {
|
|
124
|
+
return this.peers.size;
|
|
125
|
+
}
|
|
126
|
+
/** Every peer currently routed through one module, which is how a bridge lists what it can reach. */
|
|
127
|
+
namesFor(module) {
|
|
128
|
+
const result = [];
|
|
129
|
+
for (const [name, carrier] of this.peers)
|
|
130
|
+
if (carrier === module)
|
|
131
|
+
result.push(name);
|
|
132
|
+
return result;
|
|
133
|
+
}
|
|
134
|
+
names() {
|
|
135
|
+
return [...this.peers.keys()];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
export class GenericModule extends EventEmitter {
|
|
139
|
+
name;
|
|
140
|
+
destinations = [];
|
|
141
|
+
/**
|
|
142
|
+
* Shared with the other modules in this graph by usePeerRegistry(). A module built on its own
|
|
143
|
+
* gets a private one, so it still routes correctly without leaking into anyone else's.
|
|
144
|
+
*/
|
|
145
|
+
peerRegistry = new PeerRegistry();
|
|
146
|
+
readyFlag = false;
|
|
147
|
+
seq = 0;
|
|
148
|
+
constructor(name, sources) {
|
|
149
|
+
super();
|
|
150
|
+
this.name = name;
|
|
151
|
+
if (!name)
|
|
152
|
+
this.name = uuidv4();
|
|
153
|
+
if (sources) {
|
|
154
|
+
sources.forEach((src) => {
|
|
155
|
+
src.pipe(this);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Waits for this module to come up, and gives up rather than waiting forever.
|
|
161
|
+
*
|
|
162
|
+
* The loop used to have no way out: a module that never became ready - one that failed to
|
|
163
|
+
* start, or was closed while something still awaited it - spun on a 10 ms timer for the life of
|
|
164
|
+
* the process, which is also long enough to keep the process alive with nothing left to do.
|
|
165
|
+
* Returning false says what happened; the overrides in RpcClient and RpcServer throw with the
|
|
166
|
+
* startup error instead, which is more than a bare module knows.
|
|
167
|
+
*/
|
|
168
|
+
async ready(timeout = 30000) {
|
|
169
|
+
const deadline = Date.now() + timeout;
|
|
170
|
+
while (!this.readyFlag) {
|
|
171
|
+
if (Date.now() > deadline)
|
|
172
|
+
return false;
|
|
173
|
+
await new Promise((res) => setTimeout(res, 10));
|
|
174
|
+
}
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
async open() { }
|
|
178
|
+
async close() { }
|
|
179
|
+
/**
|
|
180
|
+
* Build the header a frame will carry. Separate from framing so a transport that signs can
|
|
181
|
+
* see the exact field values before they are serialised, and add its signature to them.
|
|
182
|
+
*/
|
|
183
|
+
buildHeader(source, target, extra) {
|
|
184
|
+
return { source, target, time: Date.now(), seq: this.seq++, ...extra };
|
|
185
|
+
}
|
|
186
|
+
prependHeader(source, target, message) {
|
|
187
|
+
return this.frameMessage(this.buildHeader(source, target), message);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Throws when the header will not fit the frame, rather than emitting one no receiver can read.
|
|
191
|
+
* The sender is the only party that can do anything about an over-long peer name, and it learns
|
|
192
|
+
* nothing from a frame that leaves correctly and is discarded at the far end.
|
|
193
|
+
*/
|
|
194
|
+
frameMessage(header, message) {
|
|
195
|
+
const headerText = JSON.stringify(header) + HEADER_DELIMITER;
|
|
196
|
+
const headerBuffer = stringToUint8Array(headerText);
|
|
197
|
+
if (headerBuffer.length > MAX_HEADER_LENGTH)
|
|
198
|
+
throw new Error(`message header is ${headerBuffer.length} bytes, over the ${MAX_HEADER_LENGTH} byte limit ` +
|
|
199
|
+
`(source '${header.source}', target '${header.target}') - shorten the peer names`);
|
|
200
|
+
if (typeof message === 'string')
|
|
201
|
+
return headerText + message;
|
|
202
|
+
const result = new Uint8Array(headerBuffer.length + message.length);
|
|
203
|
+
result.set(headerBuffer, 0);
|
|
204
|
+
result.set(message, headerBuffer.length);
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Split a frame into its header and payload. Never throws: every frame here came off the
|
|
209
|
+
* network, and one malformed frame from one peer must not take down a process serving the rest.
|
|
210
|
+
* The third element says why nothing was extracted, so a dropped frame can be diagnosed instead
|
|
211
|
+
* of merely disappearing.
|
|
212
|
+
*/
|
|
213
|
+
extractHeader(message) {
|
|
214
|
+
const isText = typeof message === 'string';
|
|
215
|
+
const end = isText
|
|
216
|
+
? findHeaderEnd((index) => message.charCodeAt(index), message.length)
|
|
217
|
+
: findHeaderEnd((index) => message[index], message.length);
|
|
218
|
+
if (end < 0)
|
|
219
|
+
return [undefined, '', 'no msgrpc header'];
|
|
220
|
+
const headerText = isText ? message.substring(0, end) : uint8ArrayToString(message.subarray(0, end));
|
|
221
|
+
let header;
|
|
222
|
+
try {
|
|
223
|
+
header = JSON.parse(headerText);
|
|
224
|
+
}
|
|
225
|
+
catch (e) {
|
|
226
|
+
return [undefined, '', `unparsable header: ${String(e)}`];
|
|
227
|
+
}
|
|
228
|
+
if (!header || typeof header !== 'object')
|
|
229
|
+
return [undefined, '', 'header is not an object'];
|
|
230
|
+
if (typeof header.target !== 'string' || !header.target)
|
|
231
|
+
return [undefined, '', 'header names no target'];
|
|
232
|
+
if (typeof header.source !== 'string' || !header.source)
|
|
233
|
+
return [undefined, '', 'header names no source'];
|
|
234
|
+
const start = end + HEADER_DELIMITER.length;
|
|
235
|
+
// Copied rather than viewed: the MQTT path hands us a view over a pooled Node Buffer, which
|
|
236
|
+
// is reused for the next packet the moment this one returns.
|
|
237
|
+
const payload = isText ? message.substring(start) : message.slice(start);
|
|
238
|
+
this.setKnownSource(header.source);
|
|
239
|
+
return [header, payload];
|
|
240
|
+
}
|
|
241
|
+
getName() {
|
|
242
|
+
return this.name;
|
|
243
|
+
}
|
|
244
|
+
targetExists(name, level) {
|
|
245
|
+
let result;
|
|
246
|
+
if (this.name === name) {
|
|
247
|
+
result = this;
|
|
248
|
+
}
|
|
249
|
+
const knownPeer = this.peerRegistry.get(name);
|
|
250
|
+
if (knownPeer)
|
|
251
|
+
result = knownPeer;
|
|
252
|
+
if (!result) {
|
|
253
|
+
this.destinations.map((dest) => {
|
|
254
|
+
if (!result && !dest.target.isTransport() && dest.target.targetExists(name, (level ? level : 0) + 1))
|
|
255
|
+
result = dest.target;
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
pipe(target) {
|
|
261
|
+
const id = uuidv4();
|
|
262
|
+
this.destinations.push({ id, target });
|
|
263
|
+
return () => {
|
|
264
|
+
this.destinations = this.destinations.filter((el) => el.id !== id);
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
268
|
+
async receive(message, source, target) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
272
|
+
async receivePayload(message, source, target) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
async send(message, source, target) {
|
|
276
|
+
await Promise.all(this.destinations.map(async (dest) => {
|
|
277
|
+
return await dest.target.receive(message, source, target);
|
|
278
|
+
}));
|
|
279
|
+
}
|
|
280
|
+
setKnownSource(source) {
|
|
281
|
+
this.peerRegistry.set(source, this);
|
|
282
|
+
}
|
|
283
|
+
/** Route peer lookups for this module through a registry shared with the rest of its graph. */
|
|
284
|
+
usePeerRegistry(registry) {
|
|
285
|
+
this.peerRegistry = registry;
|
|
286
|
+
return this;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* The authenticated identity bound to a peer name, for transports that authenticate.
|
|
290
|
+
* Undefined means this transport cannot vouch for the peer, not that the peer is untrusted.
|
|
291
|
+
*/
|
|
292
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
293
|
+
getIdentity(source) {
|
|
294
|
+
return undefined;
|
|
295
|
+
}
|
|
296
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
297
|
+
async sendPayload(payload, messageType, source, target) { }
|
|
298
|
+
isTransport() {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
export var MessageType;
|
|
303
|
+
(function (MessageType) {
|
|
304
|
+
MessageType["RequestMessage"] = "REQUEST";
|
|
305
|
+
MessageType["ResponseMessage"] = "RESPONSE";
|
|
306
|
+
MessageType["ErrorMessage"] = "ERROR";
|
|
307
|
+
MessageType["EventMessage"] = "EVENT";
|
|
308
|
+
MessageType["UnknownMessage"] = "UNKNOWN";
|
|
309
|
+
})(MessageType || (MessageType = {}));
|
|
310
|
+
export class Message {
|
|
311
|
+
type;
|
|
312
|
+
payload;
|
|
313
|
+
}
|
|
314
|
+
const makeMessage = (payload, source, target, messageType) => {
|
|
315
|
+
const result = new Message();
|
|
316
|
+
result.type = messageType ? messageType : MessageType.UnknownMessage;
|
|
317
|
+
result.payload = payload;
|
|
318
|
+
return result;
|
|
319
|
+
};
|
|
320
|
+
export class MessageModule extends GenericModule {
|
|
321
|
+
name;
|
|
322
|
+
constructor(name, sources) {
|
|
323
|
+
super(name);
|
|
324
|
+
this.name = name;
|
|
325
|
+
if (!name)
|
|
326
|
+
this.name = uuidv4();
|
|
327
|
+
if (sources) {
|
|
328
|
+
sources.forEach((src) => {
|
|
329
|
+
src.pipe(this);
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
pipe(target) {
|
|
334
|
+
const id = uuidv4();
|
|
335
|
+
this.destinations.push({ id, target });
|
|
336
|
+
return () => {
|
|
337
|
+
this.destinations = this.destinations.filter((el) => el.id !== id);
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
341
|
+
receive(message, source, target) {
|
|
342
|
+
return Promise.resolve();
|
|
343
|
+
}
|
|
344
|
+
async send(message, source, target) {
|
|
345
|
+
await Promise.all(this.destinations.map(async (dest) => {
|
|
346
|
+
return await dest.target.receive(message, source, target);
|
|
347
|
+
}));
|
|
348
|
+
}
|
|
349
|
+
async sendPayload(payload, messageType, source, target) {
|
|
350
|
+
const message = makeMessage(payload, this.name, target, messageType);
|
|
351
|
+
await this.send(message, source, target);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
//# sourceMappingURL=Core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Core.js","sourceRoot":"","sources":["../../src/RPC/Core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { RpcCallContext } from './Auth.js';
|
|
2
|
+
import type { RpcMethodSemantics } from './Messages.js';
|
|
3
|
+
/**
|
|
4
|
+
* How calls into one exposed instance may overlap.
|
|
5
|
+
*
|
|
6
|
+
* `parallel` is the default and has always been the behaviour: calls run as they arrive, which is
|
|
7
|
+
* right for stateless services and for unrelated devices behind one server. It is not right for a
|
|
8
|
+
* long-lived object holding mutable state, where `setMode('manual'); start(); setSetpoint(80)` from
|
|
9
|
+
* one caller can interleave with `stop(); setMode('automatic')` from another and leave a machine in
|
|
10
|
+
* a combination neither of them asked for.
|
|
11
|
+
*
|
|
12
|
+
* `serial` runs one call at a time per exposed instance. A function instead runs one call at a time
|
|
13
|
+
* per key it returns, which is how a server fronting many devices keeps each device's commands in
|
|
14
|
+
* order without serialising the whole server behind the slowest one.
|
|
15
|
+
*
|
|
16
|
+
* **A serial instance must not call back into itself over RPC.** The second call queues behind the
|
|
17
|
+
* first, which is waiting for it, and neither ever runs. That is why `parallel` remains the default
|
|
18
|
+
* rather than the safer-sounding option: serialising by default would deadlock re-entrant designs
|
|
19
|
+
* that work today, silently and only under load.
|
|
20
|
+
*/
|
|
21
|
+
export type RpcExecution = 'parallel' | 'serial' | ((context: RpcCallContext) => string);
|
|
22
|
+
export interface RpcMethodOptions {
|
|
23
|
+
/**
|
|
24
|
+
* What this method does to the world: `query`, `idempotent-command` or
|
|
25
|
+
* `non-repeatable-command`. Read by a caller deciding whether an uncertain answer may be
|
|
26
|
+
* retried, and by the server deciding whether to consult a durable idempotency store.
|
|
27
|
+
*/
|
|
28
|
+
semantics?: RpcMethodSemantics;
|
|
29
|
+
}
|
|
30
|
+
type RpcMethodDecorator<This, Args extends unknown[], Return> = (target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Marks a method as remotely callable, and optionally says what it does to the world.
|
|
33
|
+
*
|
|
34
|
+
* ```typescript
|
|
35
|
+
* class Plant {
|
|
36
|
+
* @rpc async readSetpoint() { ... } // marked, nothing declared
|
|
37
|
+
* @rpc({ semantics: 'idempotent-command' }) async writeSetpoint(v: number) { ... }
|
|
38
|
+
* @rpc({ semantics: 'non-repeatable-command' }) async advanceBatch() { ... }
|
|
39
|
+
* private recompute() { ... } // unmarked, so unreachable
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* Both spellings are the same decorator: bare `@rpc` where there is nothing to say, and `@rpc({…})`
|
|
44
|
+
* where there is. A standard ECMAScript decorator either way, so no experimentalDecorators is
|
|
45
|
+
* needed, and the mark is recorded per instance at construction, which is when the RPC layer needs
|
|
46
|
+
* it.
|
|
47
|
+
*/
|
|
48
|
+
export declare function rpc<This, Args extends unknown[], Return>(target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>): void;
|
|
49
|
+
export declare function rpc<This, Args extends unknown[], Return>(options: RpcMethodOptions): RpcMethodDecorator<This, Args, Return>;
|
|
50
|
+
/**
|
|
51
|
+
* Marks methods without decorators, for JavaScript callers or code that prefers not to use them.
|
|
52
|
+
* Names that are not functions on the prototype are rejected, since a typo would silently expose
|
|
53
|
+
* nothing.
|
|
54
|
+
*/
|
|
55
|
+
export declare const exposeMethods: <T>(constructor: new (...args: never[]) => T, methods: string[]) => new (...args: never[]) => T;
|
|
56
|
+
export interface DeclaredNamespace {
|
|
57
|
+
name: string;
|
|
58
|
+
version?: string;
|
|
59
|
+
execution?: RpcExecution;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Declares the name a class is exposed under, and optionally the version of its contract and how
|
|
63
|
+
* its calls may overlap.
|
|
64
|
+
*
|
|
65
|
+
* The exposure name only existed at the call site - `exposeClassInstance(instance, 'plant')` - so
|
|
66
|
+
* nothing reading the source could tell which namespace a class belongs to. Declaring it here lets
|
|
67
|
+
* the extraction CLI key a schema correctly, and lets exposeClassInstance take the name as read.
|
|
68
|
+
*
|
|
69
|
+
* ```typescript
|
|
70
|
+
* @rpcNamespace('plant', { version: '3', execution: 'serial' })
|
|
71
|
+
* class Plant { @rpc async writeSetpoint(value: number) { ... } }
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare const rpcNamespace: (name: string, options?: {
|
|
75
|
+
version?: string;
|
|
76
|
+
execution?: RpcExecution;
|
|
77
|
+
}) => <T extends abstract new (...args: never[]) => unknown>(target: T, _context: ClassDecoratorContext) => T;
|
|
78
|
+
/** The namespace an instance's class declares, walking up so a subclass inherits it. */
|
|
79
|
+
export declare const declaredNamespace: (instance: object) => DeclaredNamespace | undefined;
|
|
80
|
+
/** The marked method names for an instance, or undefined when the class marks nothing. */
|
|
81
|
+
export declare const markedMethods: (instance: object) => Set<string> | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* The semantics an instance's methods declare, walking the chain so a subclass inherits them.
|
|
84
|
+
*
|
|
85
|
+
* A subclass that redeclares wins, which is why the nearest constructor is consulted first: an
|
|
86
|
+
* override that turns a query into a command has to be able to say so.
|
|
87
|
+
*/
|
|
88
|
+
export declare const declaredSemantics: (instance: object) => Map<string, RpcMethodSemantics>;
|
|
89
|
+
export {};
|
|
90
|
+
//# sourceMappingURL=Expose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Expose.d.ts","sourceRoot":"","sources":["../../src/RPC/Expose.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAEvD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,QAAQ,GAAG,CAAC,CAAC,OAAO,EAAE,cAAc,KAAK,MAAM,CAAC,CAAA;AA4BxF,MAAM,WAAW,gBAAgB;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,kBAAkB,CAAA;CACjC;AAED,KAAK,kBAAkB,CAAC,IAAI,EAAE,IAAI,SAAS,OAAO,EAAE,EAAE,MAAM,IAAI,CAC5D,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,EAC7C,OAAO,EAAE,2BAA2B,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,KAChF,IAAI,CAAA;AAaT;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,GAAG,CAAC,IAAI,EAAE,IAAI,SAAS,OAAO,EAAE,EAAE,MAAM,EACpD,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,EAC7C,OAAO,EAAE,2BAA2B,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,GAClF,IAAI,CAAA;AACP,wBAAgB,GAAG,CAAC,IAAI,EAAE,IAAI,SAAS,OAAO,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;AAY5H;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,eAAe,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,WAAW,MAAM,EAAE,mBAAhC,KAAK,EAAE,KAAK,CAOvE,CAAA;AAKD,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,YAAY,CAAA;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,SACd,MAAM,YAAW;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,YAAY,CAAA;CAAE,MACrE,CAAC,SAAS,QAAQ,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,UAAU,CAAC,YAAY,qBAAqB,MAGhG,CAAA;AAEL,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,aAAc,MAAM,kCAMjD,CAAA;AAED,0FAA0F;AAC1F,eAAO,MAAM,aAAa,aAAc,MAAM,KAAG,GAAG,CAAC,MAAM,CAAC,GAAG,SAO9D,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,aAAc,MAAM,KAAG,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAMlF,CAAA"}
|