* Emit events either immediately or batch them for later emission
(
changes: Array<ChangeMessage<TOutput, TKey>>,
forceEmit = false,
)
| 74 | * Emit events either immediately or batch them for later emission |
| 75 | */ |
| 76 | public emitEvents( |
| 77 | changes: Array<ChangeMessage<TOutput, TKey>>, |
| 78 | forceEmit = false, |
| 79 | ): void { |
| 80 | // Skip batching for user actions (forceEmit=true) to keep UI responsive |
| 81 | if (this.shouldBatchEvents && !forceEmit) { |
| 82 | // Add events to the batch |
| 83 | this.batchedEvents.push(...changes) |
| 84 | return |
| 85 | } |
| 86 | |
| 87 | // Either we're not batching, or we're forcing emission (user action or ending batch cycle) |
| 88 | let rawEvents = changes |
| 89 | |
| 90 | if (forceEmit) { |
| 91 | // Force emit is used to end a batch (e.g. after a sync commit). Combine any |
| 92 | // buffered optimistic events with the final changes so subscribers see the |
| 93 | // whole picture, even if the sync diff is empty. |
| 94 | if (this.batchedEvents.length > 0) { |
| 95 | rawEvents = [...this.batchedEvents, ...changes] |
| 96 | } |
| 97 | this.batchedEvents = [] |
| 98 | this.shouldBatchEvents = false |
| 99 | } |
| 100 | |
| 101 | if (rawEvents.length === 0) { |
| 102 | return |
| 103 | } |
| 104 | |
| 105 | // Enrich all change messages with virtual properties |
| 106 | // This uses the "add-if-missing" pattern to preserve pass-through semantics |
| 107 | const enrichedEvents: Array< |
| 108 | ChangeMessage<WithVirtualProps<TOutput, TKey>, TKey> |
| 109 | > = rawEvents.map((change) => this.enrichChangeWithVirtualProps(change)) |
| 110 | |
| 111 | // Emit to all listeners |
| 112 | for (const subscription of this.changeSubscriptions) { |
| 113 | subscription.emitEvents(enrichedEvents) |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | /** |
| 118 | * Subscribe to changes in the collection |
no test coverage detected