lakesync 0.1.8 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/adapter-types-DwsQGQS4.d.ts +94 -0
  2. package/dist/adapter.d.ts +23 -49
  3. package/dist/adapter.js +9 -4
  4. package/dist/analyst.js +1 -1
  5. package/dist/{base-poller-Bj9kX9dv.d.ts → base-poller-Y7ORYgUv.d.ts} +2 -0
  6. package/dist/catalogue.js +2 -2
  7. package/dist/{chunk-LDFFCG2K.js → chunk-4SG66H5K.js} +44 -31
  8. package/dist/chunk-4SG66H5K.js.map +1 -0
  9. package/dist/{chunk-LPWXOYNS.js → chunk-C4KD6YKP.js} +59 -43
  10. package/dist/chunk-C4KD6YKP.js.map +1 -0
  11. package/dist/{chunk-JI4C4R5H.js → chunk-FIIHPQMQ.js} +196 -118
  12. package/dist/chunk-FIIHPQMQ.js.map +1 -0
  13. package/dist/{chunk-TMLG32QV.js → chunk-U2NV4DUX.js} +2 -2
  14. package/dist/{chunk-QNITY4F6.js → chunk-XVP5DJJ7.js} +16 -13
  15. package/dist/{chunk-QNITY4F6.js.map → chunk-XVP5DJJ7.js.map} +1 -1
  16. package/dist/{chunk-KVSWLIJR.js → chunk-YHYBLU6W.js} +2 -2
  17. package/dist/{chunk-PYRS74YP.js → chunk-ZNY4DSFU.js} +16 -13
  18. package/dist/{chunk-PYRS74YP.js.map → chunk-ZNY4DSFU.js.map} +1 -1
  19. package/dist/{chunk-SSICS5KI.js → chunk-ZU7RC7CT.js} +2 -2
  20. package/dist/client.d.ts +28 -10
  21. package/dist/client.js +150 -29
  22. package/dist/client.js.map +1 -1
  23. package/dist/compactor.d.ts +1 -1
  24. package/dist/compactor.js +3 -3
  25. package/dist/connector-jira.d.ts +13 -3
  26. package/dist/connector-jira.js +6 -2
  27. package/dist/connector-salesforce.d.ts +13 -3
  28. package/dist/connector-salesforce.js +6 -2
  29. package/dist/{coordinator-NXy6tA0h.d.ts → coordinator-eGmZMnJ_.d.ts} +99 -16
  30. package/dist/create-poller-Cc2MGfhh.d.ts +55 -0
  31. package/dist/factory-DFfR-030.d.ts +33 -0
  32. package/dist/gateway-server.d.ts +398 -95
  33. package/dist/gateway-server.js +743 -56
  34. package/dist/gateway-server.js.map +1 -1
  35. package/dist/gateway.d.ts +14 -8
  36. package/dist/gateway.js +6 -5
  37. package/dist/index.d.ts +45 -73
  38. package/dist/index.js +5 -3
  39. package/dist/parquet.js +2 -2
  40. package/dist/proto.js +2 -2
  41. package/dist/react.d.ts +3 -3
  42. package/dist/{registry-BcspAtZI.d.ts → registry-Dd8JuW8T.d.ts} +1 -1
  43. package/dist/{request-handler-pUvL7ozF.d.ts → request-handler-B1I5xDOx.d.ts} +71 -27
  44. package/dist/{src-ROW4XLO7.js → src-WU7IBVC4.js} +6 -4
  45. package/dist/{types-BrcD1oJg.d.ts → types-D2C9jTbL.d.ts} +33 -23
  46. package/package.json +1 -1
  47. package/dist/auth-CAVutXzx.d.ts +0 -30
  48. package/dist/chunk-JI4C4R5H.js.map +0 -1
  49. package/dist/chunk-LDFFCG2K.js.map +0 -1
  50. package/dist/chunk-LPWXOYNS.js.map +0 -1
  51. package/dist/db-types-CfLMUBfW.d.ts +0 -29
  52. package/dist/src-B6NLV3FP.js +0 -27
  53. package/dist/src-ROW4XLO7.js.map +0 -1
  54. package/dist/src-ZRHKG42A.js +0 -25
  55. package/dist/src-ZRHKG42A.js.map +0 -1
  56. package/dist/types-DSC_EiwR.d.ts +0 -45
  57. /package/dist/{chunk-TMLG32QV.js.map → chunk-U2NV4DUX.js.map} +0 -0
  58. /package/dist/{chunk-KVSWLIJR.js.map → chunk-YHYBLU6W.js.map} +0 -0
  59. /package/dist/{chunk-SSICS5KI.js.map → chunk-ZU7RC7CT.js.map} +0 -0
  60. /package/dist/{src-B6NLV3FP.js.map → src-WU7IBVC4.js.map} +0 -0
