@topgunbuild/server 0.3.0 → 0.5.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.
package/dist/index.d.mts CHANGED
@@ -1,6 +1,7 @@
1
- import { Timestamp, LWWRecord, ORMapRecord, Principal, PermissionPolicy, ConsistencyLevel, ReplicationConfig, LWWMap, ORMap, PermissionType, MigrationConfig, MigrationStatus, MigrationMetrics, PartitionMap, PartitionInfo, PartitionChange, ReplicationLag, ReplicationHealth, ReplicationResult } from '@topgunbuild/core';
1
+ import * as _topgunbuild_core from '@topgunbuild/core';
2
+ import { Timestamp, LWWRecord, ORMapRecord, Principal, EventJournalImpl, EventJournalConfig, JournalEvent, PermissionPolicy, ConsistencyLevel, ReplicationConfig, LWWMap, ORMap, PermissionType, MigrationConfig, MigrationStatus, MigrationMetrics, PartitionMap, PartitionInfo, PartitionChange, ReplicationLag, ReplicationHealth, ReplicationResult, EntryProcessorDef, EntryProcessorResult, HLC, MergeRejection, ConflictResolverDef, MergeContext, MergeResult, IndexedLWWMap, IndexedORMap } from '@topgunbuild/core';
2
3
  import { WebSocket } from 'ws';
3
- import { PoolConfig, Pool } from 'pg';
4
+ import { Pool, PoolConfig } from 'pg';
4
5
  import pino from 'pino';
5
6
  import { EventEmitter } from 'events';
6
7
 
@@ -1671,6 +1672,116 @@ type CoalescingPreset = keyof typeof coalescingPresets;
1671
1672
  */
1672
1673
  declare function getCoalescingPreset(preset: CoalescingPreset): CoalescingWriterOptions;
1673
1674
 
