@generacy-ai/cluster-relay 0.0.0-preview-20260314042105

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.
@@ -0,0 +1,252 @@
1
+ import { z } from 'zod';
2
+ export interface ApiRequestMessage {
3
+ type: 'api_request';
4
+ id: string;
5
+ method: string;
6
+ path: string;
7
+ headers?: Record<string, string>;
8
+ body?: unknown;
9
+ }
10
+ export interface ApiResponseMessage {
11
+ type: 'api_response';
12
+ id: string;
13
+ status: number;
14
+ headers?: Record<string, string>;
15
+ body?: unknown;
16
+ }
17
+ export interface EventMessage {
18
+ type: 'event';
19
+ channel: string;
20
+ event: unknown;
21
+ }
22
+ export interface ConversationMessage {
23
+ type: 'conversation';
24
+ conversationId: string;
25
+ data: unknown;
26
+ }
27
+ export interface HeartbeatMessage {
28
+ type: 'heartbeat';
29
+ }
30
+ export interface HandshakeMessage {
31
+ type: 'handshake';
32
+ metadata: ClusterMetadata;
33
+ }
34
+ export interface ErrorMessage {
35
+ type: 'error';
36
+ code: string;
37
+ message: string;
38
+ }
39
+ export type RelayMessage = ApiRequestMessage | ApiResponseMessage | EventMessage | ConversationMessage | HeartbeatMessage | HandshakeMessage | ErrorMessage;
40
+ export interface GitRemote {
41
+ name: string;
42
+ url: string;
43
+ }
44
+ export interface ClusterMetadata {
45
+ workerCount: number;
46
+ activeWorkflows: number;
47
+ channel: 'preview' | 'stable';
48
+ orchestratorVersion: string;
49
+ gitRemotes: GitRemote[];
50
+ uptime: number;
51
+ }
52
+ declare const GitRemoteSchema: z.ZodObject<{
53
+ name: z.ZodString;
54
+ url: z.ZodString;
55
+ }, "strip", z.ZodTypeAny, {
56
+ name: string;
57
+ url: string;
58
+ }, {
59
+ name: string;
60
+ url: string;
61
+ }>;
62
+ declare const ClusterMetadataSchema: z.ZodObject<{
63
+ workerCount: z.ZodNumber;
64
+ activeWorkflows: z.ZodNumber;
65
+ channel: z.ZodEnum<["preview", "stable"]>;
66
+ orchestratorVersion: z.ZodString;
67
+ gitRemotes: z.ZodArray<z.ZodObject<{
68
+ name: z.ZodString;
69
+ url: z.ZodString;
70
+ }, "strip", z.ZodTypeAny, {
71
+ name: string;
72
+ url: string;
73
+ }, {
74
+ name: string;
75
+ url: string;
76
+ }>, "many">;
77
+ uptime: z.ZodNumber;
78
+ }, "strip", z.ZodTypeAny, {
79
+ workerCount: number;
80
+ activeWorkflows: number;
81
+ channel: "preview" | "stable";
82
+ orchestratorVersion: string;
83
+ gitRemotes: {
84
+ name: string;
85
+ url: string;
86
+ }[];
87
+ uptime: number;
88
+ }, {
89
+ workerCount: number;
90
+ activeWorkflows: number;
91
+ channel: "preview" | "stable";
92
+ orchestratorVersion: string;
93
+ gitRemotes: {
94
+ name: string;
95
+ url: string;
96
+ }[];
97
+ uptime: number;
98
+ }>;
99
+ export declare const RelayMessageSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
100
+ type: z.ZodLiteral<"api_request">;
101
+ id: z.ZodString;
102
+ method: z.ZodString;
103
+ path: z.ZodString;
104
+ headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
105
+ body: z.ZodOptional<z.ZodUnknown>;
106
+ }, "strip", z.ZodTypeAny, {
107
+ path: string;
108
+ type: "api_request";
109
+ id: string;
110
+ method: string;
111
+ headers?: Record<string, string> | undefined;
112
+ body?: unknown;
113
+ }, {
114
+ path: string;
115
+ type: "api_request";
116
+ id: string;
117
+ method: string;
118
+ headers?: Record<string, string> | undefined;
119
+ body?: unknown;
120
+ }>, z.ZodObject<{
121
+ type: z.ZodLiteral<"api_response">;
122
+ id: z.ZodString;
123
+ status: z.ZodNumber;
124
+ headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
125
+ body: z.ZodOptional<z.ZodUnknown>;
126
+ }, "strip", z.ZodTypeAny, {
127
+ type: "api_response";
128
+ status: number;
129
+ id: string;
130
+ headers?: Record<string, string> | undefined;
131
+ body?: unknown;
132
+ }, {
133
+ type: "api_response";
134
+ status: number;
135
+ id: string;
136
+ headers?: Record<string, string> | undefined;
137
+ body?: unknown;
138
+ }>, z.ZodObject<{
139
+ type: z.ZodLiteral<"event">;
140
+ channel: z.ZodString;
141
+ event: z.ZodUnknown;
142
+ }, "strip", z.ZodTypeAny, {
143
+ type: "event";
144
+ channel: string;
145
+ event?: unknown;
146
+ }, {
147
+ type: "event";
148
+ channel: string;
149
+ event?: unknown;
150
+ }>, z.ZodObject<{
151
+ type: z.ZodLiteral<"conversation">;
152
+ conversationId: z.ZodString;
153
+ data: z.ZodUnknown;
154
+ }, "strip", z.ZodTypeAny, {
155
+ type: "conversation";
156
+ conversationId: string;
157
+ data?: unknown;
158
+ }, {
159
+ type: "conversation";
160
+ conversationId: string;
161
+ data?: unknown;
162
+ }>, z.ZodObject<{
163
+ type: z.ZodLiteral<"heartbeat">;
164
+ }, "strip", z.ZodTypeAny, {
165
+ type: "heartbeat";
166
+ }, {
167
+ type: "heartbeat";
168
+ }>, z.ZodObject<{
169
+ type: z.ZodLiteral<"handshake">;
170
+ metadata: z.ZodObject<{
171
+ workerCount: z.ZodNumber;
172
+ activeWorkflows: z.ZodNumber;
173
+ channel: z.ZodEnum<["preview", "stable"]>;
174
+ orchestratorVersion: z.ZodString;
175
+ gitRemotes: z.ZodArray<z.ZodObject<{
176
+ name: z.ZodString;
177
+ url: z.ZodString;
178
+ }, "strip", z.ZodTypeAny, {
179
+ name: string;
180
+ url: string;
181
+ }, {
182
+ name: string;
183
+ url: string;
184
+ }>, "many">;
185
+ uptime: z.ZodNumber;
186
+ }, "strip", z.ZodTypeAny, {
187
+ workerCount: number;
188
+ activeWorkflows: number;
189
+ channel: "preview" | "stable";
190
+ orchestratorVersion: string;
191
+ gitRemotes: {
192
+ name: string;
193
+ url: string;
194
+ }[];
195
+ uptime: number;
196
+ }, {
197
+ workerCount: number;
198
+ activeWorkflows: number;
199
+ channel: "preview" | "stable";
200
+ orchestratorVersion: string;
201
+ gitRemotes: {
202
+ name: string;
203
+ url: string;
204
+ }[];
205
+ uptime: number;
206
+ }>;
207
+ }, "strip", z.ZodTypeAny, {
208
+ type: "handshake";
209
+ metadata: {
210
+ workerCount: number;
211
+ activeWorkflows: number;
212
+ channel: "preview" | "stable";
213
+ orchestratorVersion: string;
214
+ gitRemotes: {
215
+ name: string;
216
+ url: string;
217
+ }[];
218
+ uptime: number;
219
+ };
220
+ }, {
221
+ type: "handshake";
222
+ metadata: {
223
+ workerCount: number;
224
+ activeWorkflows: number;
225
+ channel: "preview" | "stable";
226
+ orchestratorVersion: string;
227
+ gitRemotes: {
228
+ name: string;
229
+ url: string;
230
+ }[];
231
+ uptime: number;
232
+ };
233
+ }>, z.ZodObject<{
234
+ type: z.ZodLiteral<"error">;
235
+ code: z.ZodString;
236
+ message: z.ZodString;
237
+ }, "strip", z.ZodTypeAny, {
238
+ code: string;
239
+ message: string;
240
+ type: "error";
241
+ }, {
242
+ code: string;
243
+ message: string;
244
+ type: "error";
245
+ }>]>;
246
+ export { ClusterMetadataSchema, GitRemoteSchema };
247
+ /**
248
+ * Parse and validate an incoming relay message.
249
+ * Returns the validated message or null if invalid.
250
+ */
251
+ export declare function parseRelayMessage(data: unknown): RelayMessage | null;
252
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,cAAc,CAAC;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,cAAc,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,YAAY,GACpB,iBAAiB,GACjB,kBAAkB,GAClB,YAAY,GACZ,mBAAmB,GACnB,gBAAgB,GAChB,gBAAgB,GAChB,YAAY,CAAC;AAEjB,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC9B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAChB;AAID,QAAA,MAAM,eAAe;;;;;;;;;EAGnB,CAAC;AAEH,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOzB,CAAC;AA8CH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAQ7B,CAAC;AAEH,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,CAAC;AAElD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CAGpE"}
@@ -0,0 +1,70 @@
1
+ import { z } from 'zod';
2
+ // --- Zod Schemas ---
3
+ const GitRemoteSchema = z.object({
4
+ name: z.string(),
5
+ url: z.string(),
6
+ });
7
+ const ClusterMetadataSchema = z.object({
8
+ workerCount: z.number(),
9
+ activeWorkflows: z.number(),
10
+ channel: z.enum(['preview', 'stable']),
11
+ orchestratorVersion: z.string(),
12
+ gitRemotes: z.array(GitRemoteSchema),
13
+ uptime: z.number(),
14
+ });
15
+ const ApiRequestMessageSchema = z.object({
16
+ type: z.literal('api_request'),
17
+ id: z.string().min(1),
18
+ method: z.string().min(1),
19
+ path: z.string().min(1),
20
+ headers: z.record(z.string()).optional(),
21
+ body: z.unknown().optional(),
22
+ });
23
+ const ApiResponseMessageSchema = z.object({
24
+ type: z.literal('api_response'),
25
+ id: z.string().min(1),
26
+ status: z.number().int().min(100).max(599),
27
+ headers: z.record(z.string()).optional(),
28
+ body: z.unknown().optional(),
29
+ });
30
+ const EventMessageSchema = z.object({
31
+ type: z.literal('event'),
32
+ channel: z.string().min(1),
33
+ event: z.unknown(),
34
+ });
35
+ const ConversationMessageSchema = z.object({
36
+ type: z.literal('conversation'),
37
+ conversationId: z.string().min(1),
38
+ data: z.unknown(),
39
+ });
40
+ const HeartbeatMessageSchema = z.object({
41
+ type: z.literal('heartbeat'),
42
+ });
43
+ const HandshakeMessageSchema = z.object({
44
+ type: z.literal('handshake'),
45
+ metadata: ClusterMetadataSchema,
46
+ });
47
+ const ErrorMessageSchema = z.object({
48
+ type: z.literal('error'),
49
+ code: z.string().min(1),
50
+ message: z.string(),
51
+ });
52
+ export const RelayMessageSchema = z.discriminatedUnion('type', [
53
+ ApiRequestMessageSchema,
54
+ ApiResponseMessageSchema,
55
+ EventMessageSchema,
56
+ ConversationMessageSchema,
57
+ HeartbeatMessageSchema,
58
+ HandshakeMessageSchema,
59
+ ErrorMessageSchema,
60
+ ]);
61
+ export { ClusterMetadataSchema, GitRemoteSchema };
62
+ /**
63
+ * Parse and validate an incoming relay message.
64
+ * Returns the validated message or null if invalid.
65
+ */
66
+ export function parseRelayMessage(data) {
67
+ const result = RelayMessageSchema.safeParse(data);
68
+ return result.success ? result.data : null;
69
+ }
70
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { ClusterMetadata } from './messages.js';
2
+ import type { RelayConfig } from './config.js';
3
+ /**
4
+ * Collect cluster metadata by querying the local orchestrator's
5
+ * /health and /metrics endpoints, and parsing git remotes.
6
+ */
7
+ export declare function collectMetadata(config: RelayConfig): Promise<ClusterMetadata>;
8
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAa,MAAM,eAAe,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;GAGG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,eAAe,CAAC,CAe1B"}
@@ -0,0 +1,77 @@
1
+ import { execSync } from 'node:child_process';
2
+ /**
3
+ * Collect cluster metadata by querying the local orchestrator's
4
+ * /health and /metrics endpoints, and parsing git remotes.
5
+ */
6
+ export async function collectMetadata(config) {
7
+ const [health, metrics, gitRemotes] = await Promise.all([
8
+ fetchHealth(config),
9
+ fetchMetrics(config),
10
+ parseGitRemotes(),
11
+ ]);
12
+ return {
13
+ workerCount: metrics.workerCount,
14
+ activeWorkflows: metrics.activeWorkflows,
15
+ channel: health.channel,
16
+ orchestratorVersion: health.version,
17
+ gitRemotes,
18
+ uptime: health.uptime,
19
+ };
20
+ }
21
+ async function fetchHealth(config) {
22
+ try {
23
+ const response = await fetch(`${config.orchestratorUrl}/health`, {
24
+ signal: AbortSignal.timeout(5000),
25
+ });
26
+ if (response.ok) {
27
+ const data = await response.json();
28
+ return {
29
+ version: String(data['version'] ?? '0.0.0'),
30
+ channel: (data['channel'] === 'preview' ? 'preview' : 'stable'),
31
+ uptime: Number(data['uptime'] ?? 0),
32
+ };
33
+ }
34
+ }
35
+ catch {
36
+ // Orchestrator unreachable — use defaults
37
+ }
38
+ return { version: '0.0.0', channel: 'stable', uptime: 0 };
39
+ }
40
+ async function fetchMetrics(config) {
41
+ try {
42
+ const response = await fetch(`${config.orchestratorUrl}/metrics`, {
43
+ signal: AbortSignal.timeout(5000),
44
+ });
45
+ if (response.ok) {
46
+ const data = await response.json();
47
+ return {
48
+ workerCount: Number(data['workerCount'] ?? 0),
49
+ activeWorkflows: Number(data['activeWorkflows'] ?? 0),
50
+ };
51
+ }
52
+ }
53
+ catch {
54
+ // Orchestrator unreachable — use defaults
55
+ }
56
+ return { workerCount: 0, activeWorkflows: 0 };
57
+ }
58
+ /**
59
+ * Parse git remotes from `git remote -v`.
60
+ */
61
+ async function parseGitRemotes() {
62
+ try {
63
+ const output = execSync('git remote -v', { encoding: 'utf-8', timeout: 5000 });
64
+ const remotes = new Map();
65
+ for (const line of output.split('\n')) {
66
+ const match = line.match(/^(\S+)\s+(\S+)\s+\(fetch\)$/);
67
+ if (match?.[1] && match[2]) {
68
+ remotes.set(match[1], match[2]);
69
+ }
70
+ }
71
+ return Array.from(remotes.entries()).map(([name, url]) => ({ name, url }));
72
+ }
73
+ catch {
74
+ return [];
75
+ }
76
+ }
77
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { ApiRequestMessage, ApiResponseMessage } from './messages.js';
2
+ import type { RelayConfig } from './config.js';
3
+ /**
4
+ * Handle an API request from the cloud by proxying it to the local orchestrator.
5
+ */
6
+ export declare function handleApiRequest(request: ApiRequestMessage, config: RelayConfig): Promise<ApiResponseMessage>;
7
+ //# sourceMappingURL=proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,kBAAkB,CAAC,CAwD7B"}
package/dist/proxy.js ADDED
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Handle an API request from the cloud by proxying it to the local orchestrator.
3
+ */
4
+ export async function handleApiRequest(request, config) {
5
+ const url = `${config.orchestratorUrl}${request.path}`;
6
+ const headers = {
7
+ ...request.headers,
8
+ };
9
+ if (config.orchestratorApiKey) {
10
+ headers['X-API-Key'] = config.orchestratorApiKey;
11
+ }
12
+ try {
13
+ const response = await fetch(url, {
14
+ method: request.method,
15
+ headers,
16
+ body: request.body != null ? JSON.stringify(request.body) : undefined,
17
+ signal: AbortSignal.timeout(config.requestTimeoutMs),
18
+ });
19
+ const responseHeaders = {};
20
+ response.headers.forEach((value, key) => {
21
+ responseHeaders[key] = value;
22
+ });
23
+ let body;
24
+ const contentType = response.headers.get('content-type');
25
+ if (contentType?.includes('application/json')) {
26
+ body = await response.json();
27
+ }
28
+ else {
29
+ body = await response.text();
30
+ }
31
+ return {
32
+ type: 'api_response',
33
+ id: request.id,
34
+ status: response.status,
35
+ headers: responseHeaders,
36
+ body,
37
+ };
38
+ }
39
+ catch (error) {
40
+ if (error instanceof DOMException && error.name === 'TimeoutError') {
41
+ return {
42
+ type: 'api_response',
43
+ id: request.id,
44
+ status: 504,
45
+ body: { error: 'Gateway Timeout', message: 'Request to orchestrator timed out' },
46
+ };
47
+ }
48
+ return {
49
+ type: 'api_response',
50
+ id: request.id,
51
+ status: 502,
52
+ body: { error: 'Bad Gateway', message: `Failed to reach orchestrator: ${String(error)}` },
53
+ };
54
+ }
55
+ }
56
+ //# sourceMappingURL=proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAA0B,EAC1B,MAAmB;IAEnB,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,eAAe,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAEvD,MAAM,OAAO,GAA2B;QACtC,GAAG,OAAO,CAAC,OAAO;KACnB,CAAC;IAEF,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC9B,OAAO,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC,kBAAkB,CAAC;IACnD,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO;YACP,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;YACrE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC;SACrD,CAAC,CAAC;QAEH,MAAM,eAAe,GAA2B,EAAE,CAAC;QACnD,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACtC,eAAe,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAC/B,CAAC,CAAC,CAAC;QAEH,IAAI,IAAa,CAAC;QAClB,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QACzD,IAAI,WAAW,EAAE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC9C,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC/B,CAAC;QAED,OAAO;YACL,IAAI,EAAE,cAAc;YACpB,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,OAAO,EAAE,eAAe;YACxB,IAAI;SACL,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACnE,OAAO;gBACL,IAAI,EAAE,cAAc;gBACpB,EAAE,EAAE,OAAO,CAAC,EAAE;gBACd,MAAM,EAAE,GAAG;gBACX,IAAI,EAAE,EAAE,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,mCAAmC,EAAE;aACjF,CAAC;QACJ,CAAC;QAED,OAAO;YACL,IAAI,EAAE,cAAc;YACpB,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,iCAAiC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE;SAC1F,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,76 @@
1
+ import type { RelayConfig } from './config.js';
2
+ import type { RelayMessage, ClusterMetadata } from './messages.js';
3
+ export type RelayState = 'disconnected' | 'connecting' | 'authenticating' | 'connected' | 'disconnecting';
4
+ export interface Logger {
5
+ info(msg: string): void;
6
+ info(obj: Record<string, unknown>, msg: string): void;
7
+ warn(msg: string): void;
8
+ warn(obj: Record<string, unknown>, msg: string): void;
9
+ error(msg: string): void;
10
+ error(obj: Record<string, unknown>, msg: string): void;
11
+ }
12
+ export declare class ClusterRelay {
13
+ private _state;
14
+ private ws;
15
+ private readonly config;
16
+ private readonly logger;
17
+ private readonly messageHandlers;
18
+ private running;
19
+ private abortController;
20
+ private reconnectAttempt;
21
+ private heartbeatTimer;
22
+ private pongReceived;
23
+ private metadataOverride;
24
+ constructor(config: RelayConfig, logger?: Logger);
25
+ get state(): RelayState;
26
+ /**
27
+ * Establish WebSocket connection with automatic reconnection.
28
+ */
29
+ connect(): Promise<void>;
30
+ /**
31
+ * Gracefully disconnect.
32
+ */
33
+ disconnect(): Promise<void>;
34
+ /**
35
+ * Send a message over the WebSocket.
36
+ */
37
+ send(message: RelayMessage): void;
38
+ /**
39
+ * Register a handler for incoming messages.
40
+ */
41
+ onMessage(handler: (message: RelayMessage) => void): void;
42
+ /**
43
+ * Push an event to the cloud (library mode).
44
+ */
45
+ pushEvent(channel: string, event: unknown): void;
46
+ /**
47
+ * Override metadata for library mode.
48
+ */
49
+ setMetadata(metadata: Partial<ClusterMetadata>): void;
50
+ /**
51
+ * Establish a single WebSocket connection, authenticate, and process messages.
52
+ * Resolves when the connection closes normally, throws on error.
53
+ */
54
+ private connectOnce;
55
+ /**
56
+ * Send handshake with cluster metadata.
57
+ */
58
+ private sendHandshake;
59
+ /**
60
+ * Start the heartbeat interval.
61
+ */
62
+ private startHeartbeat;
63
+ /**
64
+ * Stop the heartbeat interval.
65
+ */
66
+ private stopHeartbeat;
67
+ /**
68
+ * Calculate exponential backoff delay.
69
+ */
70
+ private get reconnectDelayMs();
71
+ /**
72
+ * Cancellable sleep.
73
+ */
74
+ private sleep;
75
+ }
76
+ //# sourceMappingURL=relay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay.d.ts","sourceRoot":"","sources":["../src/relay.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAKnE,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,YAAY,GAAG,gBAAgB,GAAG,WAAW,GAAG,eAAe,CAAC;AAE1G,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACxD;AAiBD,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA8C;IAC9E,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,cAAc,CAA+C;IACrE,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,gBAAgB,CAAyC;gBAErD,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,MAAM;IAKhD,IAAI,KAAK,IAAI,UAAU,CAEtB;IAED;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAuC9B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BjC;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAQjC;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI;IAIzD;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAIhD;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IAIrD;;;OAGG;YACW,WAAW;IA+FzB;;OAEG;YACW,aAAa;IAa3B;;OAEG;IACH,OAAO,CAAC,cAAc;IAmBtB;;OAEG;IACH,OAAO,CAAC,aAAa;IAOrB;;OAEG;IACH,OAAO,KAAK,gBAAgB,GAG3B;IAED;;OAEG;IACH,OAAO,CAAC,KAAK;CAcd"}