@@ -1,15 +1,15 @@
1
- import { A as AuthClaims } from './auth-CAVutXzx.js';
2
- export { a as AuthError, v as verifyToken } from './auth-CAVutXzx.js';
1
+ import { A as AuthClaims, b as PollerRegistry } from './create-poller-Cc2MGfhh.js';
2
+ export { a as AuthError, v as verifyToken } from './create-poller-Cc2MGfhh.js';
3
3
  import { IncomingMessage, ServerResponse, Server } from 'node:http';
4
- import { D as DatabaseAdapter } from './db-types-CfLMUBfW.js';
5
- import { C as ConfigStore, d as SyncGateway, c as HandlerResult } from './request-handler-pUvL7ozF.js';
4
+ import { D as DatabaseAdapter, L as LakeAdapter } from './adapter-types-DwsQGQS4.js';
5
+ import { a as AdapterFactoryRegistry } from './factory-DFfR-030.js';
6
+ import { b as ConfigStore, g as SyncGateway, d as HandlerResult } from './request-handler-B1I5xDOx.js';
6
7
  import { R as RowDelta, f as SyncResponse } from './types-BdGBv2ba.js';
7
- import { L as LakeAdapter } from './types-DSC_EiwR.js';
8
- import { H as HLCTimestamp } from './result-CojzlFE2.js';
9
- import './types-Bs-QyOe-.js';
10
- import './types-BrcD1oJg.js';
11
- import './base-poller-Bj9kX9dv.js';
8
+ import { R as Result, H as HLCTimestamp } from './result-CojzlFE2.js';
9
+ import './base-poller-Y7ORYgUv.js';
12
10
  import './hlc-DiD8QNG3.js';
11
+ import './types-D2C9jTbL.js';
12
+ import './types-Bs-QyOe-.js';
13
13
  import './nessie-client-DrNikVXy.js';
14
14
 
15
15
  /** Result of authentication: either authenticated claims or an error. */
@@ -78,23 +78,82 @@ declare class AdapterBasedLock implements DistributedLock {
78
78
  private makeHlc;
79
79
  }
80
80
 
81
+ /**
82
+ * Persistence interface for buffering unflushed deltas across restarts.
83
+ *
84
+ * Implementations must be synchronous (no async) to avoid race conditions
85
+ * during the push-then-flush cycle.
86
+ */
87
+ interface DeltaPersistence {
88
+ /** Append a batch of deltas to the persistence store. */
89
+ appendBatch(deltas: RowDelta[]): void;
90
+ /** Load all persisted deltas. */
91
+ loadAll(): RowDelta[];
92
+ /** Clear all persisted deltas (after successful flush). */
93
+ clear(): void;
94
+ /** Release resources. */
95
+ close(): void;
96
+ /** Persist the cursor state for a connector. */
97
+ saveCursor(connectorName: string, cursor: string): void;
98
+ /** Load the persisted cursor state for a connector, or null if none exists. */
99
+ loadCursor(connectorName: string): string | null;
100
+ }
101
+ /**
102
+ * In-memory persistence (no durability across restarts).
103
+ * Used as the default when `persistence` is "memory".
104
+ */
105
+ declare class MemoryPersistence implements DeltaPersistence {
106
+ private buffer;
107
+ private cursors;
108
+ appendBatch(deltas: RowDelta[]): void;
109
+ loadAll(): RowDelta[];
110
+ clear(): void;
111
+ close(): void;
112
+ saveCursor(connectorName: string, cursor: string): void;
113
+ loadCursor(connectorName: string): string | null;
114
+ }
115
+ /**
116
+ * SQLite-backed persistence using `better-sqlite3`.
117
+ *
118
+ * Stores deltas as JSON rows in a single table. On startup, loads all
119
+ * rows back as RowDeltas. On flush success, truncates the table.
120
+ */
121
+ declare class SqlitePersistence implements DeltaPersistence {
122
+ private db;
123
+ constructor(path: string);
124
+ appendBatch(deltas: RowDelta[]): void;
125
+ loadAll(): RowDelta[];
126
+ clear(): void;
127
+ saveCursor(connectorName: string, cursor: string): void;
128
+ loadCursor(connectorName: string): string | null;
129
+ close(): void;
130
+ }
131
+
81
132
  /**
82
133
  * Manages connector registration, adapter creation, and poller lifecycle.
83
134
  *
84
- * Encapsulates the if/else chains for different connector types and
85
- * handles clean-up on unregistration.
135
+ * Uses {@link PollerRegistry} and {@link AdapterFactoryRegistry} for
136
+ * dispatch no if/else chains for specific connector types.
86
137
  */
