kalam-link 0.2.0-alpha1
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 +17 -0
- package/README.md +423 -0
- package/dist/auth.d.ts +113 -0
- package/dist/auth.js +131 -0
- package/dist/index.d.ts +781 -0
- package/dist/index.js +683 -0
- package/dist/wasm/README.md +460 -0
- package/dist/wasm/kalam_link.d.ts +368 -0
- package/dist/wasm/kalam_link.js +1237 -0
- package/dist/wasm/kalam_link_bg.wasm +0 -0
- package/dist/wasm/kalam_link_bg.wasm.d.ts +45 -0
- package/package.json +59 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,781 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kalam-link - Official TypeScript/JavaScript client for KalamDB
|
|
3
|
+
*
|
|
4
|
+
* This package provides a type-safe wrapper around the KalamDB WASM bindings
|
|
5
|
+
* for use in Node.js and browser environments.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - SQL query execution via HTTP
|
|
9
|
+
* - Real-time subscriptions via WebSocket (single connection, multiple subscriptions)
|
|
10
|
+
* - Subscription management with modern patterns (unsubscribe functions)
|
|
11
|
+
* - Cross-platform support (Node.js & Browser)
|
|
12
|
+
* - Type-safe authentication with multiple providers (Basic Auth, JWT, Anonymous)
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { createClient, Auth } from 'kalam-link';
|
|
17
|
+
*
|
|
18
|
+
* // Basic Auth (username/password)
|
|
19
|
+
* const client = createClient({
|
|
20
|
+
* url: 'http://localhost:8080',
|
|
21
|
+
* auth: Auth.basic('admin', 'admin')
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* // JWT Token Auth
|
|
25
|
+
* const jwtClient = createClient({
|
|
26
|
+
* url: 'http://localhost:8080',
|
|
27
|
+
* auth: Auth.jwt('eyJhbGciOiJIUzI1NiIs...')
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // Anonymous (localhost bypass)
|
|
31
|
+
* const anonClient = createClient({
|
|
32
|
+
* url: 'http://localhost:8080',
|
|
33
|
+
* auth: Auth.none()
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* await client.connect();
|
|
37
|
+
*
|
|
38
|
+
* // Subscribe to changes (returns unsubscribe function - Firebase/Supabase style)
|
|
39
|
+
* const unsubscribe = await client.subscribe('messages', (event) => {
|
|
40
|
+
* console.log('Change:', event);
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* // Check subscription count
|
|
44
|
+
* console.log(`Active subscriptions: ${client.getSubscriptionCount()}`);
|
|
45
|
+
*
|
|
46
|
+
* // Later: unsubscribe when done
|
|
47
|
+
* await unsubscribe();
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export { Auth, AuthCredentials, BasicAuthCredentials, JwtAuthCredentials, NoAuthCredentials, buildAuthHeader, encodeBasicAuth, isAuthenticated, isBasicAuth, isJwtAuth, isNoAuth } from './auth.js';
|
|
51
|
+
import type { AuthCredentials } from './auth.js';
|
|
52
|
+
export type { KalamClient as WasmKalamClient } from './wasm/kalam_link.js';
|
|
53
|
+
/**
|
|
54
|
+
* Schema field describing a column in the result set
|
|
55
|
+
*/
|
|
56
|
+
export interface SchemaField {
|
|
57
|
+
/** Column name */
|
|
58
|
+
name: string;
|
|
59
|
+
/** Data type (e.g., 'BigInt', 'Text', 'Timestamp') */
|
|
60
|
+
data_type: string;
|
|
61
|
+
/** Column index in the row array */
|
|
62
|
+
index: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Query result structure matching KalamDB server response
|
|
66
|
+
*/
|
|
67
|
+
export interface QueryResult {
|
|
68
|
+
/** Schema describing the columns in the result set */
|
|
69
|
+
schema: SchemaField[];
|
|
70
|
+
/** Result rows as arrays of values (ordered by schema index) */
|
|
71
|
+
rows?: unknown[][];
|
|
72
|
+
/** Number of rows affected or returned */
|
|
73
|
+
row_count: number;
|
|
74
|
+
/** Optional message for non-query statements */
|
|
75
|
+
message?: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Full query response from the server
|
|
79
|
+
*/
|
|
80
|
+
export interface QueryResponse {
|
|
81
|
+
/** Query execution status */
|
|
82
|
+
status: 'success' | 'error';
|
|
83
|
+
/** Array of result sets, one per executed statement */
|
|
84
|
+
results: QueryResult[];
|
|
85
|
+
/** Query execution time in milliseconds */
|
|
86
|
+
took?: number;
|
|
87
|
+
/** Error details if status is "error" */
|
|
88
|
+
error?: ErrorDetail;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Error detail structure
|
|
92
|
+
*/
|
|
93
|
+
export interface ErrorDetail {
|
|
94
|
+
/** Error code */
|
|
95
|
+
code: string;
|
|
96
|
+
/** Error message */
|
|
97
|
+
message: string;
|
|
98
|
+
/** Optional error details */
|
|
99
|
+
details?: any;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Message type enum for WebSocket subscription events
|
|
103
|
+
*/
|
|
104
|
+
export declare enum MessageType {
|
|
105
|
+
SubscriptionAck = "subscription_ack",
|
|
106
|
+
InitialDataBatch = "initial_data_batch",
|
|
107
|
+
Change = "change",
|
|
108
|
+
Error = "error"
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Change type enum for live subscription change events
|
|
112
|
+
*/
|
|
113
|
+
export declare enum ChangeType {
|
|
114
|
+
Insert = "insert",
|
|
115
|
+
Update = "update",
|
|
116
|
+
Delete = "delete"
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Batch loading status enum
|
|
120
|
+
*/
|
|
121
|
+
export declare enum BatchStatus {
|
|
122
|
+
Loading = "loading",
|
|
123
|
+
LoadingBatch = "loading_batch",
|
|
124
|
+
Ready = "ready"
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Server message types for WebSocket subscriptions
|
|
128
|
+
*/
|
|
129
|
+
export type ServerMessage = {
|
|
130
|
+
type: MessageType.SubscriptionAck | 'subscription_ack';
|
|
131
|
+
subscription_id: string;
|
|
132
|
+
total_rows: number;
|
|
133
|
+
batch_control: BatchControl;
|
|
134
|
+
schema: SchemaField[];
|
|
135
|
+
} | {
|
|
136
|
+
type: MessageType.InitialDataBatch | 'initial_data_batch';
|
|
137
|
+
subscription_id: string;
|
|
138
|
+
rows: Record<string, any>[];
|
|
139
|
+
batch_control: BatchControl;
|
|
140
|
+
} | {
|
|
141
|
+
type: MessageType.Change | 'change';
|
|
142
|
+
subscription_id: string;
|
|
143
|
+
change_type: ChangeType | 'insert' | 'update' | 'delete';
|
|
144
|
+
rows?: Record<string, any>[];
|
|
145
|
+
old_values?: Record<string, any>[];
|
|
146
|
+
} | {
|
|
147
|
+
type: MessageType.Error | 'error';
|
|
148
|
+
subscription_id: string;
|
|
149
|
+
code: string;
|
|
150
|
+
message: string;
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Batch control metadata for paginated data loading
|
|
154
|
+
*
|
|
155
|
+
* Note: We don't include total_batches because we can't know it upfront
|
|
156
|
+
* without counting all rows first (expensive). The `has_more` field is
|
|
157
|
+
* sufficient for clients to know whether to request more batches.
|
|
158
|
+
*/
|
|
159
|
+
export interface BatchControl {
|
|
160
|
+
/** Current batch number (0-indexed) */
|
|
161
|
+
batch_num: number;
|
|
162
|
+
/** Whether more batches are available */
|
|
163
|
+
has_more: boolean;
|
|
164
|
+
/** Loading status */
|
|
165
|
+
status: BatchStatus | 'loading' | 'loading_batch' | 'ready';
|
|
166
|
+
/** Last sequence ID in this batch */
|
|
167
|
+
last_seq_id?: string;
|
|
168
|
+
/** Snapshot boundary sequence ID */
|
|
169
|
+
snapshot_end_seq?: string;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Subscription callback function type
|
|
173
|
+
*/
|
|
174
|
+
export type SubscriptionCallback = (event: ServerMessage) => void;
|
|
175
|
+
/**
|
|
176
|
+
* Function to unsubscribe from a subscription (Firebase/Supabase style)
|
|
177
|
+
* @returns Promise that resolves when unsubscription is complete
|
|
178
|
+
*/
|
|
179
|
+
export type Unsubscribe = () => Promise<void>;
|
|
180
|
+
/**
|
|
181
|
+
* Information about an active subscription
|
|
182
|
+
*/
|
|
183
|
+
export interface SubscriptionInfo {
|
|
184
|
+
/** Unique subscription ID */
|
|
185
|
+
id: string;
|
|
186
|
+
/** Table name or SQL query being subscribed to */
|
|
187
|
+
tableName: string;
|
|
188
|
+
/** Timestamp when subscription was created */
|
|
189
|
+
createdAt: Date;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Connection-level options for WebSocket connection behavior
|
|
193
|
+
*
|
|
194
|
+
* These options control the overall WebSocket connection, including:
|
|
195
|
+
* - Automatic reconnection on connection loss
|
|
196
|
+
* - Reconnection timing and retry limits
|
|
197
|
+
*
|
|
198
|
+
* Separate from SubscriptionOptions which control individual subscriptions.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```typescript
|
|
202
|
+
* const client = new KalamDBClient('http://localhost:8080', 'user', 'pass');
|
|
203
|
+
*
|
|
204
|
+
* // Configure connection options before connecting
|
|
205
|
+
* client.setAutoReconnect(true);
|
|
206
|
+
* client.setReconnectDelay(2000, 60000);
|
|
207
|
+
* client.setMaxReconnectAttempts(10);
|
|
208
|
+
*
|
|
209
|
+
* await client.connect();
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
export interface ConnectionOptions {
|
|
213
|
+
/**
|
|
214
|
+
* Enable automatic reconnection on connection loss
|
|
215
|
+
* Default: true - automatically attempts to reconnect
|
|
216
|
+
*/
|
|
217
|
+
auto_reconnect?: boolean;
|
|
218
|
+
/**
|
|
219
|
+
* Initial delay in milliseconds between reconnection attempts
|
|
220
|
+
* Default: 1000ms (1 second)
|
|
221
|
+
* Uses exponential backoff up to max_reconnect_delay_ms
|
|
222
|
+
*/
|
|
223
|
+
reconnect_delay_ms?: number;
|
|
224
|
+
/**
|
|
225
|
+
* Maximum delay between reconnection attempts (for exponential backoff)
|
|
226
|
+
* Default: 30000ms (30 seconds)
|
|
227
|
+
*/
|
|
228
|
+
max_reconnect_delay_ms?: number;
|
|
229
|
+
/**
|
|
230
|
+
* Maximum number of reconnection attempts before giving up
|
|
231
|
+
* Default: undefined (infinite retries)
|
|
232
|
+
* Set to 0 to disable reconnection entirely
|
|
233
|
+
*/
|
|
234
|
+
max_reconnect_attempts?: number;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Subscription options for controlling individual subscription behavior
|
|
238
|
+
*
|
|
239
|
+
* These options control subscription behavior including:
|
|
240
|
+
* - Initial data loading (batch_size, last_rows)
|
|
241
|
+
* - Data resumption after reconnection (from_seq_id)
|
|
242
|
+
*
|
|
243
|
+
* Aligned with backend's SubscriptionOptions.
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* ```typescript
|
|
247
|
+
* // Fetch last 100 rows with batch size of 50
|
|
248
|
+
* const options: SubscriptionOptions = {
|
|
249
|
+
* batch_size: 50,
|
|
250
|
+
* last_rows: 100
|
|
251
|
+
* };
|
|
252
|
+
*
|
|
253
|
+
* const unsubscribe = await client.subscribe('messages', callback, options);
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
256
|
+
export interface SubscriptionOptions {
|
|
257
|
+
/**
|
|
258
|
+
* Hint for server-side batch sizing during initial data load
|
|
259
|
+
* Default: server-configured (typically 1000 rows per batch)
|
|
260
|
+
*/
|
|
261
|
+
batch_size?: number;
|
|
262
|
+
/**
|
|
263
|
+
* Number of last (newest) rows to fetch for initial data
|
|
264
|
+
* Default: undefined (fetch all matching rows)
|
|
265
|
+
*/
|
|
266
|
+
last_rows?: number;
|
|
267
|
+
/**
|
|
268
|
+
* Resume subscription from a specific sequence ID
|
|
269
|
+
* When set, the server will only send changes after this seq_id
|
|
270
|
+
* Typically set automatically during reconnection to resume from last received event
|
|
271
|
+
*/
|
|
272
|
+
from_seq_id?: string;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* @deprecated Use SubscriptionOptions instead. This type alias is for backwards compatibility.
|
|
276
|
+
*/
|
|
277
|
+
export type SubscribeOptions = SubscriptionOptions;
|
|
278
|
+
/**
|
|
279
|
+
* Configuration options for KalamDB client (new type-safe API)
|
|
280
|
+
*
|
|
281
|
+
* Uses discriminated unions for type-safe authentication.
|
|
282
|
+
*
|
|
283
|
+
* @example
|
|
284
|
+
* ```typescript
|
|
285
|
+
* // Type-safe auth options
|
|
286
|
+
* const client = createClient({
|
|
287
|
+
* url: 'http://localhost:8080',
|
|
288
|
+
* auth: Auth.basic('admin', 'admin')
|
|
289
|
+
* });
|
|
290
|
+
*
|
|
291
|
+
* // JWT authentication
|
|
292
|
+
* const jwtClient = createClient({
|
|
293
|
+
* url: 'http://localhost:8080',
|
|
294
|
+
* auth: Auth.jwt('eyJhbGciOiJIUzI1NiIs...')
|
|
295
|
+
* });
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
export interface ClientOptionsWithAuth {
|
|
299
|
+
/** Server URL (e.g., 'http://localhost:8080') */
|
|
300
|
+
url: string;
|
|
301
|
+
/** Authentication credentials (type-safe) */
|
|
302
|
+
auth: AuthCredentials;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Configuration options for KalamDB client (legacy API)
|
|
306
|
+
*
|
|
307
|
+
* @deprecated Use ClientOptionsWithAuth with Auth.basic() instead
|
|
308
|
+
*/
|
|
309
|
+
export interface ClientOptionsLegacy {
|
|
310
|
+
/** Server URL (e.g., 'http://localhost:8080') */
|
|
311
|
+
url: string;
|
|
312
|
+
/** Username for authentication */
|
|
313
|
+
username: string;
|
|
314
|
+
/** Password for authentication */
|
|
315
|
+
password: string;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Configuration options for KalamDB client
|
|
319
|
+
*
|
|
320
|
+
* Supports both new type-safe auth API and legacy username/password API.
|
|
321
|
+
*/
|
|
322
|
+
export type ClientOptions = ClientOptionsWithAuth | ClientOptionsLegacy;
|
|
323
|
+
/**
|
|
324
|
+
* KalamDB Client - TypeScript wrapper around WASM bindings
|
|
325
|
+
*
|
|
326
|
+
* Provides a type-safe interface to KalamDB with support for:
|
|
327
|
+
* - SQL query execution
|
|
328
|
+
* - Real-time WebSocket subscriptions
|
|
329
|
+
* - Multiple authentication methods (Basic Auth, JWT, Anonymous)
|
|
330
|
+
* - Cross-platform (Node.js & Browser)
|
|
331
|
+
* - Subscription tracking and management
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* ```typescript
|
|
335
|
+
* // New API with type-safe auth (recommended)
|
|
336
|
+
* import { createClient, Auth } from 'kalam-link';
|
|
337
|
+
*
|
|
338
|
+
* const client = createClient({
|
|
339
|
+
* url: 'http://localhost:8080',
|
|
340
|
+
* auth: Auth.basic('alice', 'password123')
|
|
341
|
+
* });
|
|
342
|
+
*
|
|
343
|
+
* // JWT authentication
|
|
344
|
+
* const jwtClient = createClient({
|
|
345
|
+
* url: 'http://localhost:8080',
|
|
346
|
+
* auth: Auth.jwt('eyJhbGciOiJIUzI1NiIs...')
|
|
347
|
+
* });
|
|
348
|
+
*
|
|
349
|
+
* // Anonymous (no auth - localhost bypass)
|
|
350
|
+
* const anonClient = createClient({
|
|
351
|
+
* url: 'http://localhost:8080',
|
|
352
|
+
* auth: Auth.none()
|
|
353
|
+
* });
|
|
354
|
+
*
|
|
355
|
+
* await client.connect();
|
|
356
|
+
*
|
|
357
|
+
* // Execute queries
|
|
358
|
+
* const users = await client.query('SELECT * FROM users WHERE active = true');
|
|
359
|
+
* console.log(users.results[0].rows);
|
|
360
|
+
*
|
|
361
|
+
* // Subscribe to changes (returns unsubscribe function)
|
|
362
|
+
* const unsubscribe = await client.subscribe('messages', (event) => {
|
|
363
|
+
* if (event.type === 'change') {
|
|
364
|
+
* console.log('New message:', event.rows);
|
|
365
|
+
* }
|
|
366
|
+
* });
|
|
367
|
+
*
|
|
368
|
+
* // Check subscription count
|
|
369
|
+
* console.log(`Active: ${client.getSubscriptionCount()}`);
|
|
370
|
+
*
|
|
371
|
+
* // Cleanup
|
|
372
|
+
* await unsubscribe();
|
|
373
|
+
* await client.disconnect();
|
|
374
|
+
* ```
|
|
375
|
+
*/
|
|
376
|
+
export declare class KalamDBClient {
|
|
377
|
+
private wasmClient;
|
|
378
|
+
private initialized;
|
|
379
|
+
private url;
|
|
380
|
+
private auth;
|
|
381
|
+
/** Track active subscriptions for management */
|
|
382
|
+
private subscriptions;
|
|
383
|
+
/**
|
|
384
|
+
* Create a new KalamDB client with type-safe auth options
|
|
385
|
+
*
|
|
386
|
+
* @param options - Client options with URL and auth credentials
|
|
387
|
+
*
|
|
388
|
+
* @throws Error if url is empty
|
|
389
|
+
*
|
|
390
|
+
* @example
|
|
391
|
+
* ```typescript
|
|
392
|
+
* import { KalamDBClient, Auth } from 'kalam-link';
|
|
393
|
+
*
|
|
394
|
+
* const client = new KalamDBClient({
|
|
395
|
+
* url: 'http://localhost:8080',
|
|
396
|
+
* auth: Auth.basic('admin', 'secret')
|
|
397
|
+
* });
|
|
398
|
+
* ```
|
|
399
|
+
*/
|
|
400
|
+
constructor(options: ClientOptionsWithAuth);
|
|
401
|
+
/**
|
|
402
|
+
* Create a new KalamDB client with username/password (legacy API)
|
|
403
|
+
*
|
|
404
|
+
* @param url - Server URL (e.g., 'http://localhost:8080')
|
|
405
|
+
* @param username - Username for authentication
|
|
406
|
+
* @param password - Password for authentication
|
|
407
|
+
*
|
|
408
|
+
* @throws Error if url, username, or password is empty
|
|
409
|
+
*
|
|
410
|
+
* @deprecated Use constructor with ClientOptionsWithAuth and Auth.basic() instead
|
|
411
|
+
*/
|
|
412
|
+
constructor(url: string, username: string, password: string);
|
|
413
|
+
/**
|
|
414
|
+
* Get the current authentication type
|
|
415
|
+
*
|
|
416
|
+
* @returns 'basic', 'jwt', or 'none'
|
|
417
|
+
*/
|
|
418
|
+
getAuthType(): 'basic' | 'jwt' | 'none';
|
|
419
|
+
/**
|
|
420
|
+
* Initialize WASM module and create client instance
|
|
421
|
+
*
|
|
422
|
+
* Must be called before any other operations. Automatically called by connect()
|
|
423
|
+
* if not already initialized.
|
|
424
|
+
*
|
|
425
|
+
* @throws Error if WASM initialization fails
|
|
426
|
+
*/
|
|
427
|
+
initialize(): Promise<void>;
|
|
428
|
+
/**
|
|
429
|
+
* Connect to KalamDB server via WebSocket
|
|
430
|
+
*
|
|
431
|
+
* Establishes a persistent WebSocket connection for real-time subscriptions.
|
|
432
|
+
* Also initializes the WASM module if not already done.
|
|
433
|
+
*
|
|
434
|
+
* @throws Error if connection fails
|
|
435
|
+
*/
|
|
436
|
+
connect(): Promise<void>;
|
|
437
|
+
/**
|
|
438
|
+
* Enable or disable automatic reconnection
|
|
439
|
+
*
|
|
440
|
+
* When enabled, the client will automatically attempt to reconnect
|
|
441
|
+
* if the WebSocket connection is lost, and will re-subscribe to all
|
|
442
|
+
* active subscriptions with resume_from_seq_id to catch up on missed events.
|
|
443
|
+
*
|
|
444
|
+
* @param enabled - Whether to automatically reconnect on connection loss
|
|
445
|
+
*
|
|
446
|
+
* @example
|
|
447
|
+
* ```typescript
|
|
448
|
+
* client.setAutoReconnect(true); // Enable (default)
|
|
449
|
+
* client.setAutoReconnect(false); // Disable for manual control
|
|
450
|
+
* ```
|
|
451
|
+
*/
|
|
452
|
+
setAutoReconnect(enabled: boolean): void;
|
|
453
|
+
/**
|
|
454
|
+
* Configure reconnection delay parameters
|
|
455
|
+
*
|
|
456
|
+
* The client uses exponential backoff starting from initialDelayMs,
|
|
457
|
+
* doubling each attempt up to maxDelayMs.
|
|
458
|
+
*
|
|
459
|
+
* @param initialDelayMs - Initial delay between reconnection attempts (default: 1000ms)
|
|
460
|
+
* @param maxDelayMs - Maximum delay for exponential backoff (default: 30000ms)
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* ```typescript
|
|
464
|
+
* // Start with 500ms delay, max out at 10 seconds
|
|
465
|
+
* client.setReconnectDelay(500, 10000);
|
|
466
|
+
* ```
|
|
467
|
+
*/
|
|
468
|
+
setReconnectDelay(initialDelayMs: number, maxDelayMs: number): void;
|
|
469
|
+
/**
|
|
470
|
+
* Set maximum number of reconnection attempts
|
|
471
|
+
*
|
|
472
|
+
* @param maxAttempts - Maximum attempts before giving up (0 = infinite)
|
|
473
|
+
*
|
|
474
|
+
* @example
|
|
475
|
+
* ```typescript
|
|
476
|
+
* client.setMaxReconnectAttempts(5); // Give up after 5 attempts
|
|
477
|
+
* client.setMaxReconnectAttempts(0); // Never give up (default)
|
|
478
|
+
* ```
|
|
479
|
+
*/
|
|
480
|
+
setMaxReconnectAttempts(maxAttempts: number): void;
|
|
481
|
+
/**
|
|
482
|
+
* Get the current number of reconnection attempts
|
|
483
|
+
*
|
|
484
|
+
* Resets to 0 after a successful reconnection.
|
|
485
|
+
*
|
|
486
|
+
* @returns Current reconnection attempt count
|
|
487
|
+
*/
|
|
488
|
+
getReconnectAttempts(): number;
|
|
489
|
+
/**
|
|
490
|
+
* Check if the client is currently attempting to reconnect
|
|
491
|
+
*
|
|
492
|
+
* @returns true if a reconnection is in progress
|
|
493
|
+
*/
|
|
494
|
+
isReconnecting(): boolean;
|
|
495
|
+
/**
|
|
496
|
+
* Get the last received sequence ID for a subscription
|
|
497
|
+
*
|
|
498
|
+
* Useful for debugging or manual tracking of subscription progress.
|
|
499
|
+
* This seq_id is automatically used during reconnection to resume
|
|
500
|
+
* from where the subscription left off.
|
|
501
|
+
*
|
|
502
|
+
* @param subscriptionId - The subscription ID to query
|
|
503
|
+
* @returns The last seq_id as a string, or undefined if not set
|
|
504
|
+
*
|
|
505
|
+
* @example
|
|
506
|
+
* ```typescript
|
|
507
|
+
* const lastSeq = client.getLastSeqId(subscriptionId);
|
|
508
|
+
* console.log(`Last received seq: ${lastSeq}`);
|
|
509
|
+
* ```
|
|
510
|
+
*/
|
|
511
|
+
getLastSeqId(subscriptionId: string): string | undefined;
|
|
512
|
+
/**
|
|
513
|
+
* Helper to ensure WASM client is initialized
|
|
514
|
+
* @private
|
|
515
|
+
*/
|
|
516
|
+
private ensureInitialized;
|
|
517
|
+
/**
|
|
518
|
+
* Disconnect from KalamDB server
|
|
519
|
+
*
|
|
520
|
+
* Closes the WebSocket connection and cleans up all active subscriptions.
|
|
521
|
+
*/
|
|
522
|
+
disconnect(): Promise<void>;
|
|
523
|
+
/**
|
|
524
|
+
* Check if client is currently connected
|
|
525
|
+
*
|
|
526
|
+
* @returns true if WebSocket connection is active, false otherwise
|
|
527
|
+
*/
|
|
528
|
+
isConnected(): boolean;
|
|
529
|
+
/**
|
|
530
|
+
* Execute a SQL query with optional parameters
|
|
531
|
+
*
|
|
532
|
+
* Supports all SQL statements: SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, etc.
|
|
533
|
+
* Use parameterized queries to prevent SQL injection.
|
|
534
|
+
*
|
|
535
|
+
* @param sql - SQL query string (may contain $1, $2, ... placeholders)
|
|
536
|
+
* @param params - Optional array of parameter values for placeholders
|
|
537
|
+
* @returns Parsed query response with results
|
|
538
|
+
*
|
|
539
|
+
* @throws Error if query execution fails
|
|
540
|
+
*
|
|
541
|
+
* @example
|
|
542
|
+
* ```typescript
|
|
543
|
+
* // Simple query
|
|
544
|
+
* const result = await client.query('SELECT * FROM users');
|
|
545
|
+
*
|
|
546
|
+
* // Parameterized query (recommended for user input)
|
|
547
|
+
* const users = await client.query(
|
|
548
|
+
* 'SELECT * FROM users WHERE id = $1 AND age > $2',
|
|
549
|
+
* [42, 18]
|
|
550
|
+
* );
|
|
551
|
+
* console.log(users.results[0].rows);
|
|
552
|
+
*
|
|
553
|
+
* // INSERT with parameters
|
|
554
|
+
* await client.query(
|
|
555
|
+
* "INSERT INTO users (name, email) VALUES ($1, $2)",
|
|
556
|
+
* ['Alice', 'alice@example.com']
|
|
557
|
+
* );
|
|
558
|
+
*
|
|
559
|
+
* // DDL statements (no params)
|
|
560
|
+
* await client.query('CREATE TABLE products (id BIGINT PRIMARY KEY, name TEXT)');
|
|
561
|
+
* ```
|
|
562
|
+
*/
|
|
563
|
+
query(sql: string, params?: any[]): Promise<QueryResponse>;
|
|
564
|
+
/**
|
|
565
|
+
* Insert data into a table (convenience method)
|
|
566
|
+
*
|
|
567
|
+
* @param tableName - Name of the table (can include namespace, e.g., 'app.users')
|
|
568
|
+
* @param data - Object containing column values
|
|
569
|
+
* @returns Query response
|
|
570
|
+
*
|
|
571
|
+
* @throws Error if insert fails
|
|
572
|
+
*
|
|
573
|
+
* @example
|
|
574
|
+
* ```typescript
|
|
575
|
+
* await client.insert('todos', {
|
|
576
|
+
* title: 'Buy groceries',
|
|
577
|
+
* completed: false
|
|
578
|
+
* });
|
|
579
|
+
* ```
|
|
580
|
+
*/
|
|
581
|
+
insert(tableName: string, data: Record<string, any>): Promise<QueryResponse>;
|
|
582
|
+
/**
|
|
583
|
+
* Delete a row from a table (convenience method)
|
|
584
|
+
*
|
|
585
|
+
* @param tableName - Name of the table
|
|
586
|
+
* @param rowId - ID of the row to delete
|
|
587
|
+
*
|
|
588
|
+
* @throws Error if delete fails
|
|
589
|
+
*
|
|
590
|
+
* @example
|
|
591
|
+
* ```typescript
|
|
592
|
+
* await client.delete('todos', '123456789');
|
|
593
|
+
* ```
|
|
594
|
+
*/
|
|
595
|
+
delete(tableName: string, rowId: string | number): Promise<void>;
|
|
596
|
+
/**
|
|
597
|
+
* Subscribe to real-time changes in a table
|
|
598
|
+
*
|
|
599
|
+
* The callback will be invoked for:
|
|
600
|
+
* - Initial data batches (type: 'initial_data_batch')
|
|
601
|
+
* - Live changes (type: 'change')
|
|
602
|
+
* - Errors (type: 'error')
|
|
603
|
+
*
|
|
604
|
+
* Returns an unsubscribe function (Firebase/Supabase style) for easy cleanup.
|
|
605
|
+
*
|
|
606
|
+
* @param tableName - Name of the table to subscribe to
|
|
607
|
+
* @param callback - Function called when changes occur
|
|
608
|
+
* @param options - Optional subscription options (batch_size, last_rows, from_seq_id)
|
|
609
|
+
* @returns Unsubscribe function to stop receiving updates
|
|
610
|
+
*
|
|
611
|
+
* @throws Error if subscription fails or not connected
|
|
612
|
+
*
|
|
613
|
+
* @example
|
|
614
|
+
* ```typescript
|
|
615
|
+
* // Simple subscription
|
|
616
|
+
* const unsubscribe = await client.subscribe('messages', (event) => {
|
|
617
|
+
* if (event.type === 'change') {
|
|
618
|
+
* console.log('New data:', event.rows);
|
|
619
|
+
* }
|
|
620
|
+
* });
|
|
621
|
+
*
|
|
622
|
+
* // With options
|
|
623
|
+
* const unsubscribe = await client.subscribe('messages', callback, {
|
|
624
|
+
* batch_size: 100, // Load initial data in batches of 100
|
|
625
|
+
* last_rows: 50 // Only fetch last 50 rows initially
|
|
626
|
+
* });
|
|
627
|
+
*
|
|
628
|
+
* // Later: unsubscribe when done
|
|
629
|
+
* await unsubscribe();
|
|
630
|
+
* ```
|
|
631
|
+
*/
|
|
632
|
+
subscribe(tableName: string, callback: SubscriptionCallback, options?: SubscriptionOptions): Promise<Unsubscribe>;
|
|
633
|
+
/**
|
|
634
|
+
* Subscribe to a SQL query with real-time updates
|
|
635
|
+
*
|
|
636
|
+
* More flexible than subscribe() - allows custom SQL queries with WHERE clauses,
|
|
637
|
+
* JOINs, and other SQL features.
|
|
638
|
+
*
|
|
639
|
+
* @param sql - SQL SELECT query to subscribe to
|
|
640
|
+
* @param callback - Function called when changes occur
|
|
641
|
+
* @param options - Optional subscription options (batch_size, last_rows, from_seq_id)
|
|
642
|
+
* @returns Unsubscribe function to stop receiving updates
|
|
643
|
+
*
|
|
644
|
+
* @throws Error if subscription fails or not connected
|
|
645
|
+
*
|
|
646
|
+
* @example
|
|
647
|
+
* ```typescript
|
|
648
|
+
* // Subscribe to filtered query
|
|
649
|
+
* const unsubscribe = await client.subscribeWithSql(
|
|
650
|
+
* 'SELECT * FROM chat.messages WHERE conversation_id = 1',
|
|
651
|
+
* (event) => {
|
|
652
|
+
* if (event.type === 'change') {
|
|
653
|
+
* console.log('New message:', event.rows);
|
|
654
|
+
* }
|
|
655
|
+
* },
|
|
656
|
+
* { batch_size: 50, last_rows: 100 }
|
|
657
|
+
* );
|
|
658
|
+
*
|
|
659
|
+
* // Later: unsubscribe when done
|
|
660
|
+
* await unsubscribe();
|
|
661
|
+
* ```
|
|
662
|
+
*/
|
|
663
|
+
subscribeWithSql(sql: string, callback: SubscriptionCallback, options?: SubscriptionOptions): Promise<Unsubscribe>;
|
|
664
|
+
/**
|
|
665
|
+
* Unsubscribe from table changes
|
|
666
|
+
*
|
|
667
|
+
* @param subscriptionId - ID returned from subscribe()
|
|
668
|
+
*
|
|
669
|
+
* @throws Error if unsubscribe fails or not connected
|
|
670
|
+
*
|
|
671
|
+
* @example
|
|
672
|
+
* ```typescript
|
|
673
|
+
* // Using the returned unsubscribe function (preferred)
|
|
674
|
+
* const unsubscribe = await client.subscribe('messages', handleChange);
|
|
675
|
+
* await unsubscribe();
|
|
676
|
+
*
|
|
677
|
+
* // Or manually with subscription ID
|
|
678
|
+
* const unsubscribe = await client.subscribe('messages', handleChange);
|
|
679
|
+
* const subs = client.getSubscriptions();
|
|
680
|
+
* await client.unsubscribe(subs[0].id);
|
|
681
|
+
* ```
|
|
682
|
+
*/
|
|
683
|
+
unsubscribe(subscriptionId: string): Promise<void>;
|
|
684
|
+
/**
|
|
685
|
+
* Get the number of active subscriptions
|
|
686
|
+
*
|
|
687
|
+
* @returns Number of active subscriptions
|
|
688
|
+
*
|
|
689
|
+
* @example
|
|
690
|
+
* ```typescript
|
|
691
|
+
* console.log(`Active subscriptions: ${client.getSubscriptionCount()}`);
|
|
692
|
+
*
|
|
693
|
+
* // Prevent too many subscriptions
|
|
694
|
+
* if (client.getSubscriptionCount() >= 10) {
|
|
695
|
+
* console.warn('Too many subscriptions!');
|
|
696
|
+
* }
|
|
697
|
+
* ```
|
|
698
|
+
*/
|
|
699
|
+
getSubscriptionCount(): number;
|
|
700
|
+
/**
|
|
701
|
+
* Get information about all active subscriptions
|
|
702
|
+
*
|
|
703
|
+
* @returns Array of subscription info objects
|
|
704
|
+
*
|
|
705
|
+
* @example
|
|
706
|
+
* ```typescript
|
|
707
|
+
* const subs = client.getSubscriptions();
|
|
708
|
+
* for (const sub of subs) {
|
|
709
|
+
* console.log(`Subscribed to ${sub.tableName} since ${sub.createdAt}`);
|
|
710
|
+
* }
|
|
711
|
+
* ```
|
|
712
|
+
*/
|
|
713
|
+
getSubscriptions(): SubscriptionInfo[];
|
|
714
|
+
/**
|
|
715
|
+
* Check if subscribed to a specific table
|
|
716
|
+
*
|
|
717
|
+
* @param tableName - Name of the table to check
|
|
718
|
+
* @returns true if there's an active subscription to this table
|
|
719
|
+
*
|
|
720
|
+
* @example
|
|
721
|
+
* ```typescript
|
|
722
|
+
* if (!client.isSubscribedTo('messages')) {
|
|
723
|
+
* await client.subscribe('messages', handleChange);
|
|
724
|
+
* }
|
|
725
|
+
* ```
|
|
726
|
+
*/
|
|
727
|
+
isSubscribedTo(tableName: string): boolean;
|
|
728
|
+
/**
|
|
729
|
+
* Unsubscribe from all active subscriptions
|
|
730
|
+
*
|
|
731
|
+
* Useful for cleanup before disconnecting or switching contexts.
|
|
732
|
+
*
|
|
733
|
+
* @example
|
|
734
|
+
* ```typescript
|
|
735
|
+
* // Cleanup all subscriptions
|
|
736
|
+
* await client.unsubscribeAll();
|
|
737
|
+
* console.log(`Subscriptions remaining: ${client.getSubscriptionCount()}`); // 0
|
|
738
|
+
* ```
|
|
739
|
+
*/
|
|
740
|
+
unsubscribeAll(): Promise<void>;
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Create a KalamDB client with the given configuration
|
|
744
|
+
*
|
|
745
|
+
* Factory function that supports both the new type-safe auth API and legacy API.
|
|
746
|
+
*
|
|
747
|
+
* @param options - Client configuration with URL and authentication
|
|
748
|
+
* @returns Configured KalamDB client
|
|
749
|
+
*
|
|
750
|
+
* @example
|
|
751
|
+
* ```typescript
|
|
752
|
+
* import { createClient, Auth } from 'kalam-link';
|
|
753
|
+
*
|
|
754
|
+
* // New type-safe API (recommended)
|
|
755
|
+
* const client = createClient({
|
|
756
|
+
* url: 'http://localhost:8080',
|
|
757
|
+
* auth: Auth.basic('admin', 'admin')
|
|
758
|
+
* });
|
|
759
|
+
*
|
|
760
|
+
* // JWT authentication
|
|
761
|
+
* const jwtClient = createClient({
|
|
762
|
+
* url: 'http://localhost:8080',
|
|
763
|
+
* auth: Auth.jwt('eyJhbGciOiJIUzI1NiIs...')
|
|
764
|
+
* });
|
|
765
|
+
*
|
|
766
|
+
* // Anonymous (no authentication)
|
|
767
|
+
* const anonClient = createClient({
|
|
768
|
+
* url: 'http://localhost:8080',
|
|
769
|
+
* auth: Auth.none()
|
|
770
|
+
* });
|
|
771
|
+
*
|
|
772
|
+
* // Legacy API (deprecated but still works)
|
|
773
|
+
* const legacyClient = createClient({
|
|
774
|
+
* url: 'http://localhost:8080',
|
|
775
|
+
* username: 'admin',
|
|
776
|
+
* password: 'admin'
|
|
777
|
+
* });
|
|
778
|
+
* ```
|
|
779
|
+
*/
|
|
780
|
+
export declare function createClient(options: ClientOptions): KalamDBClient;
|
|
781
|
+
export default KalamDBClient;
|