@@ -42,6 +42,10 @@ export class ModelApi<N extends JsonNode = JsonNode> implements SyncStore<JsonNo
4242 /** Emitted after local changes through `model.api` are applied. Same as
4343 * `.onLocalChange`, but this event buffered withing a microtask. */
4444 public readonly onLocalChanges = new MicrotaskBufferFanOut < number > ( this . onLocalChange ) ;
45+ /** Emitted before a transaction is started. */
46+ public readonly onBeforeTransaction = new FanOut < void > ( ) ;
47+ /** Emitted after transaction completes. */
48+ public readonly onTransaction = new FanOut < void > ( ) ;
4549 /** Emitted when the model changes. Combines `onReset`, `onPatch` and `onLocalChange`. */
4650 public readonly onChange = new MergeFanOut < number | Patch | void > ( [ this . onReset , this . onPatch , this . onLocalChange ] ) ;
4751 /** Emitted when the model changes. Same as `.onChange`, but this event is emitted once per microtask. */
@@ -248,6 +252,12 @@ export class ModelApi<N extends JsonNode = JsonNode> implements SyncStore<JsonNo
248252 return this . model . view ( ) ;
249253 }
250254
255+ public transaction ( callback : ( ) => void ) {
256+ this . onBeforeTransaction . emit ( ) ;
257+ callback ( ) ;
258+ this . onTransaction . emit ( ) ;
259+ }
260+
251261 /**
252262 * Flushes the builder and returns a patch.
253263 *
@@ -261,15 +271,26 @@ export class ModelApi<N extends JsonNode = JsonNode> implements SyncStore<JsonNo
261271 return patch ;
262272 }
263273
264- /** Emitted before a transaction is started. */
265- public readonly onBeforeTransaction = new FanOut < void > ( ) ;
266- /** Emitted after transaction completes. */
267- public readonly onTransaction = new FanOut < void > ( ) ;
274+ public stopAutoFlush ?: ( ) => void = undefined ;
268275
269- public transaction ( callback : ( ) => void ) {
270- this . onBeforeTransaction . emit ( ) ;
271- callback ( ) ;
272- this . onTransaction . emit ( ) ;
276+ /**
277+ * Begins to automatically flush buffered operations into patches, grouping
278+ * operations by microtasks or by transactions. To capture the patch, listen
279+ * to the `.onFlush` event.
280+ *
281+ * @returns Callback to stop auto flushing.
282+ */
283+ public autoFlush ( ) : ( ( ) => void ) {
284+ const drain = ( ) => this . builder . patch . ops . length && this . flush ( ) ;
285+ const onLocalChangesUnsubscribe = this . onLocalChanges . listen ( drain ) ;
286+ const onBeforeTransactionUnsubscribe = this . onBeforeTransaction . listen ( drain ) ;
287+ const onTransactionUnsubscribe = this . onTransaction . listen ( drain ) ;
288+ return this . stopAutoFlush = ( ) => {
289+ this . stopAutoFlush = undefined ;
290+ onLocalChangesUnsubscribe ( ) ;
291+ onBeforeTransactionUnsubscribe ( ) ;
292+ onTransactionUnsubscribe ( ) ;
293+ } ;
273294 }
274295
275296 // ---------------------------------------------------------------- SyncStore
0 commit comments