@topgunbuild/server 0.3.0 → 0.4.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.ts 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 } 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 ===
@@ -3048,4 +3174,518 @@ declare class ClusterCoordinator extends EventEmitter {
3048
3174
  private setupEventHandlers;
3049
3175
  }
3050
3176
 
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 };
3177
+ /**
3178
+ * Configuration for the processor sandbox.
3179
+ */
3180
+ interface ProcessorSandboxConfig {
3181
+ /** Memory limit in MB per isolate */
3182
+ memoryLimitMb: number;
3183
+ /** Execution timeout in milliseconds */
3184
+ timeoutMs: number;
3185
+ /** Maximum number of cached isolates */
3186
+ maxCachedIsolates: number;
3187
+ /** Enable strict code validation */
3188
+ strictValidation: boolean;
3189
+ }
3190
+ /**
3191
+ * Default sandbox configuration.
3192
+ */
3193
+ declare const DEFAULT_SANDBOX_CONFIG: ProcessorSandboxConfig;
3194
+ /**
3195
+ * Sandbox for executing entry processor code securely.
3196
+ *
3197
+ * Uses isolated-vm for production environments with:
3198
+ * - Memory limits to prevent memory bombs
3199
+ * - CPU limits via timeout to prevent infinite loops
3200
+ * - No I/O access (no require, fs, net, etc.)
3201
+ * - Minimal exposed globals (only value, key, args)
3202
+ *
3203
+ * Falls back to Node.js vm module for development/testing
3204
+ * when isolated-vm is not available.
3205
+ */
3206
+ declare class ProcessorSandbox {
3207
+ private config;
3208
+ private isolateCache;
3209
+ private scriptCache;
3210
+ private fallbackScriptCache;
3211
+ private disposed;
3212
+ constructor(config?: Partial<ProcessorSandboxConfig>);
3213
+ /**
3214
+ * Execute an entry processor in the sandbox.
3215
+ *
3216
+ * @param processor The processor definition (name, code, args)
3217
+ * @param value The current value for the key (or undefined)
3218
+ * @param key The key being processed
3219
+ * @returns Result containing success status, result, and new value
3220
+ */
3221
+ execute<V, R>(processor: EntryProcessorDef<V, R>, value: V | undefined, key: string): Promise<EntryProcessorResult<R>>;
3222
+ /**
3223
+ * Execute processor in isolated-vm (secure production mode).
3224
+ */
3225
+ private executeInIsolate;
3226
+ /**
3227
+ * Execute processor in fallback VM (less secure, for development).
3228
+ */
3229
+ private executeInFallback;
3230
+ /**
3231
+ * Get or create an isolate for a processor.
3232
+ */
3233
+ private getOrCreateIsolate;
3234
+ /**
3235
+ * Get or compile a script for a processor.
3236
+ */
3237
+ private getOrCompileScript;
3238
+ /**
3239
+ * Clear script cache for a specific processor (e.g., when code changes).
3240
+ */
3241
+ clearCache(processorName?: string): void;
3242
+ /**
3243
+ * Check if using secure isolated-vm mode.
3244
+ */
3245
+ isSecureMode(): boolean;
3246
+ /**
3247
+ * Get current cache sizes.
3248
+ */
3249
+ getCacheStats(): {
3250
+ isolates: number;
3251
+ scripts: number;
3252
+ fallbackScripts: number;
3253
+ };
3254
+ /**
3255
+ * Dispose of all isolates and clear caches.
3256
+ */
3257
+ dispose(): void;
3258
+ }
3259
+
3260
+ /**
3261
+ * Configuration for the EntryProcessorHandler.
3262
+ */
3263
+ interface EntryProcessorHandlerConfig {
3264
+ /** HLC instance for timestamp generation */
3265
+ hlc: HLC;
3266
+ /** Optional sandbox configuration override */
3267
+ sandboxConfig?: Partial<ProcessorSandboxConfig>;
3268
+ }
3269
+ /**
3270
+ * Server-side handler for Entry Processor execution.
3271
+ *
3272
+ * Responsibilities:
3273
+ * - Validate incoming processor definitions
3274
+ * - Execute processors in sandboxed environment
3275
+ * - Update map state atomically
3276
+ * - Return results with new values for client cache sync
3277
+ */
3278
+ declare class EntryProcessorHandler {
3279
+ private sandbox;
3280
+ private hlc;
3281
+ constructor(config: EntryProcessorHandlerConfig);
3282
+ /**
3283
+ * Execute a processor on a single key atomically.
3284
+ *
3285
+ * @param map The LWWMap to operate on
3286
+ * @param key The key to process
3287
+ * @param processorDef The processor definition (will be validated)
3288
+ * @returns Result with success status, processor result, and new value
3289
+ */
3290
+ executeOnKey<V, R>(map: LWWMap<string, V>, key: string, processorDef: unknown): Promise<{
3291
+ result: EntryProcessorResult<R>;
3292
+ timestamp?: Timestamp;
3293
+ }>;
3294
+ /**
3295
+ * Execute a processor on multiple keys.
3296
+ *
3297
+ * Each key is processed sequentially to ensure atomicity per-key.
3298
+ * For parallel execution across keys, use multiple calls.
3299
+ *
3300
+ * @param map The LWWMap to operate on
3301
+ * @param keys The keys to process
3302
+ * @param processorDef The processor definition
3303
+ * @returns Map of key -> result
3304
+ */
3305
+ executeOnKeys<V, R>(map: LWWMap<string, V>, keys: string[], processorDef: unknown): Promise<{
3306
+ results: Map<string, EntryProcessorResult<R>>;
3307
+ timestamps: Map<string, Timestamp>;
3308
+ }>;
3309
+ /**
3310
+ * Execute a processor on all entries matching a predicate.
3311
+ *
3312
+ * WARNING: This can be expensive for large maps.
3313
+ *
3314
+ * @param map The LWWMap to operate on
3315
+ * @param processorDef The processor definition
3316
+ * @param predicateCode Optional predicate code to filter entries
3317
+ * @returns Map of key -> result for processed entries
3318
+ */
3319
+ executeOnEntries<V, R>(map: LWWMap<string, V>, processorDef: unknown, predicateCode?: string): Promise<{
3320
+ results: Map<string, EntryProcessorResult<R>>;
3321
+ timestamps: Map<string, Timestamp>;
3322
+ }>;
3323
+ /**
3324
+ * Check if sandbox is in secure mode (using isolated-vm).
3325
+ */
3326
+ isSecureMode(): boolean;
3327
+ /**
3328
+ * Get sandbox cache statistics.
3329
+ */
3330
+ getCacheStats(): {
3331
+ isolates: number;
3332
+ scripts: number;
3333
+ fallbackScripts: number;
3334
+ };
3335
+ /**
3336
+ * Clear sandbox cache.
3337
+ */
3338
+ clearCache(processorName?: string): void;
3339
+ /**
3340
+ * Dispose of the handler and its sandbox.
3341
+ */
3342
+ dispose(): void;
3343
+ }
3344
+
3345
+ /**
3346
+ * Configuration for ConflictResolverService.
3347
+ */
3348
+ interface ConflictResolverServiceConfig {
3349
+ /** Maximum resolvers per map */
3350
+ maxResolversPerMap: number;
3351
+ /** Enable sandboxed code execution (requires isolated-vm) */
3352
+ enableSandboxedResolvers: boolean;
3353
+ /** Default timeout for resolver execution in milliseconds */
3354
+ resolverTimeoutMs: number;
3355
+ }
3356
+ /**
3357
+ * Default service configuration.
3358
+ */
3359
+ declare const DEFAULT_CONFLICT_RESOLVER_CONFIG: ConflictResolverServiceConfig;
3360
+ /**
3361
+ * Service for managing and executing conflict resolvers.
3362
+ *
3363
+ * Resolvers are executed in priority order (highest first).
3364
+ * The first resolver that returns a non-'local' action wins.
3365
+ * If all resolvers return 'local', LWW is used as fallback.
3366
+ *
3367
+ * ## Design Decisions
3368
+ *
3369
+ * ### In-Memory Storage
3370
+ * Resolvers are stored in memory only (not persisted to database).
3371
+ * This is intentional - resolvers represent application logic that should
3372
+ * be registered by clients on connection. Benefits:
3373
+ * - Simpler architecture without resolver schema migrations
3374
+ * - Clients control their own conflict resolution logic
3375
+ * - Natural cleanup when client disconnects
3376
+ *
3377
+ * ### Permission Model
3378
+ * Resolver registration requires PUT permission on the target map.
3379
+ * This aligns with the principle that if you can write to a map,
3380
+ * you can define how your writes are resolved. For stricter control,
3381
+ * implement custom permission checks in ServerCoordinator.
3382
+ *
3383
+ * ### Deletion Handling
3384
+ * Deletions (tombstones with null value) are passed through resolvers
3385
+ * with `remoteValue: null`. This allows resolvers like IMMUTABLE or
3386
+ * OWNER_ONLY to protect against unauthorized deletions.
3387
+ */
3388
+ declare class ConflictResolverService {
3389
+ private resolvers;
3390
+ private sandbox;
3391
+ private config;
3392
+ private onRejectionCallback?;
3393
+ private disposed;
3394
+ constructor(sandbox: ProcessorSandbox, config?: Partial<ConflictResolverServiceConfig>);
3395
+ /**
3396
+ * Set callback for merge rejections.
3397
+ */
3398
+ onRejection(callback: (rejection: MergeRejection) => void): void;
3399
+ /**
3400
+ * Register a resolver for a map.
3401
+ *
3402
+ * @param mapName The map this resolver applies to
3403
+ * @param resolver The resolver definition
3404
+ * @param registeredBy Optional client ID that registered this resolver
3405
+ */
3406
+ register<V>(mapName: string, resolver: ConflictResolverDef<V>, registeredBy?: string): void;
3407
+ /**
3408
+ * Unregister a resolver.
3409
+ *
3410
+ * @param mapName The map name
3411
+ * @param resolverName The resolver name to unregister
3412
+ * @param clientId Optional - only unregister if registered by this client
3413
+ */
3414
+ unregister(mapName: string, resolverName: string, clientId?: string): boolean;
3415
+ /**
3416
+ * Resolve a merge conflict using registered resolvers.
3417
+ *
3418
+ * @param context The merge context
3419
+ * @returns The merge result
3420
+ */
3421
+ resolve<V>(context: MergeContext<V>): Promise<MergeResult<V>>;
3422
+ /**
3423
+ * List registered resolvers.
3424
+ *
3425
+ * @param mapName Optional - filter by map name
3426
+ */
3427
+ list(mapName?: string): Array<{
3428
+ mapName: string;
3429
+ name: string;
3430
+ priority?: number;
3431
+ keyPattern?: string;
3432
+ registeredBy?: string;
3433
+ }>;
3434
+ /**
3435
+ * Check if a map has any registered resolvers.
3436
+ */
3437
+ hasResolvers(mapName: string): boolean;
3438
+ /**
3439
+ * Get the number of registered resolvers.
3440
+ */
3441
+ get size(): number;
3442
+ /**
3443
+ * Clear all registered resolvers.
3444
+ *
3445
+ * @param mapName Optional - only clear resolvers for specific map
3446
+ */
3447
+ clear(mapName?: string): void;
3448
+ /**
3449
+ * Clear resolvers registered by a specific client.
3450
+ */
3451
+ clearByClient(clientId: string): number;
3452
+ /**
3453
+ * Dispose the service.
3454
+ */
3455
+ dispose(): void;
3456
+ /**
3457
+ * Match a key against a glob-like pattern.
3458
+ * Supports * (any chars) and ? (single char).
3459
+ */
3460
+ private matchKeyPattern;
3461
+ /**
3462
+ * Compile sandboxed resolver code.
3463
+ */
3464
+ private compileSandboxed;
3465
+ }
3466
+
3467
+ /**
3468
+ * Configuration for MapWithResolver.
3469
+ */
3470
+ interface MapWithResolverConfig {
3471
+ /** Map name */
3472
+ name: string;
3473
+ /** Node ID for HLC */
3474
+ nodeId: string;
3475
+ /** Conflict resolver service */
3476
+ resolverService: ConflictResolverService;
3477
+ /** Callback for merge rejections */
3478
+ onRejection?: (rejection: MergeRejection) => void;
3479
+ }
3480
+ /**
3481
+ * Result of setWithResolver operation.
3482
+ */
3483
+ interface SetWithResolverResult<V> {
3484
+ /** Whether the value was applied */
3485
+ applied: boolean;
3486
+ /** The merge result */
3487
+ result: MergeResult<V>;
3488
+ /** The final record if applied */
3489
+ record?: LWWRecord<V>;
3490
+ }
3491
+ /**
3492
+ * Extended LWWMap that supports custom conflict resolvers.
3493
+ *
3494
+ * This wrapper delegates merge operations to ConflictResolverService,
3495
+ * allowing custom business logic to intercept and modify merge behavior.
3496
+ */
3497
+ declare class MapWithResolver<K extends string, V> {
3498
+ private map;
3499
+ private resolverService;
3500
+ private mapName;
3501
+ private hlc;
3502
+ private onRejection?;
3503
+ constructor(config: MapWithResolverConfig);
3504
+ /**
3505
+ * Get the map name.
3506
+ */
3507
+ get name(): string;
3508
+ /**
3509
+ * Get the underlying LWWMap.
3510
+ */
3511
+ get rawMap(): LWWMap<K, V>;
3512
+ /**
3513
+ * Get a value by key.
3514
+ */
3515
+ get(key: K): V | undefined;
3516
+ /**
3517
+ * Get the full record for a key.
3518
+ */
3519
+ getRecord(key: K): LWWRecord<V> | undefined;
3520
+ /**
3521
+ * Get the timestamp for a key.
3522
+ */
3523
+ getTimestamp(key: K): Timestamp | undefined;
3524
+ /**
3525
+ * Set a value locally (no resolver).
3526
+ * Use for server-initiated writes.
3527
+ */
3528
+ set(key: K, value: V, ttlMs?: number): LWWRecord<V>;
3529
+ /**
3530
+ * Set a value with conflict resolution.
3531
+ * Use for client-initiated writes.
3532
+ *
3533
+ * @param key The key to set
3534
+ * @param value The new value
3535
+ * @param timestamp The client's timestamp
3536
+ * @param remoteNodeId The client's node ID
3537
+ * @param auth Optional authentication context
3538
+ * @returns Result containing applied status and merge result
3539
+ */
3540
+ setWithResolver(key: K, value: V, timestamp: Timestamp, remoteNodeId: string, auth?: MergeContext['auth']): Promise<SetWithResolverResult<V>>;
3541
+ /**
3542
+ * Remove a key.
3543
+ */
3544
+ remove(key: K): LWWRecord<V>;
3545
+ /**
3546
+ * Standard merge without resolver (for sync operations).
3547
+ */
3548
+ merge(key: K, record: LWWRecord<V>): boolean;
3549
+ /**
3550
+ * Merge with resolver support.
3551
+ * Equivalent to setWithResolver but takes a full record.
3552
+ */
3553
+ mergeWithResolver(key: K, record: LWWRecord<V>, remoteNodeId: string, auth?: MergeContext['auth']): Promise<SetWithResolverResult<V>>;
3554
+ /**
3555
+ * Clear all data.
3556
+ */
3557
+ clear(): void;
3558
+ /**
3559
+ * Get map size.
3560
+ */
3561
+ get size(): number;
3562
+ /**
3563
+ * Iterate over entries.
3564
+ */
3565
+ entries(): IterableIterator<[K, V]>;
3566
+ /**
3567
+ * Get all keys.
3568
+ */
3569
+ allKeys(): IterableIterator<K>;
3570
+ /**
3571
+ * Subscribe to changes.
3572
+ */
3573
+ onChange(callback: () => void): () => void;
3574
+ /**
3575
+ * Get MerkleTree for sync.
3576
+ */
3577
+ getMerkleTree(): _topgunbuild_core.MerkleTree;
3578
+ /**
3579
+ * Prune old tombstones.
3580
+ */
3581
+ prune(olderThan: Timestamp): K[];
3582
+ }
3583
+
3584
+ /**
3585
+ * Configuration for ConflictResolverHandler.
3586
+ */
3587
+ interface ConflictResolverHandlerConfig {
3588
+ /** Node ID for identifying server-side resolvers */
3589
+ nodeId: string;
3590
+ /** Optional sandbox configuration override */
3591
+ sandboxConfig?: Partial<ProcessorSandboxConfig>;
3592
+ /** Optional resolver service configuration */
3593
+ resolverConfig?: Partial<ConflictResolverServiceConfig>;
3594
+ }
3595
+ /**
3596
+ * Result of merge operation with resolver.
3597
+ */
3598
+ interface MergeWithResolverResult<V> {
3599
+ /** Whether the merge was applied */
3600
+ applied: boolean;
3601
+ /** The merge result details */
3602
+ result: MergeResult<V>;
3603
+ /** The final record if applied */
3604
+ record?: LWWRecord<V>;
3605
+ /** Rejection details if rejected */
3606
+ rejection?: MergeRejection;
3607
+ }
3608
+ /**
3609
+ * Server-side handler for Conflict Resolver operations.
3610
+ *
3611
+ * Responsibilities:
3612
+ * - Manage conflict resolver registrations
3613
+ * - Execute resolvers during merge operations
3614
+ * - Provide merge rejection notifications
3615
+ */
3616
+ declare class ConflictResolverHandler {
3617
+ private sandbox;
3618
+ private resolverService;
3619
+ /** Reserved for future use (server-side resolver identification) */
3620
+ private readonly nodeId;
3621
+ private rejectionListeners;
3622
+ constructor(config: ConflictResolverHandlerConfig);
3623
+ /**
3624
+ * Register a conflict resolver for a map.
3625
+ *
3626
+ * @param mapName The map name
3627
+ * @param resolver The resolver definition
3628
+ * @param clientId Optional client ID that registered this resolver
3629
+ */
3630
+ registerResolver<V>(mapName: string, resolver: ConflictResolverDef<V>, clientId?: string): void;
3631
+ /**
3632
+ * Unregister a conflict resolver.
3633
+ *
3634
+ * @param mapName The map name
3635
+ * @param resolverName The resolver name
3636
+ * @param clientId Optional - only unregister if registered by this client
3637
+ */
3638
+ unregisterResolver(mapName: string, resolverName: string, clientId?: string): boolean;
3639
+ /**
3640
+ * List registered resolvers.
3641
+ *
3642
+ * @param mapName Optional - filter by map name
3643
+ */
3644
+ listResolvers(mapName?: string): Array<{
3645
+ mapName: string;
3646
+ name: string;
3647
+ priority?: number;
3648
+ keyPattern?: string;
3649
+ }>;
3650
+ /**
3651
+ * Apply a merge with conflict resolution.
3652
+ *
3653
+ * Deletions (tombstones) are also passed through resolvers to allow
3654
+ * protection via IMMUTABLE, OWNER_ONLY, or similar resolvers.
3655
+ * If no custom resolvers are registered, deletions use standard LWW.
3656
+ *
3657
+ * @param map The LWWMap to merge into
3658
+ * @param mapName The map name (for resolver lookup)
3659
+ * @param key The key being merged
3660
+ * @param record The incoming record
3661
+ * @param remoteNodeId The source node ID
3662
+ * @param auth Optional authentication context
3663
+ */
3664
+ mergeWithResolver<V>(map: LWWMap<string, V>, mapName: string, key: string, record: LWWRecord<V>, remoteNodeId: string, auth?: MergeContext['auth']): Promise<MergeWithResolverResult<V>>;
3665
+ /**
3666
+ * Check if a map has custom resolvers registered.
3667
+ */
3668
+ hasResolvers(mapName: string): boolean;
3669
+ /**
3670
+ * Add a listener for merge rejections.
3671
+ */
3672
+ onRejection(listener: (rejection: MergeRejection) => void): () => void;
3673
+ /**
3674
+ * Clear resolvers registered by a specific client.
3675
+ */
3676
+ clearByClient(clientId: string): number;
3677
+ /**
3678
+ * Get the number of registered resolvers.
3679
+ */
3680
+ get resolverCount(): number;
3681
+ /**
3682
+ * Check if sandbox is in secure mode.
3683
+ */
3684
+ isSecureMode(): boolean;
3685
+ /**
3686
+ * Dispose of the handler.
3687
+ */
3688
+ dispose(): void;
3689
+ }
3690
+
3691
+ 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_JOURNAL_SERVICE_CONFIG, DEFAULT_LAG_TRACKER_CONFIG, DEFAULT_SANDBOX_CONFIG, EntryProcessorHandler, type EntryProcessorHandlerConfig, EventJournalService, type EventJournalServiceConfig, type ExportOptions, FilterTasklet, ForEachTasklet, type IInterceptor, type IServerStorage, IteratorTasklet, type IteratorTaskletConfig, type LagInfo, LagTracker, type LagTrackerConfig, LockManager, type Logger, 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 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, setGlobalBufferPool, setGlobalEventPayloadPool, setGlobalMessagePool, setGlobalRecordPool, setGlobalTimestampPool };