coaction 3.0.0 → 3.1.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.
@@ -431,6 +431,50 @@ declare const replaceExternalStoreState: <T extends CreateState>(store: Middlewa
431
431
  syncImmutable
432
432
  }?: ReplaceExternalStoreStateOptions) => void;
433
433
  //#endregion
434
+ //#region packages/core/src/storeCommit.d.ts
435
+ type StoreCommitSource = 'setState' | 'mutableAction' | 'external' | 'replay';
436
+ /**
437
+ * A patch pair emitted after Coaction has committed an authoritative state
438
+ * transition.
439
+ */
440
+ type StoreCommit<T extends CreateState = CreateState> = {
441
+ readonly state: T;
442
+ readonly patches: Patches;
443
+ readonly inversePatches: Patches;
444
+ readonly source: StoreCommitSource;
445
+ };
446
+ /** Patch pair to replay through Coaction's authoritative mutation pipeline. */
447
+ type StorePatchTransition = {
448
+ readonly patches: Patches;
449
+ readonly inversePatches: Patches;
450
+ };
451
+ type StorePatchReplayOptions<T extends CreateState = CreateState> = {
452
+ /** Middleware-scoped setState entry that should observe the replay. */setState?: Store<T>['setState'];
453
+ };
454
+ type StoreCommitListener<T extends CreateState> = (commit: StoreCommit<T>) => void;
455
+ type StoreCommitPrepareListener<T extends CreateState> = (commit: StoreCommit<T>) => boolean | void;
456
+ /**
457
+ * Observe patch pairs after successful Coaction commits.
458
+ *
459
+ * @remarks
460
+ * Registering a listener enables patch generation only while it is needed,
461
+ * even when the store was created without `enablePatches: true`.
462
+ */
463
+ declare const onStoreCommit: <T extends CreateState>(store: Store<T>, listener: StoreCommitListener<T>) => () => void;
464
+ /**
465
+ * Inspect a pending object-valued commit before its patch pair is applied.
466
+ *
467
+ * @remarks
468
+ * Return `true` to request an exact state replacement for transitions whose
469
+ * object graph cannot be represented safely by the patch pair.
470
+ */
471
+ declare const onStoreCommitPrepare: <T extends CreateState>(store: Store<T>, listener: StoreCommitPrepareListener<T>) => () => void;
472
+ /**
473
+ * Replay a patch pair through Coaction validation, patch middleware, adapters,
474
+ * subscriptions, and transports.
475
+ */
476
+ declare const replayStorePatches: <T extends CreateState>(store: Store<T>, transition: StorePatchTransition, options?: StorePatchReplayOptions<T>) => T;
477
+ //#endregion
434
478
  //#region packages/core/src/utils.d.ts
