@fatagnus/dink-sdk 2.24.0 → 2.24.1

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.
@@ -1,4 +1,501 @@
1
- export { EdgeClient } from './client.js';
2
- export { ServiceBuilder } from './service-builder.js';
3
- export { createEdgeWorker, type EdgeWorkerOptions, type EdgeWorkerHandle, type EdgeConnection } from './worker.js';
4
- //# sourceMappingURL=index.d.ts.map
1
+ // Generated by dts-bundle-generator v9.5.1
2
+
3
+ /**
4
+ * Service definition metadata
5
+ */
6
+ export interface ServiceDefinition {
7
+ name: string;
8
+ version: string;
9
+ methods: string[];
10
+ }
11
+ /**
12
+ * Interface for implementing a service handler on the edge
13
+ */
14
+ /** Bidirectional raw byte channel on the edge side. */
15
+ export interface EdgeChannel {
16
+ /** Unique channel identifier (e.g., "ch_abc123") */
17
+ readonly id: string;
18
+ /** Send raw bytes to the browser. Returns false if backpressure is active. */
19
+ write(data: Uint8Array): boolean;
20
+ /** Register handler for incoming raw bytes from browser */
21
+ onData(handler: (data: Uint8Array) => void): void;
22
+ /** Close the channel, optionally with a reason */
23
+ close(reason?: string): void;
24
+ /** Called when the channel closes (by either side). Supports multiple handlers. */
25
+ onClose(handler: (reason?: string) => void): void;
26
+ /** Send a JSON-serializable control message out-of-band */
27
+ sendControl(msg: unknown): void;
28
+ /** Register handler for incoming control messages */
29
+ onControl(handler: (msg: unknown) => void): void;
30
+ /** True if channel is open */
31
+ readonly isOpen: boolean;
32
+ /** Promise that resolves when the channel closes */
33
+ readonly closed: Promise<void>;
34
+ /** Number of bytes queued for sending */
35
+ readonly bufferedAmount: number;
36
+ /** Register handler called when buffered data has been flushed */
37
+ onDrain(handler: () => void): void;
38
+ }
39
+ /**
40
+ */
41
+ export interface ServiceHandler {
42
+ definition(): ServiceDefinition;
43
+ handleRequest(method: string, data: Uint8Array): Promise<Uint8Array>;
44
+ handleStream?(method: string, data: Uint8Array, emit: (data: Uint8Array) => Promise<void>, signal?: AbortSignal): Promise<void>;
45
+ handleChannel?(method: string, channel: EdgeChannel, request: unknown): Promise<void>;
46
+ }
47
+ /**
48
+ * Interface for making RPC calls to edge services
49
+ */
50
+ export interface ServiceCaller {
51
+ call<Req, Resp>(edgeId: string, service: string, method: string, req: Req): Promise<Resp>;
52
+ subscribe<Req, Resp>(edgeId: string, service: string, method: string, req: Req, handler: (resp: Resp) => void): Promise<Subscription>;
53
+ }
54
+ /**
55
+ * Interface for streaming subscriptions
56
+ */
57
+ export interface Subscription {
58
+ unsubscribe(): void;
59
+ }
60
+ /**
61
+ * Connection quality level
62
+ */
63
+ export type ConnectionQualityLevel = "excellent" | "good" | "fair" | "poor" | "unknown";
64
+ /**
65
+ * Connection state
66
+ */
67
+ export type ConnectionState = "connecting" | "connected" | "reconnecting" | "disconnected";
68
+ /**
69
+ * Connection quality metrics
70
+ */
71
+ export interface ConnectionQuality {
72
+ state: ConnectionState;
73
+ latencyMs: number | null;
74
+ avgLatencyMs: number | null;
75
+ messagesSentPerSecond: number;
76
+ messagesReceivedPerSecond: number;
77
+ totalMessagesSent: number;
78
+ totalMessagesReceived: number;
79
+ lastPingAt: number | null;
80
+ qualityLevel: ConnectionQualityLevel;
81
+ }
82
+ /**
83
+ * Configuration for connection quality monitoring
84
+ */
85
+ export interface ConnectionQualityConfig {
86
+ /** Latency threshold for "excellent" quality in ms (default: 50) */
87
+ excellentLatencyMs?: number;
88
+ /** Latency threshold for "good" quality in ms (default: 150) */
89
+ goodLatencyMs?: number;
90
+ /** Latency threshold for "fair" quality in ms (default: 300) */
91
+ fairLatencyMs?: number;
92
+ /** Ping interval in milliseconds (default: 30000) */
93
+ pingIntervalMs?: number;
94
+ }
95
+ /**
96
+ * Configuration for EdgeClient
97
+ */
98
+ export interface EdgeConfig {
99
+ /** Edge API key (required, format: base64 JSON with url+secret, or legacy dk_<env>_ed_<appID>_<edgeID>_<random>) */
100
+ apiKey: string;
101
+ /** dinkd server URL (e.g., "nats://localhost:4222"). Optional if using new key format with embedded URL. */
102
+ serverUrl?: string;
103
+ /** Optional display name for the edge */
104
+ edgeName?: string;
105
+ /** Optional labels for edge discovery */
106
+ labels?: Record<string, string>;
107
+ /** Optional version string */
108
+ version?: string;
109
+ /** Optional hostname (auto-detected in Node.js) */
110
+ hostname?: string;
111
+ /** Optional IP address */
112
+ ipAddress?: string;
113
+ /** Heartbeat interval in ms (default: 30000) */
114
+ heartbeatInterval?: number;
115
+ /** Connection/request timeout in ms (default: 30000) */
116
+ timeout?: number;
117
+ /** Reconnect wait time in ms (default: 2000) */
118
+ reconnectWait?: number;
119
+ /** Max reconnect attempts, -1 for infinite (default: -1) */
120
+ maxReconnects?: number;
121
+ /** Connection quality configuration */
122
+ qualityConfig?: ConnectionQualityConfig;
123
+ }
124
+ /**
125
+ * Information about a discovered edge
126
+ */
127
+ export interface EdgeInfo {
128
+ /** Unique edge identifier */
129
+ id: string;
130
+ /** Display name of the edge */
131
+ name: string;
132
+ /** Online status */
133
+ status: "online" | "offline";
134
+ /** Labels attached to the edge */
135
+ labels: Record<string, string>;
136
+ /** Services exposed by this edge */
137
+ services: string[];
138
+ /** Groups this edge belongs to */
139
+ groups?: string[];
140
+ }
141
+ /**
142
+ * Options for discovering edges
143
+ */
144
+ export interface DiscoverOptions {
145
+ /** Filter by service name */
146
+ serviceName?: string;
147
+ /** Filter by labels */
148
+ labels?: Record<string, string>;
149
+ /** Only return online edges (default: true) */
150
+ onlineOnly?: boolean;
151
+ /** Filter by method name (requires serviceName) */
152
+ methodName?: string;
153
+ }
154
+ /**
155
+ * Options for RPC calls
156
+ */
157
+ export interface CallOptions {
158
+ /** Request timeout in ms */
159
+ timeout?: number;
160
+ /** Number of retries on failure (default: 0) */
161
+ retries?: number;
162
+ /** Delay between retries in ms (default: 1000) */
163
+ retryDelay?: number;
164
+ }
165
+ /**
166
+ * Service introspection types for AI agent support.
167
+ * These types match the Go struct definitions in pkg/types/introspect.go
168
+ * Property names use snake_case to match Go JSON tags for wire compatibility.
169
+ */
170
+ /**
171
+ * MethodAIContext provides AI-specific guidance for understanding and using a method.
172
+ */
173
+ export interface MethodAIContext {
174
+ /** When this method should be called */
175
+ when_to_use?: string;
176
+ /** Why to use this method over alternatives */
177
+ why_to_use?: string;
178
+ /** Instructions on how to use this method correctly */
179
+ how_to_use?: string;
180
+ /** Conditions that must be true before calling this method */
181
+ preconditions?: string[];
182
+ /** Side effects that occur when calling this method */
183
+ side_effects?: string[];
184
+ /** Names of related methods that may be useful */
185
+ related_methods?: string[];
186
+ /** Scenarios describing when to use this method */
187
+ scenarios?: string[];
188
+ }
189
+ /**
190
+ * ServiceAIContext provides AI-specific guidance for understanding a service.
191
+ */
192
+ export interface ServiceAIContext {
193
+ /** High-level description of what this service does */
194
+ overview?: string;
195
+ /** List of capabilities this service provides */
196
+ capabilities?: string[];
197
+ /** Known limitations of this service */
198
+ limitations?: string[];
199
+ }
200
+ /**
201
+ * MethodDescriptor provides complete metadata about a service method for introspection
202
+ * and AI agent consumption.
203
+ */
204
+ export interface MethodDescriptor {
205
+ /** Method name */
206
+ name: string;
207
+ /** Human-readable description of what this method does */
208
+ description?: string;
209
+ /** JSON Schema describing the input parameters */
210
+ input_schema?: Record<string, unknown>;
211
+ /** JSON Schema describing the output */
212
+ output_schema?: Record<string, unknown>;
213
+ /** Tags for categorization and filtering */
214
+ tags?: string[];
215
+ /** AI-specific context for this method */
216
+ ai_context?: MethodAIContext;
217
+ }
218
+ /**
219
+ * ServiceDescriptor provides complete metadata about a service for introspection
220
+ * and AI agent consumption.
221
+ */
222
+ export interface ServiceDescriptor {
223
+ /** Service name */
224
+ name: string;
225
+ /** Service version (semver recommended) */
226
+ version: string;
227
+ /** Human-readable description of this service */
228
+ description?: string;
229
+ /** Methods provided by this service */
230
+ methods?: MethodDescriptor[];
231
+ /** AI-specific context for this service */
232
+ ai_context?: ServiceAIContext;
233
+ /** Names of related services */
234
+ related_services?: string[];
235
+ }
236
+ export declare class EdgeClient {
237
+ private config;
238
+ private nc;
239
+ private services;
240
+ private heartbeatTimer;
241
+ private pingTimer;
242
+ private appId;
243
+ private edgeId;
244
+ private connectionState;
245
+ private lastLatencyMs;
246
+ private lastPingAt;
247
+ private latencyHistory;
248
+ private messagesSent;
249
+ private messagesReceived;
250
+ private statsStartedAt;
251
+ private qualityCallbacks;
252
+ private qualityConfig;
253
+ private groups;
254
+ constructor(config: EdgeConfig);
255
+ connect(): Promise<void>;
256
+ disconnect(): Promise<void>;
257
+ exposeService(handler: ServiceHandler): Promise<void>;
258
+ private handleStreamRequest;
259
+ private handleChannelRequest;
260
+ unexposeService(name: string): Promise<void>;
261
+ isConnected(): boolean;
262
+ /** Returns the edge ID (extracted from the API key) */
263
+ getEdgeId(): string;
264
+ /** Returns the app ID (extracted from the API key) */
265
+ getAppId(): string;
266
+ /**
267
+ * Get the ServiceDescriptor for an exposed service.
268
+ * Returns null if the service is not found.
269
+ * @param serviceName - The name of the service to describe
270
+ */
271
+ getServiceDescriptor(serviceName: string): ServiceDescriptor | null;
272
+ /** Returns the groups this edge belongs to */
273
+ getGroups(): string[];
274
+ /**
275
+ * Expose a service to group peers.
276
+ * Subscribes to both directed and broadcast subjects for each group.
277
+ */
278
+ exposePeerService(handler: ServiceHandler): Promise<void>;
279
+ /**
280
+ * Call a peer edge's service within a group.
281
+ */
282
+ callPeer<Req, Resp>(groupId: string, edgeId: string, service: string, method: string, req: Req, opts?: CallOptions): Promise<Resp>;
283
+ /**
284
+ * Call a service on any peer in the group (broadcast/queue).
285
+ */
286
+ callGroup<Req, Resp>(groupId: string, service: string, method: string, req: Req, opts?: CallOptions): Promise<Resp>;
287
+ /**
288
+ * Call a center service that is exposed to a specific group.
289
+ */
290
+ callCenterGroup<Req, Resp>(groupId: string, service: string, method: string, req: Req, opts?: CallOptions): Promise<Resp>;
291
+ /**
292
+ * Create a ServiceCaller scoped to a specific group for directed peer-to-peer RPC.
293
+ * The returned caller routes through callPeer, so generated typed clients
294
+ * (e.g., MarketWatcherService.Client) work with edge-to-edge calls.
295
+ *
296
+ * @example
297
+ * const caller = edge.groupCaller('trading-team');
298
+ * const client = new MarketWatcherService.Client('market-watcher', caller);
299
+ * const snapshot = await client.GetMarketSnapshot({ pair: 'BTC/USDT' });
300
+ */
301
+ groupCaller(groupId: string): ServiceCaller;
302
+ /**
303
+ * Create a ServiceCaller scoped to a specific group for broadcast/queue-based RPC.
304
+ * The edgeId parameter in call() is ignored — one random peer in the group handles it.
305
+ */
306
+ groupBroadcastCaller(groupId: string): ServiceCaller;
307
+ /**
308
+ * Unwrap a peer/group service response, handling { result } wrapper and error responses.
309
+ */
310
+ private unwrapPeerResponse;
311
+ /**
312
+ * Discover peers within a group.
313
+ */
314
+ discoverPeers(groupId: string, opts?: DiscoverOptions): Promise<EdgeInfo[]>;
315
+ /**
316
+ * Get current connection quality metrics.
317
+ */
318
+ getConnectionQuality(): ConnectionQuality;
319
+ /**
320
+ * Subscribe to connection quality changes.
321
+ * @param callback - Function called with updated quality metrics
322
+ * @returns Unsubscribe function
323
+ */
324
+ onConnectionQualityChange(callback: (quality: ConnectionQuality) => void): () => void;
325
+ /**
326
+ * Ping the server and return round-trip latency in milliseconds.
327
+ */
328
+ ping(): Promise<number>;
329
+ private setConnectionState;
330
+ private calculateQualityLevel;
331
+ private calculateAvgLatency;
332
+ private buildQualitySnapshot;
333
+ private emitQualityChange;
334
+ private setupConnectionHandlers;
335
+ private startPingTimer;
336
+ private stopPingTimer;
337
+ private extractMethod;
338
+ private registerPresence;
339
+ private deregisterPresence;
340
+ private registerService;
341
+ private deregisterService;
342
+ /** Register a webhook endpoint with dinkd. */
343
+ registerWebhook(service: string, method: string, secret: string, secretMode: string, description: string): Promise<Record<string, unknown>>;
344
+ /** Remove a webhook registration. */
345
+ deregisterWebhook(webhookId: string): Promise<void>;
346
+ /** List all registered webhooks for this edge. */
347
+ listWebhooks(): Promise<Array<Record<string, unknown>>>;
348
+ private startHeartbeat;
349
+ private stopHeartbeat;
350
+ private sendHeartbeat;
351
+ private extractPeerMethod;
352
+ private extractBroadcastPeerMethod;
353
+ private registerPeerService;
354
+ private getAuthHeaders;
355
+ }
356
+ declare class MethodBuilder {
357
+ private methodDescriptor;
358
+ private parent;
359
+ constructor(parent: ServiceBuilder, name: string, description?: string);
360
+ /**
361
+ * Add AI context to this method.
362
+ */
363
+ withAI(aiContext: MethodAIContext): MethodBuilder;
364
+ /**
365
+ * Add another method to the service (returns to service builder context).
366
+ */
367
+ method(name: string, description?: string): MethodBuilder;
368
+ /**
369
+ * Build the final ServiceDescriptor.
370
+ */
371
+ build(): ServiceDescriptor;
372
+ /**
373
+ * Create a ServiceHandler from the builder with the given implementation.
374
+ */
375
+ toHandler(impl: Record<string, (data: unknown) => Promise<unknown>>): ServiceHandler & {
376
+ _descriptor: ServiceDescriptor;
377
+ };
378
+ /**
379
+ * Internal: Get the method descriptor.
380
+ */
381
+ _getDescriptor(): MethodDescriptor;
382
+ }
383
+ /**
384
+ * ServiceBuilder provides a fluent API for building ServiceDescriptor with AI context.
385
+ *
386
+ * @example
387
+ * ```typescript
388
+ * const builder = new ServiceBuilder('SensorService', '1.0.0')
389
+ * .description('Manages sensor data')
390
+ * .withAI({
391
+ * overview: 'Service for reading and managing sensor data',
392
+ * capabilities: ['read temperature', 'set thresholds'],
393
+ * })
394
+ * .method('ReadTemperature', 'Reads current temperature')
395
+ * .withAI({ when_to_use: 'When you need current sensor readings' })
396
+ * .withExample('typescript', 'await sensor.readTemperature()', 'Basic usage')
397
+ * .method('SetThreshold')
398
+ * .withAI({ when_to_use: 'When you need to configure alerts' });
399
+ *
400
+ * const handler = builder.toHandler({
401
+ * ReadTemperature: async () => ({ value: 23.5 }),
402
+ * SetThreshold: async (data) => ({ success: true }),
403
+ * });
404
+ *
405
+ * await edge.exposeService(handler);
406
+ * ```
407
+ */
408
+ export declare class ServiceBuilder {
409
+ private descriptor;
410
+ private methodBuilders;
411
+ private currentMethodBuilder;
412
+ constructor(name: string, version: string);
413
+ /**
414
+ * Set the service description.
415
+ */
416
+ description(desc: string): ServiceBuilder;
417
+ /**
418
+ * Add AI context to the service.
419
+ */
420
+ withAI(aiContext: ServiceAIContext): ServiceBuilder;
421
+ /**
422
+ * Add a related service.
423
+ */
424
+ relatedService(serviceName: string): ServiceBuilder;
425
+ /**
426
+ * Add a method to the service. Returns a MethodBuilder for fluent chaining.
427
+ */
428
+ method(name: string, description?: string): MethodBuilder;
429
+ /**
430
+ * Build the final ServiceDescriptor.
431
+ */
432
+ build(): ServiceDescriptor;
433
+ /**
434
+ * Create a ServiceHandler from the builder with the given implementation.
435
+ *
436
+ * @param impl - Object mapping method names to handler functions
437
+ * @returns A ServiceHandler that can be passed to EdgeClient.exposeService()
438
+ */
439
+ toHandler(impl: Record<string, (data: unknown) => Promise<unknown>>): ServiceHandler & {
440
+ _descriptor: ServiceDescriptor;
441
+ };
442
+ }
443
+ /** Type alias for the edge connection passed to onConnected/onError callbacks */
444
+ export type EdgeConnection = EdgeClient;
445
+ /**
446
+ * Options for createEdgeWorker.
447
+ */
448
+ export interface EdgeWorkerOptions {
449
+ /** Services to expose. Required, at least one. */
450
+ services: ServiceHandler[];
451
+ /** API key. Defaults to process.env.DINK_EDGE_KEY || process.env.DINK_API_KEY */
452
+ apiKey?: string;
453
+ /** Server URL. Optional if using new key format with embedded URL. Defaults to process.env.DINK_SERVER_URL */
454
+ serverUrl?: string;
455
+ /** Display name for the edge. Defaults to process.env.EDGE_NAME */
456
+ edgeName?: string;
457
+ /** Labels for edge discovery */
458
+ labels?: Record<string, string>;
459
+ /** Heartbeat interval in ms (default: 30000) */
460
+ heartbeatInterval?: number;
461
+ /** Whether to register SIGINT/SIGTERM handlers for graceful shutdown (default: true) */
462
+ gracefulShutdown?: boolean;
463
+ /** Callback when connected */
464
+ onConnected?: (edge: EdgeClient) => void;
465
+ /** Callback when disconnected */
466
+ onDisconnected?: () => void;
467
+ /** Callback on error */
468
+ onError?: (error: Error) => void;
469
+ }
470
+ /**
471
+ * Handle returned by createEdgeWorker for lifecycle control.
472
+ */
473
+ export interface EdgeWorkerHandle {
474
+ /** The underlying EdgeClient instance */
475
+ client: EdgeClient;
476
+ /** Gracefully shut down the worker */
477
+ shutdown: () => Promise<void>;
478
+ /** Promise that resolves when the worker shuts down */
479
+ done: Promise<void>;
480
+ }
481
+ /**
482
+ * Create and start an edge worker with minimal configuration.
483
+ *
484
+ * Handles credential resolution from environment, connection, service exposure,
485
+ * signal handling, and graceful shutdown automatically.
486
+ *
487
+ * @example
488
+ * ```typescript
489
+ * import { createEdgeWorker } from '@fatagnus/dink-sdk/edge'
490
+ * import { SensorServiceHandler } from './generated/sensorservice.handler.js'
491
+ * import { SensorServiceImpl } from './sensor-impl.js'
492
+ *
493
+ * await createEdgeWorker({
494
+ * services: [new SensorServiceHandler(new SensorServiceImpl())],
495
+ * labels: { region: 'us-east', type: 'sensor' },
496
+ * })
497
+ * ```
498
+ */
499
+ export declare function createEdgeWorker(options: EdgeWorkerOptions): Promise<EdgeWorkerHandle>;
500
+
501
+ export {};
@@ -91,4 +91,3 @@ export declare class ServiceBuilder {
91
91
  };