1675
+ /**
1676
+ * Export options for streaming journal events.
1677
+ */
1678
+ interface ExportOptions {
1679
+ /** Start from this sequence (inclusive) */
1680
+ fromSequence?: bigint;
1681
+ /** End at this sequence (inclusive) */
1682
+ toSequence?: bigint;
1683
+ /** Filter by map name */
1684
+ mapName?: string;
1685
+ /** Filter by event types */
1686
+ types?: ('PUT' | 'UPDATE' | 'DELETE')[];
1687
+ }
1688
+ /**
1689
+ * Configuration for EventJournalService.
1690
+ */
1691
+ interface EventJournalServiceConfig extends EventJournalConfig {
1692
+ /** PostgreSQL connection pool */
1693
+ pool: Pool;
1694
+ /** Table name for journal storage */
1695
+ tableName?: string;
1696
+ /** Batch size for persistence */
1697
+ persistBatchSize?: number;
1698
+ /** Interval for periodic persistence (ms) */
1699
+ persistIntervalMs?: number;
1700
+ }
1701
+ /**
1702
+ * Default configuration for EventJournalService.
1703
+ */
1704
+ declare const DEFAULT_JOURNAL_SERVICE_CONFIG: Omit<EventJournalServiceConfig, 'pool'>;
1705
+ /**
1706
+ * Server-side Event Journal Service with PostgreSQL persistence.
1707
+ * Extends EventJournalImpl to add durable storage.
1708
+ */
1709
+ declare class EventJournalService extends EventJournalImpl {
1710
+ private readonly pool;
1711
+ private readonly tableName;
1712
+ private readonly persistBatchSize;
1713
+ private readonly persistIntervalMs;
1714
+ private pendingPersist;
1715
+ private persistTimer?;
1716
+ private isPersisting;
1717
+ private isInitialized;
1718
+ private isLoadingFromStorage;
1719
+ constructor(config: EventJournalServiceConfig);
1720
+ /**
1721
+ * Initialize the journal service, creating table if needed.
1722
+ */
1723
+ initialize(): Promise<void>;
1724
+ /**
1725
+ * Persist pending events to PostgreSQL.
1726
+ */
1727
+ persistToStorage(): Promise<void>;
1728
+ /**
1729
+ * Load journal events from PostgreSQL on startup.
1730
+ */
1731
+ loadFromStorage(): Promise<void>;
1732
+ /**
1733
+ * Export events as NDJSON stream.
1734
+ */
1735
+ exportStream(options?: ExportOptions): ReadableStream<string>;
1736
+ /**
1737
+ * Get events for a specific map.
1738
+ */
1739
+ getMapEvents(mapName: string, fromSeq?: bigint): JournalEvent[];
1740
+ /**
1741
+ * Query events from PostgreSQL with filters.
1742
+ */
1743
+ queryFromStorage(options?: {
1744
+ mapName?: string;
1745
+ key?: string;
1746
+ types?: ('PUT' | 'UPDATE' | 'DELETE')[];
1747
+ fromSequence?: bigint;
1748
+ toSequence?: bigint;
1749
+ fromDate?: Date;
1750
+ toDate?: Date;
1751
+ limit?: number;
1752
+ offset?: number;
1753
+ }): Promise<JournalEvent[]>;
1754
+ /**
1755
+ * Count events matching filters.
1756
+ */
1757
+ countFromStorage(options?: {
1758
+ mapName?: string;
1759
+ types?: ('PUT' | 'UPDATE' | 'DELETE')[];
1760
+ fromDate?: Date;
1761
+ toDate?: Date;
1762
+ }): Promise<number>;
1763
+ /**
1764
+ * Cleanup old events based on retention policy.
1765
+ */
1766
+ cleanupOldEvents(retentionDays: number): Promise<number>;
1767
+ /**
1768
+ * Start the periodic persistence timer.
1769
+ */
1770
+ private startPersistTimer;
1771
+ /**
1772
+ * Stop the periodic persistence timer.
1773
+ */
1774
+ private stopPersistTimer;
1775
+ /**
1776
+ * Dispose resources and persist remaining events.
1777
+ */
1778
+ dispose(): void;
1779
+ /**
1780
+ * Get pending persist count (for monitoring).
1781
+ */
1782
+ getPendingPersistCount(): number;
1783
+ }
1784
+
1674
1785
  interface ServerCoordinatorConfig {
1675
1786
  port: number;
1676
1787
  nodeId: string;
@@ -1743,6 +1854,10 @@ interface ServerCoordinatorConfig {
1743
1854
  defaultConsistency?: ConsistencyLevel;
1744
1855
  /** Replication configuration */
1745
1856
  replicationConfig?: Partial<ReplicationConfig>;
1857
+ /** Enable event journal for audit/CDC (default: false) */
1858
+ eventJournalEnabled?: boolean;
1859
+ /** Event journal configuration */
1860
+ eventJournalConfig?: Partial<Omit<EventJournalServiceConfig, 'pool'>>;
1746
1861
  }
1747
1862
  declare class ServerCoordinator {
1748
1863
  private httpServer;
@@ -1782,6 +1897,12 @@ declare class ServerCoordinator {
1782
1897
  private eventPayloadPool;
1783
1898
  private taskletScheduler;
1784
1899
  private writeAckManager;
1900
+ private counterHandler;
1901
+ private entryProcessorHandler;
1902
+ private conflictResolverHandler;
1903
+ private eventJournalService?;
1904
+ private journalSubscriptions;
1905
+ private readonly _nodeId;
1785
1906
  private _actualPort;
1786
1907
  private _actualClusterPort;
1787
1908
  private _readyPromise;
@@ -1831,6 +1952,11 @@ declare class ServerCoordinator {
1831
1952
  * Called when partition topology changes (node join/leave/failover).
1832
1953
  */
1833
1954
  private broadcastPartitionMap;
1955
+ /**
1956
+ * Notify a client about a merge rejection (Phase 5.05).
1957
+ * Finds the client by node ID and sends MERGE_REJECTED message.
1958
+ */
1959
+ private notifyMergeRejection;
1834
1960
  private broadcast;
1835
1961
  /**
1836
1962
  * === OPTIMIZATION 2 & 3: Batched Broadcast with Serialization Caching ===
@@ -1852,6 +1978,19 @@ declare class ServerCoordinator {
1852
1978
  private broadcastBatchSync;
1853
1979
  private setupClusterListeners;
1854
1980
  private executeLocalQuery;
1981
+ /**
1982
+ * Convert server Query format to core Query format for indexed execution.
1983
+ * Returns null if conversion is not possible (complex queries).
1984
+ */
1985
+ private convertToCoreQuery;
1986
+ /**
1987
+ * Convert predicate node to core Query format.
1988
+ */
1989
+ private predicateToCoreQuery;
1990
+ /**
1991
+ * Convert server operator to core query type.
1992
+ */
1993
+ private convertOperator;
1855
1994
  private finalizeClusterQuery;
1856
1995
  /**
1857
1996
  * Core operation application logic shared between processLocalOp and processLocalOpForBatch.
@@ -3048,4 +3187,689 @@ declare class ClusterCoordinator extends EventEmitter {
3048
3187
  private setupEventHandlers;
3049
3188
  }
3050
3189
 
3051
- export { BufferPool, type BufferPoolConfig, type BufferPoolStats, type ClusterConfig, ClusterCoordinator, type ClusterCoordinatorConfig, type ClusterCoordinatorEvents, ClusterManager, type ClusterMember, type ClusterMessage, type CoalescingPreset, type CoalescingWriterMetrics, type CoalescingWriterOptions, type ConnectionContext, ConnectionRateLimiter, DEFAULT_CLUSTER_COORDINATOR_CONFIG, DEFAULT_LAG_TRACKER_CONFIG, FilterTasklet, ForEachTasklet, type IInterceptor, type IServerStorage, IteratorTasklet, type IteratorTaskletConfig, type LagInfo, LagTracker, type LagTrackerConfig, LockManager, type Logger, MapTasklet, MemoryServerAdapter, MigrationManager, type NativeModuleStatus, type NativeStats, type ORMapTombstones, type ORMapValue, ObjectPool, type ObjectPoolConfig, type ObjectPoolStats, type OpContext, type PartitionDistribution, PartitionService, type PartitionServiceConfig, type PartitionServiceEvents, type PooledEventPayload, type PooledMessage, type PooledRecord, type PooledTimestamp, PostgresAdapter, type PostgresAdapterOptions, type ProgressState, RateLimitInterceptor, type RateLimiterConfig, type RateLimiterStats, ReduceTasklet, ReplicationPipeline, SecurityManager, ServerCoordinator, type ServerCoordinatorConfig, type ServerOp, type StorageValue, type Tasklet, TaskletScheduler, type TaskletSchedulerConfig, type TaskletSchedulerStats, TimestampInterceptor, coalescingPresets, createEventPayloadPool, createMessagePool, createRecordPool, createTimestampPool, getCoalescingPreset, getGlobalBufferPool, getGlobalEventPayloadPool, getGlobalMessagePool, getGlobalRecordPool, getGlobalTimestampPool, getNativeModuleStatus, getNativeStats, logNativeStatus, logger, setGlobalBufferPool, setGlobalEventPayloadPool, setGlobalMessagePool, setGlobalRecordPool, setGlobalTimestampPool };
3190
+ /**
3191
+ * Configuration for the processor sandbox.
3192
+ */
3193
+ interface ProcessorSandboxConfig {
3194
+ /** Memory limit in MB per isolate */
3195
+ memoryLimitMb: number;
3196
+ /** Execution timeout in milliseconds */
3197
+ timeoutMs: number;
3198
+ /** Maximum number of cached isolates */
3199
+ maxCachedIsolates: number;
3200
+ /** Enable strict code validation */
3201
+ strictValidation: boolean;
3202
+ }
3203
+ /**
3204
+ * Default sandbox configuration.
3205
+ */
3206
+ declare const DEFAULT_SANDBOX_CONFIG: ProcessorSandboxConfig;
3207
+ /**
3208
+ * Sandbox for executing entry processor code securely.
3209
+ *
3210
+ * Uses isolated-vm for production environments with:
3211
+ * - Memory limits to prevent memory bombs
3212
+ * - CPU limits via timeout to prevent infinite loops
3213
+ * - No I/O access (no require, fs, net, etc.)
3214
+ * - Minimal exposed globals (only value, key, args)
3215
+ *
3216
+ * Falls back to Node.js vm module for development/testing
3217
+ * when isolated-vm is not available.
3218
+ */
3219
+ declare class ProcessorSandbox {
3220
+ private config;
3221
+ private isolateCache;
3222
+ private scriptCache;
3223
+ private fallbackScriptCache;
3224
+ private disposed;
3225
+ constructor(config?: Partial<ProcessorSandboxConfig>);
3226
+ /**
3227
+ * Execute an entry processor in the sandbox.
3228
+ *
3229
+ * @param processor The processor definition (name, code, args)
3230
+ * @param value The current value for the key (or undefined)
3231
+ * @param key The key being processed
3232
+ * @returns Result containing success status, result, and new value
3233
+ */
3234
+ execute<V, R>(processor: EntryProcessorDef<V, R>, value: V | undefined, key: string): Promise<EntryProcessorResult<R>>;
3235
+ /**
3236
+ * Execute processor in isolated-vm (secure production mode).
3237
+ */
3238
+ private executeInIsolate;
3239
+ /**
3240
+ * Execute processor in fallback VM (less secure, for development).
3241
+ */
3242
+ private executeInFallback;
3243
+ /**
3244
+ * Get or create an isolate for a processor.
3245
+ */
3246
+ private getOrCreateIsolate;
3247
+ /**
3248
+ * Get or compile a script for a processor.
3249
+ */
3250
+ private getOrCompileScript;
3251
+ /**
3252
+ * Clear script cache for a specific processor (e.g., when code changes).
3253
+ */
3254
+ clearCache(processorName?: string): void;
3255
+ /**
3256
+ * Check if using secure isolated-vm mode.
3257
+ */
3258
+ isSecureMode(): boolean;
3259
+ /**
3260
+ * Get current cache sizes.
3261
+ */
3262
+ getCacheStats(): {
3263
+ isolates: number;
3264
+ scripts: number;
3265
+ fallbackScripts: number;
3266
+ };
3267
+ /**
3268
+ * Dispose of all isolates and clear caches.
3269
+ */
3270
+ dispose(): void;
3271
+ }
3272
+
3273
+ /**
3274
+ * Configuration for the EntryProcessorHandler.
3275
+ */
3276
+ interface EntryProcessorHandlerConfig {
3277
+ /** HLC instance for timestamp generation */
3278
+ hlc: HLC;
3279
+ /** Optional sandbox configuration override */
3280
+ sandboxConfig?: Partial<ProcessorSandboxConfig>;
3281
+ }
3282
+ /**
3283
+ * Server-side handler for Entry Processor execution.
3284
+ *
3285
+ * Responsibilities:
3286
+ * - Validate incoming processor definitions
3287
+ * - Execute processors in sandboxed environment
3288
+ * - Update map state atomically
3289
+ * - Return results with new values for client cache sync
3290
+ */
3291
+ declare class EntryProcessorHandler {
3292
+ private sandbox;
3293
+ private hlc;
3294
+ constructor(config: EntryProcessorHandlerConfig);
3295
+ /**
3296
+ * Execute a processor on a single key atomically.
3297
+ *
3298
+ * @param map The LWWMap to operate on
3299
+ * @param key The key to process
3300
+ * @param processorDef The processor definition (will be validated)
3301
+ * @returns Result with success status, processor result, and new value
3302
+ */
3303
+ executeOnKey<V, R>(map: LWWMap<string, V>, key: string, processorDef: unknown): Promise<{
3304
+ result: EntryProcessorResult<R>;
3305
+ timestamp?: Timestamp;
3306
+ }>;
3307
+ /**
3308
+ * Execute a processor on multiple keys.
3309
+ *
3310
+ * Each key is processed sequentially to ensure atomicity per-key.
3311
+ * For parallel execution across keys, use multiple calls.
3312
+ *
3313
+ * @param map The LWWMap to operate on
3314
+ * @param keys The keys to process
3315
+ * @param processorDef The processor definition
3316
+ * @returns Map of key -> result
3317
+ */
3318
+ executeOnKeys<V, R>(map: LWWMap<string, V>, keys: string[], processorDef: unknown): Promise<{
3319
+ results: Map<string, EntryProcessorResult<R>>;
3320
+ timestamps: Map<string, Timestamp>;
3321
+ }>;
3322
+ /**
3323
+ * Execute a processor on all entries matching a predicate.
3324
+ *
3325
+ * WARNING: This can be expensive for large maps.
3326
+ *
3327
+ * @param map The LWWMap to operate on
3328
+ * @param processorDef The processor definition
3329
+ * @param predicateCode Optional predicate code to filter entries
3330
+ * @returns Map of key -> result for processed entries
3331
+ */
3332
+ executeOnEntries<V, R>(map: LWWMap<string, V>, processorDef: unknown, predicateCode?: string): Promise<{
3333
+ results: Map<string, EntryProcessorResult<R>>;
3334
+ timestamps: Map<string, Timestamp>;
3335
+ }>;
3336
+ /**
3337
+ * Check if sandbox is in secure mode (using isolated-vm).
3338
+ */
3339
+ isSecureMode(): boolean;
3340
+ /**
3341
+ * Get sandbox cache statistics.
3342
+ */
3343
+ getCacheStats(): {
3344
+ isolates: number;
3345
+ scripts: number;
3346
+ fallbackScripts: number;
3347
+ };
3348
+ /**
3349
+ * Clear sandbox cache.
3350
+ */
3351
+ clearCache(processorName?: string): void;
3352
+ /**
3353
+ * Dispose of the handler and its sandbox.
3354
+ */
3355
+ dispose(): void;
3356
+ }
3357
+
3358
+ /**
3359
+ * Configuration for ConflictResolverService.
3360
+ */
3361
+ interface ConflictResolverServiceConfig {
3362
+ /** Maximum resolvers per map */
3363
+ maxResolversPerMap: number;
3364
+ /** Enable sandboxed code execution (requires isolated-vm) */
3365
+ enableSandboxedResolvers: boolean;
3366
+ /** Default timeout for resolver execution in milliseconds */
3367
+ resolverTimeoutMs: number;
3368
+ }
3369
+ /**
3370
+ * Default service configuration.
3371
+ */
3372
+ declare const DEFAULT_CONFLICT_RESOLVER_CONFIG: ConflictResolverServiceConfig;
3373
+ /**
3374
+ * Service for managing and executing conflict resolvers.
3375
+ *
3376
+ * Resolvers are executed in priority order (highest first).
3377
+ * The first resolver that returns a non-'local' action wins.
3378
+ * If all resolvers return 'local', LWW is used as fallback.
3379
+ *
3380
+ * ## Design Decisions
3381
+ *
3382
+ * ### In-Memory Storage
3383
+ * Resolvers are stored in memory only (not persisted to database).
3384
+ * This is intentional - resolvers represent application logic that should
3385
+ * be registered by clients on connection. Benefits:
3386
+ * - Simpler architecture without resolver schema migrations
3387
+ * - Clients control their own conflict resolution logic
3388
+ * - Natural cleanup when client disconnects
3389
+ *
3390
+ * ### Permission Model
3391
+ * Resolver registration requires PUT permission on the target map.
3392
+ * This aligns with the principle that if you can write to a map,
3393
+ * you can define how your writes are resolved. For stricter control,
3394
+ * implement custom permission checks in ServerCoordinator.
3395
+ *
3396
+ * ### Deletion Handling
3397
+ * Deletions (tombstones with null value) are passed through resolvers
3398
+ * with `remoteValue: null`. This allows resolvers like IMMUTABLE or
3399
+ * OWNER_ONLY to protect against unauthorized deletions.
3400
+ */
3401
+ declare class ConflictResolverService {
3402
+ private resolvers;
3403
+ private sandbox;
3404
+ private config;
3405
+ private onRejectionCallback?;
3406
+ private disposed;
3407
+ constructor(sandbox: ProcessorSandbox, config?: Partial<ConflictResolverServiceConfig>);
3408
+ /**
3409
+ * Set callback for merge rejections.
3410
+ */
3411
+ onRejection(callback: (rejection: MergeRejection) => void): void;
3412
+ /**
3413
+ * Register a resolver for a map.
3414
+ *
3415
+ * @param mapName The map this resolver applies to
3416
+ * @param resolver The resolver definition
3417
+ * @param registeredBy Optional client ID that registered this resolver
3418
+ */
3419
+ register<V>(mapName: string, resolver: ConflictResolverDef<V>, registeredBy?: string): void;
3420
+ /**
3421
+ * Unregister a resolver.
3422
+ *
3423
+ * @param mapName The map name
3424
+ * @param resolverName The resolver name to unregister
3425
+ * @param clientId Optional - only unregister if registered by this client
3426
+ */
3427
+ unregister(mapName: string, resolverName: string, clientId?: string): boolean;
3428
+ /**
3429
+ * Resolve a merge conflict using registered resolvers.
3430
+ *
3431
+ * @param context The merge context
3432
+ * @returns The merge result
3433
+ */
3434
+ resolve<V>(context: MergeContext<V>): Promise<MergeResult<V>>;
3435
+ /**
3436
+ * List registered resolvers.
3437
+ *
3438
+ * @param mapName Optional - filter by map name
3439
+ */
3440
+ list(mapName?: string): Array<{
3441
+ mapName: string;
3442
+ name: string;
3443
+ priority?: number;
3444
+ keyPattern?: string;
3445
+ registeredBy?: string;
3446
+ }>;
3447
+ /**
3448
+ * Check if a map has any registered resolvers.
3449
+ */
3450
+ hasResolvers(mapName: string): boolean;
3451
+ /**
3452
+ * Get the number of registered resolvers.
3453
+ */
3454
+ get size(): number;
3455
+ /**
3456
+ * Clear all registered resolvers.
3457
+ *
3458
+ * @param mapName Optional - only clear resolvers for specific map
3459
+ */
3460
+ clear(mapName?: string): void;
3461
+ /**
3462
+ * Clear resolvers registered by a specific client.
3463
+ */
3464
+ clearByClient(clientId: string): number;
3465
+ /**
3466
+ * Dispose the service.
3467
+ */
3468
+ dispose(): void;
3469
+ /**
3470
+ * Match a key against a glob-like pattern.
3471
+ * Supports * (any chars) and ? (single char).
3472
+ */
3473
+ private matchKeyPattern;
3474
+ /**
3475
+ * Compile sandboxed resolver code.
3476
+ */
3477
+ private compileSandboxed;
3478
+ }
3479
+
3480
+ /**
3481
+ * Configuration for MapWithResolver.
3482
+ */
3483
+ interface MapWithResolverConfig {
3484
+ /** Map name */
3485
+ name: string;
3486
+ /** Node ID for HLC */
3487
+ nodeId: string;
3488
+ /** Conflict resolver service */
3489
+ resolverService: ConflictResolverService;
3490
+ /** Callback for merge rejections */
3491
+ onRejection?: (rejection: MergeRejection) => void;
3492
+ }
3493
+ /**
3494
+ * Result of setWithResolver operation.
3495
+ */
3496
+ interface SetWithResolverResult<V> {
3497
+ /** Whether the value was applied */
3498
+ applied: boolean;
3499
+ /** The merge result */
3500
+ result: MergeResult<V>;
3501
+ /** The final record if applied */
3502
+ record?: LWWRecord<V>;
3503
+ }
3504
+ /**
3505
+ * Extended LWWMap that supports custom conflict resolvers.
3506
+ *
3507
+ * This wrapper delegates merge operations to ConflictResolverService,
3508
+ * allowing custom business logic to intercept and modify merge behavior.
3509
+ */
3510
+ declare class MapWithResolver<K extends string, V> {
3511
+ private map;
3512
+ private resolverService;
3513
+ private mapName;
3514
+ private hlc;
3515
+ private onRejection?;
3516
+ constructor(config: MapWithResolverConfig);
3517
+ /**
3518
+ * Get the map name.
3519
+ */
3520
+ get name(): string;
3521
+ /**
3522
+ * Get the underlying LWWMap.
3523
+ */
3524
+ get rawMap(): LWWMap<K, V>;
3525
+ /**
3526
+ * Get a value by key.
3527
+ */
3528
+ get(key: K): V | undefined;
3529
+ /**
3530
+ * Get the full record for a key.
3531
+ */
3532
+ getRecord(key: K): LWWRecord<V> | undefined;
3533
+ /**
3534
+ * Get the timestamp for a key.
3535
+ */
3536
+ getTimestamp(key: K): Timestamp | undefined;
3537
+ /**
3538
+ * Set a value locally (no resolver).
3539
+ * Use for server-initiated writes.
3540
+ */
3541
+ set(key: K, value: V, ttlMs?: number): LWWRecord<V>;
3542
+ /**
3543
+ * Set a value with conflict resolution.
3544
+ * Use for client-initiated writes.
3545
+ *
3546
+ * @param key The key to set
3547
+ * @param value The new value
3548
+ * @param timestamp The client's timestamp
3549
+ * @param remoteNodeId The client's node ID
3550
+ * @param auth Optional authentication context
3551
+ * @returns Result containing applied status and merge result
3552
+ */
3553
+ setWithResolver(key: K, value: V, timestamp: Timestamp, remoteNodeId: string, auth?: MergeContext['auth']): Promise<SetWithResolverResult<V>>;
3554
+ /**
3555
+ * Remove a key.
3556
+ */
3557
+ remove(key: K): LWWRecord<V>;
3558
+ /**
3559
+ * Standard merge without resolver (for sync operations).
3560
+ */
3561
+ merge(key: K, record: LWWRecord<V>): boolean;
3562
+ /**
3563
+ * Merge with resolver support.
3564
+ * Equivalent to setWithResolver but takes a full record.
3565
+ */
3566
+ mergeWithResolver(key: K, record: LWWRecord<V>, remoteNodeId: string, auth?: MergeContext['auth']): Promise<SetWithResolverResult<V>>;
3567
+ /**
3568
+ * Clear all data.
3569
+ */
3570
+ clear(): void;
3571
+ /**
3572
+ * Get map size.
3573
+ */
3574
+ get size(): number;
3575
+ /**
3576
+ * Iterate over entries.
3577
+ */
3578
+ entries(): IterableIterator<[K, V]>;
3579
+ /**
3580
+ * Get all keys.
3581
+ */
3582
+ allKeys(): IterableIterator<K>;
3583
+ /**
3584
+ * Subscribe to changes.
3585
+ */
3586
+ onChange(callback: () => void): () => void;
3587
+ /**
3588
+ * Get MerkleTree for sync.
3589
+ */
3590
+ getMerkleTree(): _topgunbuild_core.MerkleTree;
3591
+ /**
3592
+ * Prune old tombstones.
3593
+ */
3594
+ prune(olderThan: Timestamp): K[];
3595
+ }
3596
+
3597
+ /**
3598
+ * Configuration for ConflictResolverHandler.
3599
+ */
3600
+ interface ConflictResolverHandlerConfig {
3601
+ /** Node ID for identifying server-side resolvers */
3602
+ nodeId: string;
3603
+ /** Optional sandbox configuration override */
3604
+ sandboxConfig?: Partial<ProcessorSandboxConfig>;
3605
+ /** Optional resolver service configuration */
3606
+ resolverConfig?: Partial<ConflictResolverServiceConfig>;
3607
+ }
3608
+ /**
3609
+ * Result of merge operation with resolver.
3610
+ */
3611
+ interface MergeWithResolverResult<V> {
3612
+ /** Whether the merge was applied */
3613
+ applied: boolean;
3614
+ /** The merge result details */
3615
+ result: MergeResult<V>;
3616
+ /** The final record if applied */
3617
+ record?: LWWRecord<V>;
3618
+ /** Rejection details if rejected */
3619
+ rejection?: MergeRejection;
3620
+ }
3621
+ /**
3622
+ * Server-side handler for Conflict Resolver operations.
3623
+ *
3624
+ * Responsibilities:
3625
+ * - Manage conflict resolver registrations
3626
+ * - Execute resolvers during merge operations
3627
+ * - Provide merge rejection notifications
3628
+ */
3629
+ declare class ConflictResolverHandler {
3630
+ private sandbox;
3631
+ private resolverService;
3632
+ /** Reserved for future use (server-side resolver identification) */
3633
+ private readonly nodeId;
3634
+ private rejectionListeners;
3635
+ constructor(config: ConflictResolverHandlerConfig);
3636
+ /**
3637
+ * Register a conflict resolver for a map.
3638
+ *
3639
+ * @param mapName The map name
3640
+ * @param resolver The resolver definition
3641
+ * @param clientId Optional client ID that registered this resolver
3642
+ */
3643
+ registerResolver<V>(mapName: string, resolver: ConflictResolverDef<V>, clientId?: string): void;
3644
+ /**
3645
+ * Unregister a conflict resolver.
3646
+ *
3647
+ * @param mapName The map name
3648
+ * @param resolverName The resolver name
3649
+ * @param clientId Optional - only unregister if registered by this client
3650
+ */
3651
+ unregisterResolver(mapName: string, resolverName: string, clientId?: string): boolean;
3652
+ /**
3653
+ * List registered resolvers.
3654
+ *
3655
+ * @param mapName Optional - filter by map name
3656
+ */
3657
+ listResolvers(mapName?: string): Array<{
3658
+ mapName: string;
3659
+ name: string;
3660
+ priority?: number;
3661
+ keyPattern?: string;
3662
+ }>;
3663
+ /**
3664
+ * Apply a merge with conflict resolution.
3665
+ *
3666
+ * Deletions (tombstones) are also passed through resolvers to allow
3667
+ * protection via IMMUTABLE, OWNER_ONLY, or similar resolvers.
3668
+ * If no custom resolvers are registered, deletions use standard LWW.
3669
+ *
3670
+ * @param map The LWWMap to merge into
3671
+ * @param mapName The map name (for resolver lookup)
3672
+ * @param key The key being merged
3673
+ * @param record The incoming record
3674
+ * @param remoteNodeId The source node ID
3675
+ * @param auth Optional authentication context
3676
+ */
3677
+ mergeWithResolver<V>(map: LWWMap<string, V>, mapName: string, key: string, record: LWWRecord<V>, remoteNodeId: string, auth?: MergeContext['auth']): Promise<MergeWithResolverResult<V>>;
3678
+ /**
3679
+ * Check if a map has custom resolvers registered.
3680
+ */
3681
+ hasResolvers(mapName: string): boolean;
3682
+ /**
3683
+ * Add a listener for merge rejections.
3684
+ */
3685
+ onRejection(listener: (rejection: MergeRejection) => void): () => void;
3686
+ /**
3687
+ * Clear resolvers registered by a specific client.
3688
+ */
3689
+ clearByClient(clientId: string): number;
3690
+ /**
3691
+ * Get the number of registered resolvers.
3692
+ */
3693
+ get resolverCount(): number;
3694
+ /**
3695
+ * Check if sandbox is in secure mode.
3696
+ */
3697
+ isSecureMode(): boolean;
3698
+ /**
3699
+ * Dispose of the handler.
3700
+ */
3701
+ dispose(): void;
3702
+ }
3703
+
3704
+ /**
3705
+ * IndexConfig Types
3706
+ *
3707
+ * Configuration types for server-side index management.
3708
+ * Used to define indexes per map at server startup.
3709
+ *
3710
+ * @module config/IndexConfig
3711
+ */
3712
+ /**
3713
+ * Definition of a single index on a map.
3714
+ */
3715
+ interface IndexDefinition {
3716
+ /** Attribute name (supports dot notation for nested attributes, e.g., "user.email") */
3717
+ attribute: string;
3718
+ /** Index type */
3719
+ type: 'hash' | 'navigable';
3720
+ /**
3721
+ * Comparator type for navigable indexes.
3722
+ * Defaults to natural ordering (string/number).
3723
+ */
3724
+ comparator?: 'number' | 'string' | 'date';
3725
+ }
3726
+ /**
3727
+ * Index configuration for a specific map.
3728
+ */
3729
+ interface MapIndexConfig {
3730
+ /** Map name */
3731
+ mapName: string;
3732
+ /** Indexes to create on this map */
3733
+ indexes: IndexDefinition[];
3734
+ }
3735
+ /**
3736
+ * Server-wide index configuration.
3737
+ */
3738
+ interface ServerIndexConfig {
3739
+ /**
3740
+ * Auto-create indexes based on query patterns.
3741
+ * When enabled, the server will analyze query patterns and suggest/create indexes.
3742
+ * Default: false
3743
+ */
3744
+ autoIndex?: boolean;
3745
+ /**
3746
+ * Maximum number of auto-created indexes per map.
3747
+ * Prevents unbounded memory growth from auto-indexing.
3748
+ * Default: 10
3749
+ */
3750
+ maxAutoIndexesPerMap?: number;
3751
+ /**
3752
+ * Pre-configured indexes per map.
3753
+ * These indexes are created at map initialization.
3754
+ */
3755
+ maps?: MapIndexConfig[];
3756
+ /**
3757
+ * Whether to log index usage statistics.
3758
+ * Default: false
3759
+ */
3760
+ logStats?: boolean;
3761
+ /**
3762
+ * Interval in milliseconds for logging index statistics.
3763
+ * Only used if logStats is true.
3764
+ * Default: 60000 (1 minute)
3765
+ */
3766
+ statsLogInterval?: number;
3767
+ }
3768
+ /**
3769
+ * Default index configuration.
3770
+ */
3771
+ declare const DEFAULT_INDEX_CONFIG: ServerIndexConfig;
3772
+ /**
3773
+ * Validate a ServerIndexConfig object.
3774
+ *
3775
+ * @param config - Config to validate
3776
+ * @returns Array of validation errors (empty if valid)
3777
+ */
3778
+ declare function validateIndexConfig(config: ServerIndexConfig): string[];
3779
+ /**
3780
+ * Merge user config with defaults.
3781
+ *
3782
+ * @param userConfig - User-provided config
3783
+ * @returns Merged config with defaults
3784
+ */
3785
+ declare function mergeWithDefaults(userConfig: Partial<ServerIndexConfig>): ServerIndexConfig;
3786
+
3787
+ /**
3788
+ * MapFactory Implementation
3789
+ *
3790
+ * Factory for creating LWWMap or IndexedLWWMap based on configuration.
3791
+ * Used by ServerCoordinator to create maps with proper indexes.
3792
+ *
3793
+ * @module config/MapFactory
3794
+ */
3795
+
3796
+ /**
3797
+ * Factory for creating indexed or regular CRDT maps.
3798
+ */
3799
+ declare class MapFactory {
3800
+ private readonly config;
3801
+ private readonly mapConfigs;
3802
+ /**
3803
+ * Create a MapFactory.
3804
+ *
3805
+ * @param config - Server index configuration
3806
+ */
3807
+ constructor(config?: Partial<ServerIndexConfig>);
3808
+ /**
3809
+ * Create an LWWMap or IndexedLWWMap based on configuration.
3810
+ *
3811
+ * @param mapName - Name of the map
3812
+ * @param hlc - Hybrid Logical Clock instance
3813
+ * @returns LWWMap or IndexedLWWMap depending on configuration
3814
+ */
3815
+ createLWWMap<V>(mapName: string, hlc: HLC): LWWMap<string, V> | IndexedLWWMap<string, V>;
3816
+ /**
3817
+ * Create an ORMap or IndexedORMap based on configuration.
3818
+ *
3819
+ * @param mapName - Name of the map
3820
+ * @param hlc - Hybrid Logical Clock instance
3821
+ * @returns ORMap or IndexedORMap depending on configuration
3822
+ */
3823
+ createORMap<V>(mapName: string, hlc: HLC): ORMap<string, V> | IndexedORMap<string, V>;
3824
+ /**
3825
+ * Add an index to an IndexedLWWMap based on definition.
3826
+ */
3827
+ private addIndexToLWWMap;
3828
+ /**
3829
+ * Add an index to an IndexedORMap based on definition.
3830
+ */
3831
+ private addIndexToORMap;
3832
+ /**
3833
+ * Create an Attribute for extracting values from records.
3834
+ * Supports dot notation for nested paths.
3835
+ */
3836
+ private createAttribute;
3837
+ /**
3838
+ * Get a nested value from an object using dot notation.
3839
+ *
3840
+ * @param obj - Object to extract value from
3841
+ * @param path - Dot-notation path (e.g., "user.email")
3842
+ * @returns Value at the path or undefined
3843
+ */
3844
+ private getNestedValue;
3845
+ /**
3846
+ * Create a comparator function for navigable indexes.
3847
+ */
3848
+ private createComparator;
3849
+ /**
3850
+ * Check if a map should be indexed based on configuration.
3851
+ *
3852
+ * @param mapName - Name of the map
3853
+ * @returns true if map has index configuration
3854
+ */
3855
+ hasIndexConfig(mapName: string): boolean;
3856
+ /**
3857
+ * Get index configuration for a map.
3858
+ *
3859
+ * @param mapName - Name of the map
3860
+ * @returns Map index config or undefined
3861
+ */
3862
+ getMapConfig(mapName: string): MapIndexConfig | undefined;
3863
+ /**
3864
+ * Get all configured map names.
3865
+ *
3866
+ * @returns Array of map names with index configuration
3867
+ */
3868
+ getConfiguredMaps(): string[];
3869
+ /**
3870
+ * Get the full server index configuration.
3871
+ */
3872
+ getConfig(): ServerIndexConfig;
3873
+ }
3874
+
3875
+ export { BufferPool, type BufferPoolConfig, type BufferPoolStats, type ClusterConfig, ClusterCoordinator, type ClusterCoordinatorConfig, type ClusterCoordinatorEvents, ClusterManager, type ClusterMember, type ClusterMessage, type CoalescingPreset, type CoalescingWriterMetrics, type CoalescingWriterOptions, ConflictResolverHandler, type ConflictResolverHandlerConfig, ConflictResolverService, type ConflictResolverServiceConfig, type ConnectionContext, ConnectionRateLimiter, DEFAULT_CLUSTER_COORDINATOR_CONFIG, DEFAULT_CONFLICT_RESOLVER_CONFIG, DEFAULT_INDEX_CONFIG, DEFAULT_JOURNAL_SERVICE_CONFIG, DEFAULT_LAG_TRACKER_CONFIG, DEFAULT_SANDBOX_CONFIG, EntryProcessorHandler, type EntryProcessorHandlerConfig, EventJournalService, type EventJournalServiceConfig, type ExportOptions, FilterTasklet, ForEachTasklet, type IInterceptor, type IServerStorage, type IndexDefinition, IteratorTasklet, type IteratorTaskletConfig, type LagInfo, LagTracker, type LagTrackerConfig, LockManager, type Logger, MapFactory, type MapIndexConfig, MapTasklet, MapWithResolver, type MapWithResolverConfig, MemoryServerAdapter, type MergeWithResolverResult, MigrationManager, type NativeModuleStatus, type NativeStats, type ORMapTombstones, type ORMapValue, ObjectPool, type ObjectPoolConfig, type ObjectPoolStats, type OpContext, type PartitionDistribution, PartitionService, type PartitionServiceConfig, type PartitionServiceEvents, type PooledEventPayload, type PooledMessage, type PooledRecord, type PooledTimestamp, PostgresAdapter, type PostgresAdapterOptions, ProcessorSandbox, type ProcessorSandboxConfig, type ProgressState, RateLimitInterceptor, type RateLimiterConfig, type RateLimiterStats, ReduceTasklet, ReplicationPipeline, SecurityManager, ServerCoordinator, type ServerCoordinatorConfig, type ServerIndexConfig, type ServerOp, type SetWithResolverResult, type StorageValue, type Tasklet, TaskletScheduler, type TaskletSchedulerConfig, type TaskletSchedulerStats, TimestampInterceptor, coalescingPresets, createEventPayloadPool, createMessagePool, createRecordPool, createTimestampPool, getCoalescingPreset, getGlobalBufferPool, getGlobalEventPayloadPool, getGlobalMessagePool, getGlobalRecordPool, getGlobalTimestampPool, getNativeModuleStatus, getNativeStats, logNativeStatus, logger, mergeWithDefaults, setGlobalBufferPool, setGlobalEventPayloadPool, setGlobalMessagePool, setGlobalRecordPool, setGlobalTimestampPool, validateIndexConfig };