87
138
  declare class ConnectorManager {
88
139
  private readonly configStore;
89
140
  private readonly gateway;
90
141
  private readonly adapters;
91
142
  private readonly pollers;
92
- constructor(configStore: ConfigStore, gateway: SyncGateway);
143
+ private readonly pollerRegistry;
144
+ private readonly adapterRegistry;
145
+ private readonly persistence;
146
+ constructor(configStore: ConfigStore, gateway: SyncGateway, options?: {
147
+ pollerRegistry?: PollerRegistry;
148
+ adapterRegistry?: AdapterFactoryRegistry;
149
+ persistence?: DeltaPersistence;
150
+ });
93
151
  /**
94
152
  * Register a connector from raw JSON body.
95
153
  *
96
- * Validates via shared handler, creates adapter/poller as appropriate,
97
- * registers with the gateway.
154
+ * Validates via shared handler, then dispatches to the appropriate
155
+ * registry: poller registry for API-based connectors, adapter registry
156
+ * for database-based connectors.
98
157
  */
99
158
  register(raw: string): Promise<HandlerResult>;
100
159
  /**
@@ -183,6 +242,8 @@ declare class SourcePoller {
183
242
  private cursorStates;
184
243
  /** Diff snapshot per table (keyed by table name). */
185
244
  private diffStates;
245
+ /** Optional callback invoked after each poll with the current cursor state. */
246
+ onCursorUpdate?: (state: Record<string, unknown>) => void;
186
247
  constructor(config: IngestSourceConfig, gateway: SyncGateway);
187
248
  /** Start the polling loop. */
188
249
  start(): void;
@@ -191,52 +252,205 @@ declare class SourcePoller {
191
252
  /** Whether the poller is currently running. */
192
253
  get isRunning(): boolean;
193
254
  private schedulePoll;
255
+ /** Export cursor state as a JSON-serialisable object for external persistence. */
256
+ getCursorState(): Record<string, unknown>;
257
+ /** Restore cursor state from a previously exported snapshot. */
258
+ setCursorState(state: Record<string, unknown>): void;
194
259
  /** Execute a single poll cycle across all configured tables. */
195
260
  poll(): Promise<void>;
196
261
  private pollCursor;
197
262
  private pollDiff;
198
263
  }
199
264
 
265
+ /** Supported log levels, ordered by severity. */
266
+ type LogLevel = "debug" | "info" | "warn" | "error";
267
+ /** A single structured log entry. */
268
+ interface LogEntry {
269
+ level: LogLevel;
270
+ msg: string;
271
+ ts: string;
272
+ [key: string]: unknown;
273
+ }
200
274
  /**
201
- * Persistence interface for buffering unflushed deltas across restarts.
275
+ * Minimal structured logger that outputs JSON lines to stdout.
202
276
  *
203
- * Implementations must be synchronous (no async) to avoid race conditions
204
- * during the push-then-flush cycle.
277
+ * Supports log-level filtering and child loggers with bound context.
278
+ * No external dependencies — compatible with any log aggregator that
279
+ * consumes JSON lines.
280
+ *
281
+ * @example
282
+ * ```ts
283
+ * const logger = new Logger("info");
284
+ * const reqLogger = logger.child({ requestId: "abc-123" });
285
+ * reqLogger.info("push received", { deltas: 5 });
286
+ * // => {"level":"info","msg":"push received","ts":"...","requestId":"abc-123","deltas":5}
287
+ * ```
205
288
  */
206
- interface DeltaPersistence {
207
- /** Append a batch of deltas to the persistence store. */
208
- appendBatch(deltas: RowDelta[]): void;
209
- /** Load all persisted deltas. */
210
- loadAll(): RowDelta[];
211
- /** Clear all persisted deltas (after successful flush). */
212
- clear(): void;
213
- /** Release resources. */
214
- close(): void;
289
+ declare class Logger {
290
+ private readonly minLevelValue;
291
+ private readonly bindings;
292
+ /** Output function defaults to stdout, overridable for testing. */
293
+ private readonly writeFn;
294
+ constructor(minLevel?: LogLevel, bindings?: Record<string, unknown>, writeFn?: (line: string) => void);
295
+ /** Log at debug level. */
296
+ debug(msg: string, data?: Record<string, unknown>): void;
297
+ /** Log at info level. */
298
+ info(msg: string, data?: Record<string, unknown>): void;
299
+ /** Log at warn level. */
300
+ warn(msg: string, data?: Record<string, unknown>): void;
301
+ /** Log at error level. */
302
+ error(msg: string, data?: Record<string, unknown>): void;
303
+ /**
304
+ * Create a child logger with additional bound context.
305
+ *
306
+ * The child inherits the parent's level and write function, plus
307
+ * merges any parent bindings with the new ones.
308
+ */
309
+ child(bindings: Record<string, unknown>): Logger;
310
+ private log;
311
+ private minLevelName;
215
312
  }
313
+
314
+ /** Label set for a metric observation. */
315
+ type Labels = Record<string, string>;
216
316
  /**
217
- * In-memory persistence (no durability across restarts).
218
- * Used as the default when `persistence` is "memory".
317
+ * Monotonically increasing counter.
318
+ *
319
+ * @example
320
+ * ```ts
321
+ * const pushTotal = new Counter("lakesync_push_total", "Total push requests");
322
+ * pushTotal.inc({ status: "ok" });
323
+ * ```
219
324
  */
220
- declare class MemoryPersistence implements DeltaPersistence {
221
- private buffer;
222
- appendBatch(deltas: RowDelta[]): void;
223
- loadAll(): RowDelta[];
224
- clear(): void;
225
- close(): void;
325
+ declare class Counter {
326
+ readonly name: string;
327
+ readonly help: string;
328
+ private readonly values;
329
+ constructor(name: string, help: string);
330
+ /** Increment the counter by `n` (default 1). */
331
+ inc(labels?: Labels, n?: number): void;
332
+ /** Return the current value for the given labels. */
333
+ get(labels?: Labels): number;
334
+ /** Reset all values. */
335
+ reset(): void;
336
+ /** Serialise to Prometheus text exposition format. */
337
+ expose(): string;
226
338
  }
227
339
  /**
228
- * SQLite-backed persistence using `better-sqlite3`.
340
+ * Gauge that can go up and down.
229
341
  *
230
- * Stores deltas as JSON rows in a single table. On startup, loads all
231
- * rows back as RowDeltas. On flush success, truncates the table.
342
+ * @example
343
+ * ```ts
344
+ * const bufferBytes = new Gauge("lakesync_buffer_bytes", "Buffer size in bytes");
345
+ * bufferBytes.set({}, 1024);
346
+ * ```
232
347
  */
233
- declare class SqlitePersistence implements DeltaPersistence {
234
- private db;
235
- constructor(path: string);
236
- appendBatch(deltas: RowDelta[]): void;
237
- loadAll(): RowDelta[];
238
- clear(): void;
239
- close(): void;
348
+ declare class Gauge {
349
+ readonly name: string;
350
+ readonly help: string;
351
+ private readonly values;
352
+ constructor(name: string, help: string);
353
+ /** Set to an absolute value. */
354
+ set(labels?: Labels, value?: number): void;
355
+ /** Increment by `n` (default 1). */
356
+ inc(labels?: Labels, n?: number): void;
357
+ /** Decrement by `n` (default 1). */
358
+ dec(labels?: Labels, n?: number): void;
359
+ /** Return the current value for the given labels. */
360
+ get(labels?: Labels): number;
361
+ /** Reset all values. */
362
+ reset(): void;
363
+ /** Serialise to Prometheus text exposition format. */
364
+ expose(): string;
365
+ }
366
+ /**
367
+ * Histogram with configurable buckets.
368
+ *
369
+ * @example
370
+ * ```ts
371
+ * const latency = new Histogram(
372
+ * "lakesync_push_latency_ms",
373
+ * "Push latency in ms",
374
+ * [1, 5, 10, 50, 100, 500],
375
+ * );
376
+ * latency.observe({}, 42);
377
+ * ```
378
+ */
379
+ declare class Histogram {
380
+ readonly name: string;
381
+ readonly help: string;
382
+ readonly buckets: number[];
383
+ private readonly data;
384
+ constructor(name: string, help: string, buckets: number[]);
385
+ /** Record an observation. */
386
+ observe(labels?: Labels, value?: number): void;
387
+ /** Return the count of observations for the given labels. */
388
+ getCount(labels?: Labels): number;
389
+ /** Return the sum of observations for the given labels. */
390
+ getSum(labels?: Labels): number;
391
+ /** Reset all values. */
392
+ reset(): void;
393
+ /** Serialise to Prometheus text exposition format. */
394
+ expose(): string;
395
+ }
396
+ /**
397
+ * Pre-configured metrics registry for the gateway server.
398
+ *
399
+ * Exposes all standard lakesync metrics and a single `expose()` method
400
+ * that returns the complete Prometheus text exposition payload.
401
+ */
402
+ declare class MetricsRegistry {
403
+ readonly pushTotal: Counter;
404
+ readonly pullTotal: Counter;
405
+ readonly flushTotal: Counter;
406
+ readonly flushDuration: Histogram;
407
+ readonly pushLatency: Histogram;
408
+ readonly bufferBytes: Gauge;
409
+ readonly bufferDeltas: Gauge;
410
+ readonly wsConnections: Gauge;
411
+ readonly activeRequests: Gauge;
412
+ /** Return the full Prometheus text exposition payload. */
413
+ expose(): string;
414
+ /** Reset all metrics. */
415
+ reset(): void;
416
+ }
417
+
418
+ /** Configuration for the per-client rate limiter. */
419
+ interface RateLimiterConfig {
420
+ /** Maximum requests per window (default: 100). */
421
+ maxRequests?: number;
422
+ /** Window size in milliseconds (default: 60_000). */
423
+ windowMs?: number;
424
+ }
425
+ /**
426
+ * Fixed-window per-client rate limiter.
427
+ *
428
+ * Tracks request counts per client within a sliding window. Stale entries
429
+ * are periodically cleaned up to prevent unbounded memory growth.
430
+ */
431
+ declare class RateLimiter {
432
+ private readonly maxRequests;
433
+ private readonly windowMs;
434
+ private readonly clients;
435
+ private cleanupTimer;
436
+ constructor(config?: RateLimiterConfig);
437
+ /**
438
+ * Attempt to consume one request token for the given client.
439
+ *
440
+ * @returns `true` if the request is allowed, `false` if rate-limited.
441
+ */
442
+ tryConsume(clientId: string): boolean;
443
+ /**
444
+ * Calculate the number of seconds until the current window resets
445
+ * for a given client. Used for the Retry-After header.
446
+ */
447
+ retryAfterSeconds(clientId: string): number;
448
+ /** Remove all tracked clients and reset state. */
449
+ reset(): void;
450
+ /** Stop the periodic cleanup timer. */
451
+ dispose(): void;
452
+ /** Remove stale entries whose window has expired. */
453
+ private cleanup;
240
454
  }
241
455
 
242
456
  /** Matched route information. */
@@ -253,6 +467,96 @@ interface RouteMatch {
253
467
  */
254
468
  declare function matchRoute(pathname: string, method: string): RouteMatch | null;
255
469
 
470
+ /** Consistency mode for shared buffer writes. */
471
+ type ConsistencyMode = "eventual" | "strong";
472
+ /** Configuration for SharedBuffer. */
473
+ interface SharedBufferConfig {
474
+ /**
475
+ * Controls how shared adapter write failures are handled.
476
+ *
477
+ * - `"eventual"` (default): Shared writes are best-effort. Failures are
478
+ * logged but do not fail the push. Local buffer remains authoritative.
479
+ * - `"strong"`: Shared writes must succeed. Failures are returned as errors,
480
+ * allowing the caller to decide whether to fail the push.
481
+ */
482
+ consistencyMode?: ConsistencyMode;
483
+ }
484
+ /** Error returned by SharedBuffer in strong consistency mode. */
485
+ interface SharedBufferError {
486
+ code: "SHARED_WRITE_FAILED";
487
+ message: string;
488
+ }
489
+ /**
490
+ * Write-through buffer that pushes to both the in-memory gateway buffer
491
+ * and a shared database adapter for cross-instance visibility.
492
+ *
493
+ * Pull merges in-memory buffer results with adapter query results,
494
+ * deduplicating by deltaId.
495
+ */
496
+ declare class SharedBuffer {
497
+ private readonly sharedAdapter;
498
+ private readonly consistencyMode;
499
+ constructor(sharedAdapter: DatabaseAdapter, config?: SharedBufferConfig);
500
+ /**
501
+ * Write-through push: write to shared adapter for cross-instance visibility.
502
+ *
503
+ * In "eventual" mode (default), failures are logged but do not fail the push.
504
+ * In "strong" mode, failures are returned as errors.
505
+ */
506
+ writeThroughPush(deltas: RowDelta[]): Promise<Result<void, SharedBufferError>>;
507
+ /**
508
+ * Merge pull: combine local buffer results with shared adapter results.
509
+ *
510
+ * Deduplicates by deltaId to avoid returning the same delta twice.
511
+ */
512
+ mergePull(localResult: SyncResponse, sinceHlc: HLCTimestamp): Promise<SyncResponse>;
513
+ }
514
+
515
+ /** Configuration for WebSocket connection and message rate limits. */
516
+ interface WebSocketLimitsConfig {
517
+ /** Maximum concurrent WebSocket connections (default: 1000). */
518
+ maxConnections?: number;
519
+ /** Maximum messages per second per client (default: 50). */
520
+ maxMessagesPerSecond?: number;
521
+ }
522
+ /**
523
+ * Manages WebSocket connections, message handling, and broadcasting.
524
+ *
525
+ * Decouples the WebSocket protocol from the HTTP server lifecycle.
526
+ */
527
+ declare class WebSocketManager {
528
+ private readonly gateway;
529
+ private readonly configStore;
530
+ private readonly gatewayId;
531
+ private readonly jwtSecret;
532
+ private readonly wss;
533
+ private readonly clients;
534
+ private readonly maxConnections;
535
+ private readonly maxMessagesPerSecond;
536
+ private readonly messageRates;
537
+ private rateResetTimer;
538
+ constructor(gateway: SyncGateway, configStore: ConfigStore, gatewayId: string, jwtSecret: string | undefined, limits?: WebSocketLimitsConfig);
539
+ /** The current number of connected clients. */
540
+ get connectionCount(): number;
541
+ /** Attach upgrade listener to an HTTP server. */
542
+ attach(httpServer: Server): void;
543
+ /**
544
+ * Broadcast ingested deltas to all connected WebSocket clients except the sender.
545
+ */
546
+ broadcastDeltas(deltas: RowDelta[], serverHlc: HLCTimestamp, excludeClientId: string): void;
547
+ /** Close all connections and shut down the WebSocket server. */
548
+ close(): void;
549
+ private handleUpgrade;
550
+ /**
551
+ * Check and increment the message rate for a client.
552
+ * @returns `true` if the message is allowed, `false` if rate-limited.
553
+ */
554
+ private checkMessageRate;
555
+ private handleMessage;
556
+ private buildSyncRulesContext;
557
+ private broadcastDeltasAsync;
558
+ }
559
+
256
560
  /** Configuration for the self-hosted gateway server. */
257
561
  interface GatewayServerConfig {
258
562
  /** Port to listen on (default 3000). */
@@ -283,7 +587,27 @@ interface GatewayServerConfig {
283
587
  lock: DistributedLock;
284
588
  /** Shared database adapter for cross-instance visibility. */
285
589
  sharedAdapter: DatabaseAdapter;
590
+ /** Shared buffer configuration (consistency mode, etc.). */
591
+ sharedBufferConfig?: SharedBufferConfig;
286
592
  };
593
+ /** Custom poller registry for connector pollers. Defaults to Jira + Salesforce. */
594
+ pollerRegistry?: PollerRegistry;
595
+ /** Custom adapter factory registry. Defaults to Postgres, MySQL, BigQuery. */
596
+ adapterRegistry?: AdapterFactoryRegistry;
597
+ /** Drain timeout in milliseconds for graceful shutdown (default 10s). */
598
+ drainTimeoutMs?: number;
599
+ /** Request timeout in milliseconds (default 30s). Aborts with 504 on timeout. */
600
+ requestTimeoutMs?: number;
601
+ /** Flush timeout in milliseconds for periodic flushes (default 60s). */
602
+ flushTimeoutMs?: number;
603
+ /** Per-client rate limiter configuration. When provided, rate limiting is enabled. */
604
+ rateLimiter?: RateLimiterConfig;
605
+ /** WebSocket connection and message rate limits. */
606
+ wsLimits?: WebSocketLimitsConfig;
607
+ /** Minimum log level for the structured logger (default "info"). */
608
+ logLevel?: LogLevel;
609
+ /** Whether to enable the Prometheus metrics endpoint at GET /metrics (default true). */
610
+ enableMetrics?: boolean;
287
611
  }
288
612
  /**
289
613
  * Self-hosted HTTP gateway server wrapping {@link SyncGateway}.
@@ -310,11 +634,20 @@ declare class GatewayServer {
310
634
  private readonly persistence;
311
635
  private readonly connectors;
312
636
  private readonly sharedBuffer;
637
+ private readonly rateLimiter;
638
+ private readonly logger;
639
+ private readonly metrics;
313
640
  private httpServer;
314
641
  private wsManager;
315
642
  private flushTimer;
316
643
  private resolvedPort;
317
644
  private pollers;
645
+ /** Whether the server is draining (rejecting new requests during shutdown). */
646
+ private draining;
647
+ /** Number of in-flight requests currently being handled. */
648
+ private activeRequests;
649
+ /** Signal handler cleanup functions. */
650
+ private signalCleanup;
318
651
  constructor(config: GatewayServerConfig);
319
652
  /**
320
653
  * Start the HTTP server and periodic flush timer.
@@ -326,11 +659,17 @@ declare class GatewayServer {
326
659
  start(): Promise<void>;
327
660
  /** Stop the server, pollers, connectors, and WebSocket connections. */
328
661
  stop(): Promise<void>;
662
+ /** Whether the server is currently draining connections. */
663
+ get isDraining(): boolean;
329
664
  /** The port the server is listening on (available after start). */
330
665
  get port(): number;
331
666
  /** The underlying SyncGateway instance for direct access. */
332
667
  get gatewayInstance(): SyncGateway;
668
+ /** The Prometheus metrics registry. */
669
+ get metricsRegistry(): MetricsRegistry;
333
670
  private handleRequest;
671
+ /** Dispatch an authenticated request to the correct route handler. */
672
+ private dispatchRoute;
334
673
  private handlePush;
335
674
  private handlePull;
336
675
  private handleAction;
@@ -342,59 +681,23 @@ declare class GatewayServer {
342
681
  private handleUnregisterConnectorRoute;
343
682
  private handleListConnectorsRoute;
344
683
  private handleMetricsRoute;
345
- private periodicFlush;
346
- }
347
-
348
- /**
349
- * Write-through buffer that pushes to both the in-memory gateway buffer
350
- * and a shared database adapter for cross-instance visibility.
351
- *
352
- * Pull merges in-memory buffer results with adapter query results,
353
- * deduplicating by deltaId.
354
- */
355
- declare class SharedBuffer {
356
- private readonly sharedAdapter;
357
- constructor(sharedAdapter: DatabaseAdapter);
684
+ /** Synchronise buffer gauge metrics with the current buffer state. */
685
+ private updateBufferGauges;
686
+ /** Handle GET /ready — checks draining status and adapter health. */
687
+ private handleReady;
358
688
  /**
359
- * Write-through push: write to shared adapter for cross-instance visibility.
689
+ * Check whether the configured adapter is reachable.
360
690
  *
361
- * Gateway buffer handles fast reads; shared adapter handles
362
- * cross-instance visibility and durability.
363
- */
364
- writeThroughPush(deltas: RowDelta[]): Promise<void>;
365
- /**
366
- * Merge pull: combine local buffer results with shared adapter results.
367
- *
368
- * Deduplicates by deltaId to avoid returning the same delta twice.
369
- */
370
- mergePull(localResult: SyncResponse, sinceHlc: HLCTimestamp): Promise<SyncResponse>;
371
- }
372
-
373
- /**
374
- * Manages WebSocket connections, message handling, and broadcasting.
375
- *
376
- * Decouples the WebSocket protocol from the HTTP server lifecycle.
377
- */
378
- declare class WebSocketManager {
379
- private readonly gateway;
380
- private readonly configStore;
381
- private readonly gatewayId;
382
- private readonly jwtSecret;
383
- private readonly wss;
384
- private readonly clients;
385
- constructor(gateway: SyncGateway, configStore: ConfigStore, gatewayId: string, jwtSecret: string | undefined);
386
- /** Attach upgrade listener to an HTTP server. */
387
- attach(httpServer: Server): void;
388
- /**
389
- * Broadcast ingested deltas to all connected WebSocket clients except the sender.
691
+ * For a DatabaseAdapter, attempts a lightweight query with a timeout.
692
+ * For a LakeAdapter, attempts a headObject call (404 still means reachable).
693
+ * Returns true when no adapter is configured (stateless mode).
390
694
  */
391
- broadcastDeltas(deltas: RowDelta[], serverHlc: HLCTimestamp, excludeClientId: string): void;
392
- /** Close all connections and shut down the WebSocket server. */
393
- close(): void;
394
- private handleUpgrade;
395
- private handleMessage;
396
- private buildSyncRulesContext;
397
- private broadcastDeltasAsync;
695
+ private checkAdapterHealth;
696
+ /** Register SIGTERM/SIGINT handlers for graceful shutdown. */
697
+ private setupSignalHandlers;
698
+ /** Graceful shutdown: stop accepting, drain, flush, exit. */
699
+ private gracefulShutdown;
700
+ private periodicFlush;
398
701
  }
399
702
 
400
- export { AdapterBasedLock, AuthClaims, type AuthResult, ConnectorManager, type CorsConfig, type CursorStrategy, type DeltaPersistence, type DiffStrategy, type DistributedLock, GatewayServer, type GatewayServerConfig, type IngestSourceConfig, type IngestTableConfig, MemoryPersistence, type QueryFn, type RouteMatch, SharedBuffer, SourcePoller, SqlitePersistence, WebSocketManager, authenticateRequest, corsHeaders, extractBearerToken, handlePreflight, matchRoute };
703
+ export { AdapterBasedLock, AuthClaims, type AuthResult, ConnectorManager, type ConsistencyMode, type CorsConfig, Counter, type CursorStrategy, type DeltaPersistence, type DiffStrategy, type DistributedLock, GatewayServer, type GatewayServerConfig, Gauge, Histogram, type IngestSourceConfig, type IngestTableConfig, type Labels, type LogEntry, type LogLevel, Logger, MemoryPersistence, MetricsRegistry, type QueryFn, RateLimiter, type RateLimiterConfig, type RouteMatch, SharedBuffer, type SharedBufferConfig, type SharedBufferError, SourcePoller, SqlitePersistence, type WebSocketLimitsConfig, WebSocketManager, authenticateRequest, corsHeaders, extractBearerToken, handlePreflight, matchRoute };