435
479
  declare class StateSchemaError extends Error {
436
480
  name: string;
@@ -465,4 +509,4 @@ declare const sanitizeInitialStateValue: <T>(source: T, seen?: WeakMap<object, u
465
509
  */
466
510
  declare const wrapStore: <T extends object>(store: Store<T>, getState?: (...args: unknown[]) => T) => StoreReturn<T>;
467
511
  //#endregion
468
- export { type CreateState, type ExternalStoreAdapterOptions, type Middleware, type MiddlewareStore, type PatchTransform, type ReactiveTracker, StateSchemaError, type Store, type StoreTraceEvent, applyMutableAdapterPatches, applyRootReplacementWithPatches, createBinder, createReactiveTracker, createRootReplacementPatches, defineExternalStoreAdapter, getMutableAdapterOwnEnumerableKeys, isEqualMutableAdapterSnapshot, isMutableAdapterUnsafeKey, isStateSchemaError, onStoreReady, replaceExternalStoreState, replaceMutableAdapterState, replaceOwnEnumerable, sanitizeInitialStateValue, sanitizeReplacementState, snapshotMutableAdapterPureState, toMutableAdapterSnapshot, wrapStore };
512
+ export { type CreateState, type ExternalStoreAdapterOptions, type Middleware, type MiddlewareStore, type PatchTransform, type ReactiveTracker, StateSchemaError, type Store, type StoreCommit, type StoreCommitSource, type StorePatchReplayOptions, type StorePatchTransition, type StoreTraceEvent, applyMutableAdapterPatches, applyRootReplacementWithPatches, createBinder, createReactiveTracker, createRootReplacementPatches, defineExternalStoreAdapter, getMutableAdapterOwnEnumerableKeys, isEqualMutableAdapterSnapshot, isMutableAdapterUnsafeKey, isStateSchemaError, onStoreCommit, onStoreCommitPrepare, onStoreReady, replaceExternalStoreState, replaceMutableAdapterState, replaceOwnEnumerable, replayStorePatches, sanitizeInitialStateValue, sanitizeReplacementState, snapshotMutableAdapterPureState, toMutableAdapterSnapshot, wrapStore };
package/dist/adapter.d.ts CHANGED
@@ -431,6 +431,50 @@ declare const replaceExternalStoreState: <T extends CreateState>(store: Middlewa
431
431
  syncImmutable
432
432
  }?: ReplaceExternalStoreStateOptions) => void;
433
433
  //#endregion
434
+ //#region packages/core/src/storeCommit.d.ts
435
+ type StoreCommitSource = 'setState' | 'mutableAction' | 'external' | 'replay';
436
+ /**
437
+ * A patch pair emitted after Coaction has committed an authoritative state
438
+ * transition.
439
+ */
440
+ type StoreCommit<T extends CreateState = CreateState> = {
441
+ readonly state: T;
442
+ readonly patches: Patches;
443
+ readonly inversePatches: Patches;
444
+ readonly source: StoreCommitSource;
445
+ };
446
+ /** Patch pair to replay through Coaction's authoritative mutation pipeline. */
447
+ type StorePatchTransition = {
448
+ readonly patches: Patches;
449
+ readonly inversePatches: Patches;
450
+ };
451
+ type StorePatchReplayOptions<T extends CreateState = CreateState> = {
452
+ /** Middleware-scoped setState entry that should observe the replay. */setState?: Store<T>['setState'];
453
+ };
454
+ type StoreCommitListener<T extends CreateState> = (commit: StoreCommit<T>) => void;
455
+ type StoreCommitPrepareListener<T extends CreateState> = (commit: StoreCommit<T>) => boolean | void;
456
+ /**
457
+ * Observe patch pairs after successful Coaction commits.
458
+ *
459
+ * @remarks
460
+ * Registering a listener enables patch generation only while it is needed,
461
+ * even when the store was created without `enablePatches: true`.
462
+ */
463
+ declare const onStoreCommit: <T extends CreateState>(store: Store<T>, listener: StoreCommitListener<T>) => () => void;
464
+ /**
465
+ * Inspect a pending object-valued commit before its patch pair is applied.
466
+ *
467
+ * @remarks
468
+ * Return `true` to request an exact state replacement for transitions whose
469
+ * object graph cannot be represented safely by the patch pair.
470
+ */
471
+ declare const onStoreCommitPrepare: <T extends CreateState>(store: Store<T>, listener: StoreCommitPrepareListener<T>) => () => void;
472
+ /**
473
+ * Replay a patch pair through Coaction validation, patch middleware, adapters,
474
+ * subscriptions, and transports.
475
+ */
476
+ declare const replayStorePatches: <T extends CreateState>(store: Store<T>, transition: StorePatchTransition, options?: StorePatchReplayOptions<T>) => T;
477
+ //#endregion
434
478
  //#region packages/core/src/utils.d.ts
435
479
  declare class StateSchemaError extends Error {
436
480
  name: string;
@@ -465,4 +509,4 @@ declare const sanitizeInitialStateValue: <T>(source: T, seen?: WeakMap<object, u
465
509
  */
466
510
  declare const wrapStore: <T extends object>(store: Store<T>, getState?: (...args: unknown[]) => T) => StoreReturn<T>;
467
511
  //#endregion
468
- export { type CreateState, type ExternalStoreAdapterOptions, type Middleware, type MiddlewareStore, type PatchTransform, type ReactiveTracker, StateSchemaError, type Store, type StoreTraceEvent, applyMutableAdapterPatches, applyRootReplacementWithPatches, createBinder, createReactiveTracker, createRootReplacementPatches, defineExternalStoreAdapter, getMutableAdapterOwnEnumerableKeys, isEqualMutableAdapterSnapshot, isMutableAdapterUnsafeKey, isStateSchemaError, onStoreReady, replaceExternalStoreState, replaceMutableAdapterState, replaceOwnEnumerable, sanitizeInitialStateValue, sanitizeReplacementState, snapshotMutableAdapterPureState, toMutableAdapterSnapshot, wrapStore };
512
+ export { type CreateState, type ExternalStoreAdapterOptions, type Middleware, type MiddlewareStore, type PatchTransform, type ReactiveTracker, StateSchemaError, type Store, type StoreCommit, type StoreCommitSource, type StorePatchReplayOptions, type StorePatchTransition, type StoreTraceEvent, applyMutableAdapterPatches, applyRootReplacementWithPatches, createBinder, createReactiveTracker, createRootReplacementPatches, defineExternalStoreAdapter, getMutableAdapterOwnEnumerableKeys, isEqualMutableAdapterSnapshot, isMutableAdapterUnsafeKey, isStateSchemaError, onStoreCommit, onStoreCommitPrepare, onStoreReady, replaceExternalStoreState, replaceMutableAdapterState, replaceOwnEnumerable, replayStorePatches, sanitizeInitialStateValue, sanitizeReplacementState, snapshotMutableAdapterPureState, toMutableAdapterSnapshot, wrapStore };
package/dist/adapter.js CHANGED
@@ -108,9 +108,10 @@ const warnDroppedUnsafePatches = (unsafePatches, source) => {
108
108
  };
109
109
  const sanitizePatches = (patches, options = {}) => {
110
110
  if (options.warnOnDropped) warnDroppedUnsafePatches(getUnsafePatchPaths(patches), options.source ?? "patches");
111
+ const seen = /* @__PURE__ */ new WeakMap();
111
112
  return patches?.filter((patch) => !hasUnsafePatchPath(patch.path)).map((patch) => Object.prototype.hasOwnProperty.call(patch, "value") ? {
112
113
  ...patch,
113
- value: sanitizeReplacementState(patch.value)
114
+ value: sanitizeReplacementState(patch.value, seen)
114
115
  } : patch);
115
116
  };
116
117
  const sanitizeCheckedPatches = (patches, source) => {
@@ -510,24 +511,107 @@ const createReactiveTracker = () => {
510
511
  };
511
512
  //#endregion
512
513
  //#region packages/core/src/lifecycle.ts
513
- const readyStores = /* @__PURE__ */ new WeakSet();
514
- const readyCallbacks = /* @__PURE__ */ new WeakMap();
514
+ const storeReadyRuntimeSymbol = Symbol.for("coaction.lifecycle.ready");
515
+ const getStoreReadyRuntime = (store, create = false) => {
516
+ const target = store;
517
+ const existing = target[storeReadyRuntimeSymbol];
518
+ if (existing || !create) return existing;
519
+ const runtime = {
520
+ callbacks: /* @__PURE__ */ new Set(),
521
+ ready: false
522
+ };
523
+ Object.defineProperty(target, storeReadyRuntimeSymbol, {
524
+ configurable: true,
525
+ enumerable: true,
526
+ value: runtime,
527
+ writable: true
528
+ });
529
+ return runtime;
530
+ };
515
531
  const onStoreReady = (store, callback) => {
516
- if (readyStores.has(store)) {
532
+ const runtime = getStoreReadyRuntime(store, true);
533
+ if (runtime.ready) {
517
534
  callback();
518
535
  return () => void 0;
519
536
  }
520
- let callbacks = readyCallbacks.get(store);
521
- if (!callbacks) {
522
- callbacks = /* @__PURE__ */ new Set();
523
- readyCallbacks.set(store, callbacks);
524
- }
525
- callbacks.add(callback);
537
+ runtime.callbacks.add(callback);
526
538
  return () => {
527
- callbacks?.delete(callback);
539
+ runtime.callbacks.delete(callback);
528
540
  };
529
541
  };
530
542
  //#endregion
543
+ //#region packages/core/src/storeCommit.ts
544
+ const storeCommitRuntimeSymbol = Symbol.for("coaction.storeCommit.runtime");
545
+ const getStoreCommitRuntime = (store, create = false) => {
546
+ const target = store;
547
+ const existing = target[storeCommitRuntimeSymbol];
548
+ if (existing || !create) return existing;
549
+ const runtime = {
550
+ disposed: false,
551
+ listeners: /* @__PURE__ */ new Set(),
552
+ prepareListeners: /* @__PURE__ */ new Set()
553
+ };
554
+ Object.defineProperty(target, storeCommitRuntimeSymbol, {
555
+ configurable: true,
556
+ enumerable: true,
557
+ value: runtime,
558
+ writable: true
559
+ });
560
+ return runtime;
561
+ };
562
+ /**
563
+ * Observe patch pairs after successful Coaction commits.
564
+ *
565
+ * @remarks
566
+ * Registering a listener enables patch generation only while it is needed,
567
+ * even when the store was created without `enablePatches: true`.
568
+ */
569
+ const onStoreCommit = (store, listener) => {
570
+ const runtime = getStoreCommitRuntime(store, true);
571
+ if (runtime.disposed) throw new Error("onStoreCommit() cannot be called after store.destroy().");
572
+ runtime.listeners.add(listener);
573
+ let active = true;
574
+ return () => {
575
+ if (!active) return;
576
+ active = false;
577
+ runtime.listeners.delete(listener);
578
+ };
579
+ };
580
+ /**
581
+ * Inspect a pending object-valued commit before its patch pair is applied.
582
+ *
583
+ * @remarks
584
+ * Return `true` to request an exact state replacement for transitions whose
585
+ * object graph cannot be represented safely by the patch pair.
586
+ */
587
+ const onStoreCommitPrepare = (store, listener) => {
588
+ const runtime = getStoreCommitRuntime(store, true);
589
+ if (runtime.disposed) throw new Error("onStoreCommitPrepare() cannot be called after store.destroy().");
590
+ runtime.prepareListeners.add(listener);
591
+ let active = true;
592
+ return () => {
593
+ if (!active) return;
594
+ active = false;
595
+ runtime.prepareListeners.delete(listener);
596
+ };
597
+ };
598
+ /**
599
+ * Replay a patch pair through Coaction validation, patch middleware, adapters,
600
+ * subscriptions, and transports.
601
+ */
602
+ const replayStorePatches = (store, transition, options = {}) => {
603
+ const runtime = getStoreCommitRuntime(store);
604
+ const replay = runtime?.disposed ? void 0 : runtime?.replay;
605
+ if (!replay) throw new Error("replayStorePatches() requires a store created by Coaction.");
606
+ return replay(transition, options.setState);
607
+ };
608
+ /** @internal */
609
+ const publishStoreCommit = (store, commit) => {
610
+ const runtime = getStoreCommitRuntime(store);
611
+ if (!runtime || runtime.disposed || !runtime.listeners.size) return;
612
+ for (const listener of [...runtime.listeners]) listener(commit);
613
+ };
614
+ //#endregion
531
615
  //#region packages/core/src/replaceExternalStoreState.ts
532
616
  const replaceExternalStoreState = (store, internal, source, { syncImmutable = true } = {}) => {
533
617
  internal.validateReplacementSource?.(source);
@@ -535,13 +619,15 @@ const replaceExternalStoreState = (store, internal, source, { syncImmutable = tr
535
619
  replaceOwnEnumerable(draft, source);
536
620
  }, { enablePatches: true });
537
621
  internal.validateState?.(nextState);
538
- const safePatches = sanitizeCheckedPatches((store.patch ? store.patch({
622
+ const finalPatches = store.patch ? store.patch({
539
623
  patches,
540
624
  inversePatches
541
625
  }) : {
542
626
  patches,
543
627
  inversePatches
544
- }).patches, "store.patch()");
628
+ };
629
+ const safePatches = sanitizeCheckedPatches(finalPatches.patches, "store.patch()");
630
+ const safeInversePatches = sanitizeCheckedPatches(finalPatches.inversePatches, "store.patch() inverse patches");
545
631
  if (!safePatches.length) return;
546
632
  const updateImmutable = internal.updateImmutable;
547
633
  if (!syncImmutable) internal.updateImmutable = void 0;
@@ -551,6 +637,12 @@ const replaceExternalStoreState = (store, internal, source, { syncImmutable = tr
551
637
  internal.updateImmutable = updateImmutable;
552
638
  }
553
639
  internal.emitPatches?.(safePatches);
640
+ publishStoreCommit(store, {
641
+ state: internal.rootState,
642
+ patches: safePatches,
643
+ inversePatches: safeInversePatches,
644
+ source: "external"
645
+ });
554
646
  };
555
647
  //#endregion
556
648
  //#region packages/core/src/wrapStore.ts
@@ -580,10 +672,13 @@ exports.getMutableAdapterOwnEnumerableKeys = getMutableAdapterOwnEnumerableKeys;
580
672
  exports.isEqualMutableAdapterSnapshot = isEqualMutableAdapterSnapshot;
581
673
  exports.isMutableAdapterUnsafeKey = isMutableAdapterUnsafeKey;
582
674
  exports.isStateSchemaError = isStateSchemaError;
675
+ exports.onStoreCommit = onStoreCommit;
676
+ exports.onStoreCommitPrepare = onStoreCommitPrepare;
583
677
  exports.onStoreReady = onStoreReady;
584
678
  exports.replaceExternalStoreState = replaceExternalStoreState;
585
679
  exports.replaceMutableAdapterState = replaceMutableAdapterState;
586
680
  exports.replaceOwnEnumerable = replaceOwnEnumerable;
681
+ exports.replayStorePatches = replayStorePatches;
587
682
  exports.sanitizeInitialStateValue = sanitizeInitialStateValue;
588
683
  exports.sanitizeReplacementState = sanitizeReplacementState;
589
684
  exports.snapshotMutableAdapterPureState = snapshotMutableAdapterPureState;
package/dist/adapter.mjs CHANGED
@@ -84,9 +84,10 @@ const warnDroppedUnsafePatches = (unsafePatches, source) => {
84
84
  };
85
85
  const sanitizePatches = (patches, options = {}) => {
86
86
  if (options.warnOnDropped) warnDroppedUnsafePatches(getUnsafePatchPaths(patches), options.source ?? "patches");
87
+ const seen = /* @__PURE__ */ new WeakMap();
87
88
  return patches?.filter((patch) => !hasUnsafePatchPath(patch.path)).map((patch) => Object.prototype.hasOwnProperty.call(patch, "value") ? {
88
89
  ...patch,
89
- value: sanitizeReplacementState(patch.value)
90
+ value: sanitizeReplacementState(patch.value, seen)
90
91
  } : patch);
91
92
  };
92
93
  const sanitizeCheckedPatches = (patches, source) => {
@@ -486,23 +487,106 @@ const createReactiveTracker = () => {
486
487
  };
487
488
  //#endregion
488
489
  //#region packages/core/src/lifecycle.ts
489
- const readyStores = /* @__PURE__ */ new WeakSet();
490
- const readyCallbacks = /* @__PURE__ */ new WeakMap();
490
+ const storeReadyRuntimeSymbol = Symbol.for("coaction.lifecycle.ready");
491
+ const getStoreReadyRuntime = (store, create = false) => {
492
+ const target = store;
493
+ const existing = target[storeReadyRuntimeSymbol];
494
+ if (existing || !create) return existing;
495
+ const runtime = {
496
+ callbacks: /* @__PURE__ */ new Set(),
497
+ ready: false
498
+ };
499
+ Object.defineProperty(target, storeReadyRuntimeSymbol, {
500
+ configurable: true,
501
+ enumerable: true,
502
+ value: runtime,
503
+ writable: true
504
+ });
505
+ return runtime;
506
+ };
491
507
  const onStoreReady = (store, callback) => {
492
- if (readyStores.has(store)) {
508
+ const runtime = getStoreReadyRuntime(store, true);
509
+ if (runtime.ready) {
493
510
  callback();
494
511
  return () => void 0;
495
512
  }
496
- let callbacks = readyCallbacks.get(store);
497
- if (!callbacks) {
498
- callbacks = /* @__PURE__ */ new Set();
499
- readyCallbacks.set(store, callbacks);
500
- }
501
- callbacks.add(callback);
513
+ runtime.callbacks.add(callback);
514
+ return () => {
515
+ runtime.callbacks.delete(callback);
516
+ };
517
+ };
518
+ //#endregion
519
+ //#region packages/core/src/storeCommit.ts
520
+ const storeCommitRuntimeSymbol = Symbol.for("coaction.storeCommit.runtime");
521
+ const getStoreCommitRuntime = (store, create = false) => {
522
+ const target = store;
523
+ const existing = target[storeCommitRuntimeSymbol];
524
+ if (existing || !create) return existing;
525
+ const runtime = {
526
+ disposed: false,
527
+ listeners: /* @__PURE__ */ new Set(),
528
+ prepareListeners: /* @__PURE__ */ new Set()
529
+ };
530
+ Object.defineProperty(target, storeCommitRuntimeSymbol, {
531
+ configurable: true,
532
+ enumerable: true,
533
+ value: runtime,
534
+ writable: true
535
+ });
536
+ return runtime;
537
+ };
538
+ /**
539
+ * Observe patch pairs after successful Coaction commits.
540
+ *
541
+ * @remarks
542
+ * Registering a listener enables patch generation only while it is needed,
543
+ * even when the store was created without `enablePatches: true`.
544
+ */
545
+ const onStoreCommit = (store, listener) => {
546
+ const runtime = getStoreCommitRuntime(store, true);
547
+ if (runtime.disposed) throw new Error("onStoreCommit() cannot be called after store.destroy().");
548
+ runtime.listeners.add(listener);
549
+ let active = true;
502
550
  return () => {
503
- callbacks?.delete(callback);
551
+ if (!active) return;
552
+ active = false;
553
+ runtime.listeners.delete(listener);
504
554
  };
505
555
  };
556
+ /**
557
+ * Inspect a pending object-valued commit before its patch pair is applied.
558
+ *
559
+ * @remarks
560
+ * Return `true` to request an exact state replacement for transitions whose
561
+ * object graph cannot be represented safely by the patch pair.
562
+ */
563
+ const onStoreCommitPrepare = (store, listener) => {
564
+ const runtime = getStoreCommitRuntime(store, true);
565
+ if (runtime.disposed) throw new Error("onStoreCommitPrepare() cannot be called after store.destroy().");
566
+ runtime.prepareListeners.add(listener);
567
+ let active = true;
568
+ return () => {
569
+ if (!active) return;
570
+ active = false;
571
+ runtime.prepareListeners.delete(listener);
572
+ };
573
+ };
574
+ /**
575
+ * Replay a patch pair through Coaction validation, patch middleware, adapters,
576
+ * subscriptions, and transports.
577
+ */
578
+ const replayStorePatches = (store, transition, options = {}) => {
579
+ const runtime = getStoreCommitRuntime(store);
580
+ const replay = runtime?.disposed ? void 0 : runtime?.replay;
581
+ if (!replay) throw new Error("replayStorePatches() requires a store created by Coaction.");
582
+ return replay(transition, options.setState);
583
+ };
584
+ /** @internal */
585
+ const publishStoreCommit = (store, commit) => {
586
+ const runtime = getStoreCommitRuntime(store);
587
+ if (!runtime || runtime.disposed || !runtime.listeners.size) return;
588
+ for (const listener of [...runtime.listeners]) listener(commit);
589
+ };
506
590
  //#endregion
507
591
  //#region packages/core/src/replaceExternalStoreState.ts
508
592
  const replaceExternalStoreState = (store, internal, source, { syncImmutable = true } = {}) => {
@@ -511,13 +595,15 @@ const replaceExternalStoreState = (store, internal, source, { syncImmutable = tr
511
595
  replaceOwnEnumerable(draft, source);
512
596
  }, { enablePatches: true });
513
597
  internal.validateState?.(nextState);
514
- const safePatches = sanitizeCheckedPatches((store.patch ? store.patch({
598
+ const finalPatches = store.patch ? store.patch({
515
599
  patches,
516
600
  inversePatches
517
601
  }) : {
518
602
  patches,
519
603
  inversePatches
520
- }).patches, "store.patch()");
604
+ };
605
+ const safePatches = sanitizeCheckedPatches(finalPatches.patches, "store.patch()");
606
+ const safeInversePatches = sanitizeCheckedPatches(finalPatches.inversePatches, "store.patch() inverse patches");
521
607
  if (!safePatches.length) return;
522
608
  const updateImmutable = internal.updateImmutable;
523
609
  if (!syncImmutable) internal.updateImmutable = void 0;
@@ -527,6 +613,12 @@ const replaceExternalStoreState = (store, internal, source, { syncImmutable = tr
527
613
  internal.updateImmutable = updateImmutable;
528
614
  }
529
615
  internal.emitPatches?.(safePatches);
616
+ publishStoreCommit(store, {
617
+ state: internal.rootState,
618
+ patches: safePatches,
619
+ inversePatches: safeInversePatches,
620
+ source: "external"
621
+ });
530
622
  };
531
623
  //#endregion
532
624
  //#region packages/core/src/wrapStore.ts
@@ -545,4 +637,4 @@ const wrapStore = (store, getState = () => store.getState()) => {
545
637
  return Object.assign({ [name]: (...args) => getState(...args) }[name], _store);
546
638
  };
547
639
  //#endregion
548
- export { StateSchemaError, applyMutableAdapterPatches, applyRootReplacementWithPatches, createBinder, createReactiveTracker, createRootReplacementPatches, defineExternalStoreAdapter, getMutableAdapterOwnEnumerableKeys, isEqualMutableAdapterSnapshot, isMutableAdapterUnsafeKey, isStateSchemaError, onStoreReady, replaceExternalStoreState, replaceMutableAdapterState, replaceOwnEnumerable, sanitizeInitialStateValue, sanitizeReplacementState, snapshotMutableAdapterPureState, toMutableAdapterSnapshot, wrapStore };
640
+ export { StateSchemaError, applyMutableAdapterPatches, applyRootReplacementWithPatches, createBinder, createReactiveTracker, createRootReplacementPatches, defineExternalStoreAdapter, getMutableAdapterOwnEnumerableKeys, isEqualMutableAdapterSnapshot, isMutableAdapterUnsafeKey, isStateSchemaError, onStoreCommit, onStoreCommitPrepare, onStoreReady, replaceExternalStoreState, replaceMutableAdapterState, replaceOwnEnumerable, replayStorePatches, sanitizeInitialStateValue, sanitizeReplacementState, snapshotMutableAdapterPureState, toMutableAdapterSnapshot, wrapStore };