92
92
  }
93
93
  export {};
94
- //# sourceMappingURL=service-builder.d.ts.map
@@ -57,4 +57,3 @@ export interface EdgeWorkerHandle {
57
57
  * ```
58
58
  */
59
59
  export declare function createEdgeWorker(options: EdgeWorkerOptions): Promise<EdgeWorkerHandle>;
60
- //# sourceMappingURL=worker.d.ts.map
@@ -1,25 +1,27 @@
1
+ // Generated by dts-bundle-generator v9.5.1
2
+
1
3
  /**
2
4
  * Credentials loaded from a .dink/ environment or env vars.
3
5
  */
4
6
  export interface DinkEnv {
5
- name: string;
6
- server: string;
7
- apiKey: string;
8
- appId: string;
9
- syncKey: string;
7
+ name: string;
8
+ server: string;
9
+ apiKey: string;
10
+ appId: string;
11
+ syncKey: string;
10
12
  }
11
13
  /**
12
14
  * Options for loadDinkEnv.
13
15
  */
14
16
  export interface LoadOptions {
15
- app?: string;
17
+ app?: string;
16
18
  }
17
19
  /**
18
20
  * Error thrown when environment resolution fails.
19
21
  */
20
22
  export declare class DinkEnvError extends Error {
21
- readonly code: 'NO_ENVIRONMENT' | 'NOT_FOUND';
22
- constructor(message: string, code: 'NO_ENVIRONMENT' | 'NOT_FOUND');
23
+ readonly code: "NO_ENVIRONMENT" | "NOT_FOUND";
24
+ constructor(message: string, code: "NO_ENVIRONMENT" | "NOT_FOUND");
23
25
  }
24
26
  /**
25
27
  * Load Dink credentials.
@@ -38,4 +40,5 @@ export declare class DinkEnvError extends Error {
38
40
  * 5. empty string
39
41
  */
40
42
  export declare function loadDinkEnv(name?: string, options?: LoadOptions): Promise<DinkEnv>;
41
- //# sourceMappingURL=index.d.ts.map
43
+
44
+ export {};
package/dist/errors.d.ts CHANGED
@@ -50,4 +50,3 @@ export declare class ConfigError extends DinkError {
50
50
  export declare class WebhookError extends DinkError {
51
51
  constructor(message: string, code?: string);
52
52
  }
53
- //# sourceMappingURL=errors.d.ts.map