@roj-ai/transport 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/client-connection.d.ts +48 -0
- package/dist/client/client-connection.d.ts.map +1 -0
- package/dist/client/client-connection.js +160 -0
- package/dist/client/index.d.ts +10 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +7 -0
- package/dist/core/connection.d.ts +59 -0
- package/dist/core/connection.d.ts.map +1 -0
- package/dist/core/connection.js +165 -0
- package/dist/core/index.d.ts +16 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +13 -0
- package/dist/core/protocol.d.ts +206 -0
- package/dist/core/protocol.d.ts.map +1 -0
- package/dist/core/protocol.js +93 -0
- package/dist/core/result.d.ts +26 -0
- package/dist/core/result.d.ts.map +1 -0
- package/dist/core/result.js +20 -0
- package/dist/core/router.d.ts +79 -0
- package/dist/core/router.d.ts.map +1 -0
- package/dist/core/router.js +119 -0
- package/dist/core/types.d.ts +44 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +14 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/platform/browser.d.ts +14 -0
- package/dist/platform/browser.d.ts.map +1 -0
- package/dist/platform/browser.js +65 -0
- package/dist/platform/bun.d.ts +69 -0
- package/dist/platform/bun.d.ts.map +1 -0
- package/dist/platform/bun.js +152 -0
- package/dist/platform/types.d.ts +83 -0
- package/dist/platform/types.d.ts.map +1 -0
- package/dist/platform/types.js +14 -0
- package/dist/server/connection-manager.d.ts +106 -0
- package/dist/server/connection-manager.d.ts.map +1 -0
- package/dist/server/connection-manager.js +234 -0
- package/dist/server/index.d.ts +12 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +8 -0
- package/dist/server/server-connection.d.ts +50 -0
- package/dist/server/server-connection.d.ts.map +1 -0
- package/dist/server/server-connection.js +84 -0
- package/package.json +52 -0
- package/src/__tests__/integration.test.ts +443 -0
- package/src/client/client-connection.ts +207 -0
- package/src/client/index.ts +24 -0
- package/src/core/connection.ts +203 -0
- package/src/core/index.ts +52 -0
- package/src/core/protocol.test.ts +235 -0
- package/src/core/protocol.ts +348 -0
- package/src/core/result.ts +35 -0
- package/src/core/router.test.ts +248 -0
- package/src/core/router.ts +186 -0
- package/src/core/types.ts +85 -0
- package/src/index.ts +80 -0
- package/src/platform/browser.ts +79 -0
- package/src/platform/bun.ts +220 -0
- package/src/platform/types.ts +102 -0
- package/src/server/connection-manager.ts +298 -0
- package/src/server/index.ts +26 -0
- package/src/server/server-connection.ts +122 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protocol Definition API
|
|
3
|
+
*
|
|
4
|
+
* Provides a type-safe way to define RPC-like protocols for WebSocket communication.
|
|
5
|
+
* Inspired by tRPC but designed for bidirectional WebSocket protocols.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import type { Result } from './result.js';
|
|
9
|
+
/**
|
|
10
|
+
* Definition for a request-response method.
|
|
11
|
+
*/
|
|
12
|
+
export interface MethodDef<TInput extends z.ZodTypeAny = z.ZodTypeAny, TOutput extends z.ZodTypeAny = z.ZodTypeAny, TError extends z.ZodTypeAny = z.ZodTypeAny> {
|
|
13
|
+
_type: 'method';
|
|
14
|
+
input: TInput;
|
|
15
|
+
output: TOutput;
|
|
16
|
+
error: TError;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Definition for a fire-and-forget notification.
|
|
20
|
+
*/
|
|
21
|
+
export interface NotificationDef<TInput extends z.ZodTypeAny = z.ZodTypeAny> {
|
|
22
|
+
_type: 'notification';
|
|
23
|
+
input: TInput;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* A single endpoint definition (method or notification).
|
|
27
|
+
*/
|
|
28
|
+
export type EndpointDef = MethodDef | NotificationDef;
|
|
29
|
+
/**
|
|
30
|
+
* Protocol definition - a collection of named endpoints.
|
|
31
|
+
*/
|
|
32
|
+
export interface ProtocolDef {
|
|
33
|
+
[key: string]: EndpointDef;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Extract input type from an endpoint definition.
|
|
37
|
+
*/
|
|
38
|
+
export type InferInput<T extends EndpointDef> = T extends MethodDef<infer I, infer _O, infer _E> ? z.infer<I> : T extends NotificationDef<infer I> ? z.infer<I> : never;
|
|
39
|
+
/**
|
|
40
|
+
* Extract output type from a method definition.
|
|
41
|
+
*/
|
|
42
|
+
export type InferOutput<T extends MethodDef> = T extends MethodDef<infer _I, infer O, infer _E> ? z.infer<O> : never;
|
|
43
|
+
/**
|
|
44
|
+
* Extract error type from a method definition.
|
|
45
|
+
*/
|
|
46
|
+
export type InferError<T extends MethodDef> = T extends MethodDef<infer _I, infer _O, infer E> ? z.infer<E> : never;
|
|
47
|
+
/**
|
|
48
|
+
* Check if endpoint is a method.
|
|
49
|
+
*/
|
|
50
|
+
export type IsMethod<T extends EndpointDef> = T extends MethodDef ? true : false;
|
|
51
|
+
/**
|
|
52
|
+
* Check if endpoint is a notification.
|
|
53
|
+
*/
|
|
54
|
+
export type IsNotification<T extends EndpointDef> = T extends NotificationDef ? true : false;
|
|
55
|
+
/**
|
|
56
|
+
* Handler context passed to method/notification handlers.
|
|
57
|
+
*/
|
|
58
|
+
export interface HandlerContext {
|
|
59
|
+
/** Connection identifier */
|
|
60
|
+
connectionId: string;
|
|
61
|
+
/** Additional context data (platform-specific) */
|
|
62
|
+
[key: string]: unknown;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Handler for a method endpoint.
|
|
66
|
+
*/
|
|
67
|
+
export type MethodHandler<T extends MethodDef> = (input: InferInput<T>, ctx: HandlerContext) => Promise<Result<InferOutput<T>, InferError<T>>>;
|
|
68
|
+
/**
|
|
69
|
+
* Handler for a notification endpoint.
|
|
70
|
+
*/
|
|
71
|
+
export type NotificationHandler<T extends NotificationDef> = (input: InferInput<T>, ctx: HandlerContext) => Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Handler for an endpoint (method or notification).
|
|
74
|
+
*/
|
|
75
|
+
export type EndpointHandler<T extends EndpointDef> = T extends MethodDef ? MethodHandler<T> : T extends NotificationDef ? NotificationHandler<T> : never;
|
|
76
|
+
/**
|
|
77
|
+
* Handlers object for a protocol.
|
|
78
|
+
*/
|
|
79
|
+
export type ProtocolHandlers<T extends ProtocolDef> = {
|
|
80
|
+
[K in keyof T]: EndpointHandler<T[K]>;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Caller function for a method endpoint.
|
|
84
|
+
*/
|
|
85
|
+
export type MethodCaller<T extends MethodDef> = (input: InferInput<T>) => Promise<Result<InferOutput<T>, InferError<T>>>;
|
|
86
|
+
/**
|
|
87
|
+
* Notifier function for a notification endpoint.
|
|
88
|
+
*/
|
|
89
|
+
export type NotificationNotifier<T extends NotificationDef> = (input: InferInput<T>) => void;
|
|
90
|
+
/**
|
|
91
|
+
* Caller object for methods in a protocol.
|
|
92
|
+
* Only includes method endpoints.
|
|
93
|
+
*/
|
|
94
|
+
export type ProtocolCaller<T extends ProtocolDef> = {
|
|
95
|
+
[K in keyof T as T[K] extends MethodDef ? K : never]: T[K] extends MethodDef ? MethodCaller<T[K]> : never;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Notifier object for notifications in a protocol.
|
|
99
|
+
* Only includes notification endpoints.
|
|
100
|
+
*/
|
|
101
|
+
export type ProtocolNotifier<T extends ProtocolDef> = {
|
|
102
|
+
[K in keyof T as T[K] extends NotificationDef ? K : never]: T[K] extends NotificationDef ? NotificationNotifier<T[K]> : never;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Options for method definition.
|
|
106
|
+
*/
|
|
107
|
+
export interface MethodOptions<TInput extends z.ZodTypeAny, TOutput extends z.ZodTypeAny, TError extends z.ZodTypeAny> {
|
|
108
|
+
/** Input schema (what the caller sends) */
|
|
109
|
+
input: TInput;
|
|
110
|
+
/** Output schema (what the handler returns on success) */
|
|
111
|
+
output: TOutput;
|
|
112
|
+
/** Error schema (what the handler returns on failure) */
|
|
113
|
+
error: TError;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Define a request-response method endpoint.
|
|
117
|
+
*/
|
|
118
|
+
export declare function method<TInput extends z.ZodTypeAny, TOutput extends z.ZodTypeAny, TError extends z.ZodTypeAny>(options: MethodOptions<TInput, TOutput, TError>): MethodDef<TInput, TOutput, TError>;
|
|
119
|
+
/**
|
|
120
|
+
* Options for notification definition.
|
|
121
|
+
*/
|
|
122
|
+
export interface NotificationOptions<TInput extends z.ZodTypeAny> {
|
|
123
|
+
/** Input schema (what is sent) */
|
|
124
|
+
input: TInput;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Define a fire-and-forget notification endpoint.
|
|
128
|
+
*/
|
|
129
|
+
export declare function notification<TInput extends z.ZodTypeAny>(options: NotificationOptions<TInput>): NotificationDef<TInput>;
|
|
130
|
+
/**
|
|
131
|
+
* Safe parse result type (matches Zod's structure).
|
|
132
|
+
*/
|
|
133
|
+
export type SafeParseResult<T> = {
|
|
134
|
+
success: true;
|
|
135
|
+
data: T;
|
|
136
|
+
} | {
|
|
137
|
+
success: false;
|
|
138
|
+
error: {
|
|
139
|
+
message: string;
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Protocol object with definition and metadata.
|
|
144
|
+
*/
|
|
145
|
+
export interface Protocol<T extends ProtocolDef> {
|
|
146
|
+
/** The protocol definition */
|
|
147
|
+
_def: T;
|
|
148
|
+
/** Get endpoint definition by name */
|
|
149
|
+
getEndpoint<K extends keyof T>(name: K): T[K];
|
|
150
|
+
/** Check if endpoint is a method */
|
|
151
|
+
isMethod(name: keyof T): boolean;
|
|
152
|
+
/** Check if endpoint is a notification */
|
|
153
|
+
isNotification(name: keyof T): boolean;
|
|
154
|
+
/** Get all method names */
|
|
155
|
+
getMethodNames(): (keyof T)[];
|
|
156
|
+
/** Get all notification names */
|
|
157
|
+
getNotificationNames(): (keyof T)[];
|
|
158
|
+
/** Validate input for an endpoint */
|
|
159
|
+
validateInput<K extends keyof T>(name: K, input: unknown): SafeParseResult<InferInput<T[K]>>;
|
|
160
|
+
/** Validate output for a method endpoint */
|
|
161
|
+
validateOutput<K extends keyof T>(name: K, output: unknown): SafeParseResult<unknown>;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Define a protocol with typed endpoints.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```typescript
|
|
168
|
+
* const clientProtocol = defineProtocol({
|
|
169
|
+
* subscribe: method({
|
|
170
|
+
* input: z.object({ sessionId: z.string() }),
|
|
171
|
+
* output: z.void(),
|
|
172
|
+
* error: z.object({ code: z.literal('SESSION_NOT_FOUND') }),
|
|
173
|
+
* }),
|
|
174
|
+
*
|
|
175
|
+
* userMessage: method({
|
|
176
|
+
* input: z.object({ sessionId: z.string(), content: z.string() }),
|
|
177
|
+
* output: z.object({ messageId: z.string() }),
|
|
178
|
+
* error: z.object({ code: z.literal('AGENT_BUSY') }),
|
|
179
|
+
* }),
|
|
180
|
+
* });
|
|
181
|
+
*
|
|
182
|
+
* const serverProtocol = defineProtocol({
|
|
183
|
+
* agentMessage: notification({
|
|
184
|
+
* input: z.object({ sessionId: z.string(), content: z.string() }),
|
|
185
|
+
* }),
|
|
186
|
+
* });
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
export declare function defineProtocol<T extends ProtocolDef>(def: T): Protocol<T>;
|
|
190
|
+
/**
|
|
191
|
+
* Extract the protocol definition type from a Protocol.
|
|
192
|
+
*/
|
|
193
|
+
export type ExtractProtocolDef<T> = T extends Protocol<infer P> ? P : never;
|
|
194
|
+
/**
|
|
195
|
+
* Create a typed handlers object type for a protocol.
|
|
196
|
+
*/
|
|
197
|
+
export type HandlersFor<T extends Protocol<ProtocolDef>> = ProtocolHandlers<ExtractProtocolDef<T>>;
|
|
198
|
+
/**
|
|
199
|
+
* Create a typed caller object type for a protocol.
|
|
200
|
+
*/
|
|
201
|
+
export type CallerFor<T extends Protocol<ProtocolDef>> = ProtocolCaller<ExtractProtocolDef<T>>;
|
|
202
|
+
/**
|
|
203
|
+
* Create a typed notifier object type for a protocol.
|
|
204
|
+
*/
|
|
205
|
+
export type NotifierFor<T extends Protocol<ProtocolDef>> = ProtocolNotifier<ExtractProtocolDef<T>>;
|
|
206
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/core/protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protocol Definition API
|
|
3
|
+
*
|
|
4
|
+
* Provides a type-safe way to define RPC-like protocols for WebSocket communication.
|
|
5
|
+
* Inspired by tRPC but designed for bidirectional WebSocket protocols.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Define a request-response method endpoint.
|
|
9
|
+
*/
|
|
10
|
+
export function method(options) {
|
|
11
|
+
return {
|
|
12
|
+
_type: 'method',
|
|
13
|
+
input: options.input,
|
|
14
|
+
output: options.output,
|
|
15
|
+
error: options.error,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Define a fire-and-forget notification endpoint.
|
|
20
|
+
*/
|
|
21
|
+
export function notification(options) {
|
|
22
|
+
return {
|
|
23
|
+
_type: 'notification',
|
|
24
|
+
input: options.input,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Define a protocol with typed endpoints.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* const clientProtocol = defineProtocol({
|
|
33
|
+
* subscribe: method({
|
|
34
|
+
* input: z.object({ sessionId: z.string() }),
|
|
35
|
+
* output: z.void(),
|
|
36
|
+
* error: z.object({ code: z.literal('SESSION_NOT_FOUND') }),
|
|
37
|
+
* }),
|
|
38
|
+
*
|
|
39
|
+
* userMessage: method({
|
|
40
|
+
* input: z.object({ sessionId: z.string(), content: z.string() }),
|
|
41
|
+
* output: z.object({ messageId: z.string() }),
|
|
42
|
+
* error: z.object({ code: z.literal('AGENT_BUSY') }),
|
|
43
|
+
* }),
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* const serverProtocol = defineProtocol({
|
|
47
|
+
* agentMessage: notification({
|
|
48
|
+
* input: z.object({ sessionId: z.string(), content: z.string() }),
|
|
49
|
+
* }),
|
|
50
|
+
* });
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export function defineProtocol(def) {
|
|
54
|
+
return {
|
|
55
|
+
_def: def,
|
|
56
|
+
getEndpoint(name) {
|
|
57
|
+
return def[name];
|
|
58
|
+
},
|
|
59
|
+
isMethod(name) {
|
|
60
|
+
const endpoint = def[name];
|
|
61
|
+
return endpoint?._type === 'method';
|
|
62
|
+
},
|
|
63
|
+
isNotification(name) {
|
|
64
|
+
const endpoint = def[name];
|
|
65
|
+
return endpoint?._type === 'notification';
|
|
66
|
+
},
|
|
67
|
+
getMethodNames() {
|
|
68
|
+
return Object.keys(def).filter((key) => def[key]._type === 'method');
|
|
69
|
+
},
|
|
70
|
+
getNotificationNames() {
|
|
71
|
+
return Object.keys(def).filter((key) => def[key]._type === 'notification');
|
|
72
|
+
},
|
|
73
|
+
validateInput(name, input) {
|
|
74
|
+
const endpoint = def[name];
|
|
75
|
+
const result = endpoint.input.safeParse(input);
|
|
76
|
+
if (result.success) {
|
|
77
|
+
return { success: true, data: result.data };
|
|
78
|
+
}
|
|
79
|
+
return { success: false, error: { message: result.error.message } };
|
|
80
|
+
},
|
|
81
|
+
validateOutput(name, output) {
|
|
82
|
+
const endpoint = def[name];
|
|
83
|
+
if (endpoint._type !== 'method') {
|
|
84
|
+
throw new Error(`Endpoint ${String(name)} is not a method`);
|
|
85
|
+
}
|
|
86
|
+
const result = endpoint.output.safeParse(output);
|
|
87
|
+
if (result.success) {
|
|
88
|
+
return { success: true, data: result.data };
|
|
89
|
+
}
|
|
90
|
+
return { success: false, error: { message: result.error.message } };
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result type for explicit error handling without exceptions.
|
|
3
|
+
* Inspired by Rust/Go approach.
|
|
4
|
+
*/
|
|
5
|
+
export type Result<T, E = Error> = {
|
|
6
|
+
ok: true;
|
|
7
|
+
value: T;
|
|
8
|
+
} | {
|
|
9
|
+
ok: false;
|
|
10
|
+
error: E;
|
|
11
|
+
};
|
|
12
|
+
export declare const Ok: <T>(value: T) => Result<T, never>;
|
|
13
|
+
export declare const Err: <E>(error: E) => Result<never, E>;
|
|
14
|
+
export declare const isOk: <T, E>(result: Result<T, E>) => result is {
|
|
15
|
+
ok: true;
|
|
16
|
+
value: T;
|
|
17
|
+
};
|
|
18
|
+
export declare const isErr: <T, E>(result: Result<T, E>) => result is {
|
|
19
|
+
ok: false;
|
|
20
|
+
error: E;
|
|
21
|
+
};
|
|
22
|
+
export declare const mapResult: <T, U, E>(result: Result<T, E>, fn: (value: T) => U) => Result<U, E>;
|
|
23
|
+
export declare const flatMapResult: <T, U, E>(result: Result<T, E>, fn: (value: T) => Result<U, E>) => Result<U, E>;
|
|
24
|
+
export declare const unwrapOr: <T, E>(result: Result<T, E>, defaultValue: T) => T;
|
|
25
|
+
export declare const unwrapOrThrow: <T, E>(result: Result<T, E>) => T;
|
|
26
|
+
//# sourceMappingURL=result.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/core/result.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,IAC5B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GACtB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAA;AAG1B,eAAO,MAAM,EAAE,GAAI,CAAC,EAAE,OAAO,CAAC,KAAG,MAAM,CAAC,CAAC,EAAE,KAAK,CAA0B,CAAA;AAC1E,eAAO,MAAM,GAAG,GAAI,CAAC,EAAE,OAAO,CAAC,KAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAA2B,CAAA;AAG5E,eAAO,MAAM,IAAI,GAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,MAAM,IAAI;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAe,CAAA;AAC/F,eAAO,MAAM,KAAK,GAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,MAAM,IAAI;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAgB,CAAA;AAGlG,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAChC,QAAQ,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EACpB,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,KACjB,MAAM,CAAC,CAAC,EAAE,CAAC,CAA8C,CAAA;AAE5D,eAAO,MAAM,aAAa,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EACpC,QAAQ,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EACpB,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KAC5B,MAAM,CAAC,CAAC,EAAE,CAAC,CAA0C,CAAA;AAGxD,eAAO,MAAM,QAAQ,GAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,CAAC,KAAG,CAA4C,CAAA;AAEnH,eAAO,MAAM,aAAa,GAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,CAG1D,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result type for explicit error handling without exceptions.
|
|
3
|
+
* Inspired by Rust/Go approach.
|
|
4
|
+
*/
|
|
5
|
+
// Constructors
|
|
6
|
+
export const Ok = (value) => ({ ok: true, value });
|
|
7
|
+
export const Err = (error) => ({ ok: false, error });
|
|
8
|
+
// Type guards
|
|
9
|
+
export const isOk = (result) => result.ok;
|
|
10
|
+
export const isErr = (result) => !result.ok;
|
|
11
|
+
// Helper functions
|
|
12
|
+
export const mapResult = (result, fn) => result.ok ? Ok(fn(result.value)) : result;
|
|
13
|
+
export const flatMapResult = (result, fn) => result.ok ? fn(result.value) : result;
|
|
14
|
+
// Unwrap functions
|
|
15
|
+
export const unwrapOr = (result, defaultValue) => result.ok ? result.value : defaultValue;
|
|
16
|
+
export const unwrapOrThrow = (result) => {
|
|
17
|
+
if (result.ok)
|
|
18
|
+
return result.value;
|
|
19
|
+
throw result.error;
|
|
20
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message Router
|
|
3
|
+
*
|
|
4
|
+
* Handles notification dispatching - no request-response, no correlation.
|
|
5
|
+
* Simplified for notification-only protocols.
|
|
6
|
+
*/
|
|
7
|
+
import type { HandlerContext, InferInput, Protocol, ProtocolDef, ProtocolHandlers } from './protocol.js';
|
|
8
|
+
/**
|
|
9
|
+
* Message send function type.
|
|
10
|
+
*/
|
|
11
|
+
export type MessageSender = (message: string) => boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Router error types for debugging protocol issues.
|
|
14
|
+
*/
|
|
15
|
+
export type RouterErrorType = 'parse' | 'unknown_type' | 'validation' | 'handler';
|
|
16
|
+
/**
|
|
17
|
+
* Router error handler callback.
|
|
18
|
+
*/
|
|
19
|
+
export type RouterErrorHandler = (error: {
|
|
20
|
+
type: RouterErrorType;
|
|
21
|
+
message: string;
|
|
22
|
+
raw?: string;
|
|
23
|
+
details?: unknown;
|
|
24
|
+
}) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Message router for handling incoming notifications and sending outbound notifications.
|
|
27
|
+
*
|
|
28
|
+
* Simplified notification-only router:
|
|
29
|
+
* - No request-response correlation
|
|
30
|
+
* - No pending requests tracking
|
|
31
|
+
* - Fire-and-forget notifications only
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Raw message listener — receives every parsed message before handler dispatch.
|
|
35
|
+
*/
|
|
36
|
+
export type RawMessageListener = (type: string, payload: unknown) => void;
|
|
37
|
+
export declare class MessageRouter<TReceive extends ProtocolDef, TSend extends ProtocolDef> {
|
|
38
|
+
private readonly receiveProtocol;
|
|
39
|
+
private readonly sendProtocol;
|
|
40
|
+
private handlers;
|
|
41
|
+
private sender;
|
|
42
|
+
private errorHandler;
|
|
43
|
+
private rawMessageListener;
|
|
44
|
+
constructor(receiveProtocol: Protocol<TReceive> | null, sendProtocol: Protocol<TSend> | null);
|
|
45
|
+
/**
|
|
46
|
+
* Set the message sender function.
|
|
47
|
+
*/
|
|
48
|
+
setSender(sender: MessageSender): void;
|
|
49
|
+
/**
|
|
50
|
+
* Set handlers for incoming notifications.
|
|
51
|
+
*/
|
|
52
|
+
setHandlers(handlers: Partial<ProtocolHandlers<TReceive>>): void;
|
|
53
|
+
/**
|
|
54
|
+
* Set error handler for debugging protocol issues.
|
|
55
|
+
*/
|
|
56
|
+
setErrorHandler(handler: RouterErrorHandler): void;
|
|
57
|
+
/**
|
|
58
|
+
* Set a raw message listener that receives every incoming message.
|
|
59
|
+
* When set, bypasses per-type handler dispatch — the listener receives (type, payload) directly.
|
|
60
|
+
*/
|
|
61
|
+
setRawMessageListener(listener: RawMessageListener): void;
|
|
62
|
+
/**
|
|
63
|
+
* Handle an incoming raw message (notification).
|
|
64
|
+
*/
|
|
65
|
+
handleMessage(raw: string, ctx: HandlerContext): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Send a notification (fire-and-forget).
|
|
68
|
+
*/
|
|
69
|
+
notify<K extends keyof TSend>(name: K, input: TSend[K] extends {
|
|
70
|
+
input: infer I;
|
|
71
|
+
} ? (I extends {
|
|
72
|
+
_type: string;
|
|
73
|
+
} ? never : InferInput<TSend[K]>) : never): boolean;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Create a message router for the given protocols.
|
|
77
|
+
*/
|
|
78
|
+
export declare function createRouter<TReceive extends ProtocolDef, TSend extends ProtocolDef>(receiveProtocol: Protocol<TReceive> | null, sendProtocol: Protocol<TSend> | null): MessageRouter<TReceive, TSend>;
|
|
79
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/core/router.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAOxG;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAA;AAExD;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,cAAc,GAAG,YAAY,GAAG,SAAS,CAAA;AAEjF;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE;IACxC,IAAI,EAAE,eAAe,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,OAAO,CAAA;CACjB,KAAK,IAAI,CAAA;AAMV;;;;;;;GAOG;AACH;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;AAEzE,qBAAa,aAAa,CAAC,QAAQ,SAAS,WAAW,EAAE,KAAK,SAAS,WAAW;IACjF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA2B;IAC3D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAwB;IAErD,OAAO,CAAC,QAAQ,CAA0C;IAC1D,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,kBAAkB,CAAkC;gBAG3D,eAAe,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,IAAI,EAC1C,YAAY,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI;IAMrC;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAItC;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI;IAIhE;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAIlD;;;OAGG;IACH,qBAAqB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAIzD;;OAEG;IACG,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAoDpE;;OAEG;IACH,MAAM,CAAC,CAAC,SAAS,MAAM,KAAK,EAC3B,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS;QAAE,KAAK,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,CAAC,CAAC,SAAS;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,GAC/G,OAAO;CAaV;AAMD;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,SAAS,WAAW,EAAE,KAAK,SAAS,WAAW,EACnF,eAAe,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,IAAI,EAC1C,YAAY,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI,GAClC,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,CAEhC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message Router
|
|
3
|
+
*
|
|
4
|
+
* Handles notification dispatching - no request-response, no correlation.
|
|
5
|
+
* Simplified for notification-only protocols.
|
|
6
|
+
*/
|
|
7
|
+
export class MessageRouter {
|
|
8
|
+
receiveProtocol;
|
|
9
|
+
sendProtocol;
|
|
10
|
+
handlers = {};
|
|
11
|
+
sender = null;
|
|
12
|
+
errorHandler = null;
|
|
13
|
+
rawMessageListener = null;
|
|
14
|
+
constructor(receiveProtocol, sendProtocol) {
|
|
15
|
+
this.receiveProtocol = receiveProtocol;
|
|
16
|
+
this.sendProtocol = sendProtocol;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Set the message sender function.
|
|
20
|
+
*/
|
|
21
|
+
setSender(sender) {
|
|
22
|
+
this.sender = sender;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Set handlers for incoming notifications.
|
|
26
|
+
*/
|
|
27
|
+
setHandlers(handlers) {
|
|
28
|
+
this.handlers = handlers;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Set error handler for debugging protocol issues.
|
|
32
|
+
*/
|
|
33
|
+
setErrorHandler(handler) {
|
|
34
|
+
this.errorHandler = handler;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Set a raw message listener that receives every incoming message.
|
|
38
|
+
* When set, bypasses per-type handler dispatch — the listener receives (type, payload) directly.
|
|
39
|
+
*/
|
|
40
|
+
setRawMessageListener(listener) {
|
|
41
|
+
this.rawMessageListener = listener;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Handle an incoming raw message (notification).
|
|
45
|
+
*/
|
|
46
|
+
async handleMessage(raw, ctx) {
|
|
47
|
+
let parsed;
|
|
48
|
+
try {
|
|
49
|
+
parsed = JSON.parse(raw);
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
this.errorHandler?.({ type: 'parse', message: 'Invalid JSON', raw, details: e });
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const { type, payload } = parsed;
|
|
56
|
+
// Raw listener mode — forward everything without dispatch or validation
|
|
57
|
+
if (this.rawMessageListener) {
|
|
58
|
+
this.rawMessageListener(type, payload);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (this.receiveProtocol) {
|
|
62
|
+
// Validated path — protocol provided, validate input before dispatching
|
|
63
|
+
const endpoint = this.receiveProtocol._def[type];
|
|
64
|
+
if (!endpoint) {
|
|
65
|
+
this.errorHandler?.({ type: 'unknown_type', message: `Unknown message type: ${type}`, raw });
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const inputResult = this.receiveProtocol.validateInput(type, payload);
|
|
69
|
+
if (!inputResult.success) {
|
|
70
|
+
this.errorHandler?.({ type: 'validation', message: `Validation failed for ${type}`, raw, details: inputResult.error });
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const handler = this.handlers[type];
|
|
74
|
+
if (!handler)
|
|
75
|
+
return;
|
|
76
|
+
try {
|
|
77
|
+
await handler(inputResult.data, ctx);
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
this.errorHandler?.({ type: 'handler', message: `Handler error for ${type}`, raw, details: e });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
// Unvalidated path — no protocol, dispatch directly (trusted source)
|
|
85
|
+
const handler = this.handlers[type];
|
|
86
|
+
if (!handler)
|
|
87
|
+
return;
|
|
88
|
+
try {
|
|
89
|
+
await handler(payload, ctx);
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
this.errorHandler?.({ type: 'handler', message: `Handler error for ${type}`, raw, details: e });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Send a notification (fire-and-forget).
|
|
98
|
+
*/
|
|
99
|
+
notify(name, input) {
|
|
100
|
+
if (!this.sender) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
const message = {
|
|
104
|
+
type: String(name),
|
|
105
|
+
payload: input,
|
|
106
|
+
ts: Date.now(),
|
|
107
|
+
};
|
|
108
|
+
return this.sender(JSON.stringify(message));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// ============================================================================
|
|
112
|
+
// Router Builder
|
|
113
|
+
// ============================================================================
|
|
114
|
+
/**
|
|
115
|
+
* Create a message router for the given protocols.
|
|
116
|
+
*/
|
|
117
|
+
export function createRouter(receiveProtocol, sendProtocol) {
|
|
118
|
+
return new MessageRouter(receiveProtocol, sendProtocol);
|
|
119
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Transport Types
|
|
3
|
+
*
|
|
4
|
+
* Platform-agnostic types for WebSocket transport infrastructure.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Connection state machine states.
|
|
8
|
+
*/
|
|
9
|
+
export type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';
|
|
10
|
+
/**
|
|
11
|
+
* Wire message envelope for all protocol messages.
|
|
12
|
+
* Simplified: notification-only, no correlation ID.
|
|
13
|
+
*/
|
|
14
|
+
export interface WireMessage<T = unknown> {
|
|
15
|
+
/** Notification type name */
|
|
16
|
+
type: string;
|
|
17
|
+
/** Message payload */
|
|
18
|
+
payload: T;
|
|
19
|
+
/** Timestamp */
|
|
20
|
+
ts: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Transport event types.
|
|
24
|
+
*/
|
|
25
|
+
export type TransportEvent = 'connected' | 'disconnected' | 'error' | 'reconnecting' | 'reconnected' | 'state_change' | 'router_error';
|
|
26
|
+
/**
|
|
27
|
+
* Transport event listener.
|
|
28
|
+
*/
|
|
29
|
+
export type TransportEventListener = (event: TransportEvent, data?: unknown) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Reconnection strategy options.
|
|
32
|
+
*/
|
|
33
|
+
export interface ReconnectOptions {
|
|
34
|
+
/** Base delay in ms (default: 1000) */
|
|
35
|
+
baseDelayMs: number;
|
|
36
|
+
/** Maximum delay in ms (default: 30000) */
|
|
37
|
+
maxDelayMs: number;
|
|
38
|
+
/** Maximum number of attempts before giving up (default: Infinity) */
|
|
39
|
+
maxAttempts: number;
|
|
40
|
+
/** Jitter factor (0-1, default: 0.3) */
|
|
41
|
+
jitterFactor: number;
|
|
42
|
+
}
|
|
43
|
+
export declare const DEFAULT_RECONNECT_OPTIONS: ReconnectOptions;
|
|
44
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;GAEG;AACH,MAAM,MAAM,eAAe,GACxB,cAAc,GACd,YAAY,GACZ,WAAW,GACX,cAAc,CAAA;AAMjB;;;GAGG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACvC,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,sBAAsB;IACtB,OAAO,EAAE,CAAC,CAAA;IACV,gBAAgB;IAChB,EAAE,EAAE,MAAM,CAAA;CACV;AAMD;;GAEG;AACH,MAAM,MAAM,cAAc,GACvB,WAAW,GACX,cAAc,GACd,OAAO,GACP,cAAc,GACd,aAAa,GACb,cAAc,GACd,cAAc,CAAA;AAEjB;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;AAMpF;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAA;IACnB,2CAA2C;IAC3C,UAAU,EAAE,MAAM,CAAA;IAClB,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAA;IACnB,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAA;CACpB;AAMD,eAAO,MAAM,yBAAyB,EAAE,gBAKvC,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Transport Types
|
|
3
|
+
*
|
|
4
|
+
* Platform-agnostic types for WebSocket transport infrastructure.
|
|
5
|
+
*/
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Default Values
|
|
8
|
+
// ============================================================================
|
|
9
|
+
export const DEFAULT_RECONNECT_OPTIONS = {
|
|
10
|
+
baseDelayMs: 1000,
|
|
11
|
+
maxDelayMs: 30000,
|
|
12
|
+
maxAttempts: Infinity,
|
|
13
|
+
jitterFactor: 0.3,
|
|
14
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @roj-ai/transport
|
|
3
|
+
*
|
|
4
|
+
* Platform-agnostic WebSocket transport infrastructure with RPC-like protocol API.
|
|
5
|
+
*/
|
|
6
|
+
export { defineProtocol, method, notification } from './core/protocol.js';
|
|
7
|
+
export type { CallerFor, EndpointDef, EndpointHandler, ExtractProtocolDef, HandlerContext, HandlersFor, InferError, InferInput, InferOutput, IsMethod, IsNotification, MethodCaller, MethodDef, MethodHandler, MethodOptions, NotificationDef, NotificationHandler, NotificationNotifier, NotificationOptions, NotifierFor, Protocol, ProtocolCaller, ProtocolDef, ProtocolHandlers, ProtocolNotifier, } from './core/protocol.js';
|
|
8
|
+
export { Err, flatMapResult, isErr, isOk, mapResult, Ok, unwrapOr, unwrapOrThrow } from './core/result.js';
|
|
9
|
+
export type { Result } from './core/result.js';
|
|
10
|
+
export type { ConnectionState, ReconnectOptions, TransportEvent, TransportEventListener, WireMessage } from './core/types.js';
|
|
11
|
+
export { DEFAULT_RECONNECT_OPTIONS } from './core/types.js';
|
|
12
|
+
export { createRouter, MessageRouter } from './core/router.js';
|
|
13
|
+
export type { MessageSender, RawMessageListener, RouterErrorHandler, RouterErrorType } from './core/router.js';
|
|
14
|
+
export { Connection } from './core/connection.js';
|
|
15
|
+
export type { ConnectionConfig } from './core/connection.js';
|
|
16
|
+
export type { ICloseEvent, IServerWebSocket, IWebSocket, IWebSocketFactory } from './platform/types.js';
|
|
17
|
+
export { WebSocketReadyState } from './platform/types.js';
|
|
18
|
+
export { ClientConnection, createClientConnection } from './client/client-connection.js';
|
|
19
|
+
export type { ClientConnectionConfig } from './client/client-connection.js';
|
|
20
|
+
export { createServerConnection, ServerConnection } from './server/server-connection.js';
|
|
21
|
+
export type { ServerConnectionConfig, ServerHandlerContext } from './server/server-connection.js';
|
|
22
|
+
export { ConnectionManager } from './server/connection-manager.js';
|
|
23
|
+
export type { ConnectionStats } from './server/connection-manager.js';
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACzE,YAAY,EACX,SAAS,EACT,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,UAAU,EACV,UAAU,EACV,WAAW,EACX,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,SAAS,EACT,aAAa,EACb,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,WAAW,EACX,QAAQ,EACR,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,gBAAgB,GAChB,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAC1G,YAAY,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAG9C,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,cAAc,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAE7H,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAA;AAG3D,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAC9D,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAE9G,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAM5D,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAEvG,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAMzD,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACxF,YAAY,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AAM3E,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AACxF,YAAY,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AAEjG,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAClE,YAAY,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA"}
|