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.
- package/dist/adapter.d.mts +45 -1
- package/dist/adapter.d.ts +45 -1
- package/dist/adapter.js +108 -13
- package/dist/adapter.mjs +106 -14
- package/dist/index.js +239 -25
- package/dist/index.mjs +239 -25
- package/dist/local.js +239 -25
- package/dist/local.mjs +239 -25
- package/dist/shared.js +239 -25
- package/dist/shared.mjs +239 -25
- package/package.json +1 -1
package/dist/adapter.d.mts
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.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
|
|
514
|
-
const
|
|
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
|
-
|
|
532
|
+
const runtime = getStoreReadyRuntime(store, true);
|
|
533
|
+
if (runtime.ready) {
|
|
517
534
|
callback();
|
|
518
535
|
return () => void 0;
|
|
519
536
|
}
|
|
520
|
-
|
|
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
|
|
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
|
|
622
|
+
const finalPatches = store.patch ? store.patch({
|
|
539
623
|
patches,
|
|
540
624
|
inversePatches
|
|
541
625
|
}) : {
|
|
542
626
|
patches,
|
|
543
627
|
inversePatches
|
|
544
|
-
}
|
|
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
|
|
490
|
-
const
|
|
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
|
-
|
|
508
|
+
const runtime = getStoreReadyRuntime(store, true);
|
|
509
|
+
if (runtime.ready) {
|
|
493
510
|
callback();
|
|
494
511
|
return () => void 0;
|
|
495
512
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
callbacks
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
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
|
-
|
|
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
|
|
598
|
+
const finalPatches = store.patch ? store.patch({
|
|
515
599
|
patches,
|
|
516
600
|
inversePatches
|
|
517
601
|
}) : {
|
|
518
602
|
patches,
|
|
519
603
|
inversePatches
|
|
520
|
-
}
|
|
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 };
|