coaction 2.0.0 → 3.0.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.
@@ -0,0 +1,548 @@
1
+ import { apply, create } from "mutative";
2
+ import { setActiveSub } from "alien-signals";
3
+ import * as alienSignalsSystem from "alien-signals/system";
4
+ //#region packages/core/src/global.ts
5
+ const getGlobal = () => {
6
+ let _global;
7
+ if (typeof window !== "undefined") _global = window;
8
+ else if (typeof global !== "undefined") _global = global;
9
+ else if (typeof self !== "undefined") _global = self;
10
+ else _global = {};
11
+ return _global;
12
+ };
13
+ getGlobal().SharedWorkerGlobalScope || globalThis.WorkerGlobalScope;
14
+ const bindSymbol = Symbol("bind");
15
+ //#endregion
16
+ //#region packages/core/src/binder.ts
17
+ const createExternalStoreAdapter = ({ handleState, handleStore }) => ((state) => {
18
+ const { copyState, key, bind } = handleState(state);
19
+ const value = typeof key !== "undefined" ? copyState[key] : copyState;
20
+ Object.defineProperty(value, bindSymbol, {
21
+ configurable: true,
22
+ enumerable: typeof key !== "undefined",
23
+ value: {
24
+ handleStore,
25
+ bind
26
+ }
27
+ });
28
+ return copyState;
29
+ });
30
+ /**
31
+ * Build an adapter helper for bridging an external store implementation into
32
+ * Coaction.
33
+ *
34
+ * @remarks
35
+ * Import this compatibility helper from `coaction/adapter`.
36
+ *
37
+ * Official bindings use this to integrate stores such as Redux, Jotai, Pinia,
38
+ * Zustand, MobX, and Valtio. Binder-backed integrations are whole-store
39
+ * adapters; they are not compatible with Coaction slices mode.
40
+ */
41
+ function createBinder({ handleState, handleStore }) {
42
+ return createExternalStoreAdapter({
43
+ handleState,
44
+ handleStore
45
+ });
46
+ }
47
+ /**
48
+ * Define a whole-store adapter for integrating an external state runtime with
49
+ * Coaction.
50
+ *
51
+ * @remarks
52
+ * Import this helper from `coaction/adapter`. `createBinder()` remains as a
53
+ * compatibility alias for existing official and community integrations.
54
+ */
55
+ function defineExternalStoreAdapter(options) {
56
+ return createExternalStoreAdapter(options);
57
+ }
58
+ //#endregion
59
+ //#region packages/core/src/utils.ts
60
+ const isUnsafeKey = (key) => key === "__proto__" || key === "prototype" || key === "constructor";
61
+ const isUnsafePathSegment = (segment) => typeof segment === "string" && isUnsafeKey(segment);
62
+ var UnsafePatchPathError = class extends Error {
63
+ name = "UnsafePatchPathError";
64
+ };
65
+ var StateSchemaError = class extends Error {
66
+ name = "StateSchemaError";
67
+ };
68
+ const isStateSchemaError = (error) => error instanceof StateSchemaError || error instanceof Error && error.name === "StateSchemaError";
69
+ const hasUnsafePatchPath = (path) => {
70
+ return (Array.isArray(path) ? path : typeof path === "string" ? path.split("/").filter(Boolean).map((segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~")) : []).some(isUnsafePathSegment);
71
+ };
72
+ const formatPatchPath = (path) => Array.isArray(path) ? path.map((segment) => String(segment)).join(".") : String(path);
73
+ const getUnsafePatchPaths = (patches) => patches?.filter((patch) => hasUnsafePatchPath(patch.path)) ?? [];
74
+ const assertSafePatches = (patches, source = "patches") => {
75
+ const unsafePatches = getUnsafePatchPaths(patches);
76
+ if (!unsafePatches.length) return;
77
+ const paths = unsafePatches.map((patch) => `'${formatPatchPath(patch.path)}'`).join(", ");
78
+ throw new UnsafePatchPathError(`Unsafe patch path${unsafePatches.length > 1 ? "s" : ""} ${paths} cannot be applied from ${source}.`);
79
+ };
80
+ const warnDroppedUnsafePatches = (unsafePatches, source) => {
81
+ if (process.env.NODE_ENV !== "development" || !unsafePatches.length) return;
82
+ const paths = unsafePatches.map((patch) => `'${formatPatchPath(patch.path)}'`).join(", ");
83
+ console.warn(`Coaction dropped unsafe patch path${unsafePatches.length > 1 ? "s" : ""} ${paths} from ${source}.`);
84
+ };
85
+ const sanitizePatches = (patches, options = {}) => {
86
+ if (options.warnOnDropped) warnDroppedUnsafePatches(getUnsafePatchPaths(patches), options.source ?? "patches");
87
+ return patches?.filter((patch) => !hasUnsafePatchPath(patch.path)).map((patch) => Object.prototype.hasOwnProperty.call(patch, "value") ? {
88
+ ...patch,
89
+ value: sanitizeReplacementState(patch.value)
90
+ } : patch);
91
+ };
92
+ const sanitizeCheckedPatches = (patches, source) => {
93
+ assertSafePatches(patches, source);
94
+ return sanitizePatches(patches) ?? [];
95
+ };
96
+ const createRootReplacementPatches = (currentState, nextState) => {
97
+ const patches = [];
98
+ const inversePatches = [];
99
+ const nextKeys = new Set(getOwnEnumerableKeys(nextState));
100
+ for (const key of getOwnEnumerableKeys(currentState)) {
101
+ if (typeof key === "string" && isUnsafeKey(key)) continue;
102
+ if (nextKeys.has(key)) continue;
103
+ patches.push({
104
+ op: "remove",
105
+ path: [key]
106
+ });
107
+ inversePatches.push({
108
+ op: "add",
109
+ path: [key],
110
+ value: currentState[key]
111
+ });
112
+ }
113
+ for (const key of nextKeys) {
114
+ if (typeof key === "string" && isUnsafeKey(key)) continue;
115
+ if (!Object.prototype.hasOwnProperty.call(currentState, key)) {
116
+ patches.push({
117
+ op: "add",
118
+ path: [key],
119
+ value: nextState[key]
120
+ });
121
+ inversePatches.push({
122
+ op: "remove",
123
+ path: [key]
124
+ });
125
+ continue;
126
+ }
127
+ if (Object.is(currentState[key], nextState[key])) continue;
128
+ patches.push({
129
+ op: "replace",
130
+ path: [key],
131
+ value: nextState[key]
132
+ });
133
+ inversePatches.push({
134
+ op: "replace",
135
+ path: [key],
136
+ value: currentState[key]
137
+ });
138
+ }
139
+ return {
140
+ patches,
141
+ inversePatches
142
+ };
143
+ };
144
+ const createRootStateFromPatches = (currentState, patches) => {
145
+ const nextState = sanitizeReplacementState(currentState);
146
+ const seen = /* @__PURE__ */ new WeakMap();
147
+ for (const patch of patches) {
148
+ if (!Array.isArray(patch.path) || patch.path.length !== 1 || ![
149
+ "add",
150
+ "remove",
151
+ "replace"
152
+ ].includes(patch.op)) return;
153
+ const key = patch.path[0];
154
+ if (patch.op === "remove") {
155
+ delete nextState[key];
156
+ continue;
157
+ }
158
+ nextState[key] = sanitizeReplacementState(patch.value, seen);
159
+ }
160
+ return nextState;
161
+ };
162
+ const applyRootReplacementWithPatches = (store, nextState, options = {}) => {
163
+ const { patches, inversePatches } = createRootReplacementPatches(store.getPureState(), nextState);
164
+ const finalPatches = store.patch ? store.patch({
165
+ patches,
166
+ inversePatches
167
+ }) : {
168
+ patches,
169
+ inversePatches
170
+ };
171
+ const safePatches = sanitizeCheckedPatches(finalPatches.patches, "store.patch()");
172
+ const safeInversePatches = sanitizeCheckedPatches(finalPatches.inversePatches, "store.patch() inverse patches");
173
+ if (safePatches.length) {
174
+ const applyExactReplacement = options.applyExactReplacement;
175
+ const exactReplacementState = applyExactReplacement ? createRootStateFromPatches(store.getPureState(), safePatches) : void 0;
176
+ if (applyExactReplacement && exactReplacementState) applyExactReplacement(exactReplacementState);
177
+ else store.apply(store.getPureState(), safePatches);
178
+ }
179
+ return [
180
+ store.getPureState(),
181
+ safePatches,
182
+ safeInversePatches
183
+ ];
184
+ };
185
+ const setOwnEnumerable = (target, key, value) => {
186
+ if (typeof key === "string" && isUnsafeKey(key)) return;
187
+ target[key] = value;
188
+ };
189
+ const getOwnEnumerableKeys = (source) => {
190
+ if (typeof source !== "object" || source === null) return [];
191
+ return Reflect.ownKeys(source).filter((key) => Object.prototype.propertyIsEnumerable.call(source, key));
192
+ };
193
+ const isArrayIndexKey$1 = (key) => {
194
+ if (typeof key !== "string") return false;
195
+ const index = Number(key);
196
+ return Number.isInteger(index) && index >= 0 && index < 2 ** 32 - 1 && String(index) === key;
197
+ };
198
+ const replaceOwnEnumerable = (target, source) => {
199
+ const seen = /* @__PURE__ */ new WeakMap();
200
+ seen.set(source, target);
201
+ const nextKeys = /* @__PURE__ */ new Set();
202
+ for (const key of getOwnEnumerableKeys(source)) {
203
+ if (typeof key === "string" && isUnsafeKey(key)) continue;
204
+ if (typeof source[key] === "function") continue;
205
+ nextKeys.add(key);
206
+ }
207
+ for (const key of getOwnEnumerableKeys(target)) if (!nextKeys.has(key)) delete target[key];
208
+ nextKeys.forEach((key) => {
209
+ setOwnEnumerable(target, key, sanitizeReplacementState(source[key], seen));
210
+ });
211
+ };
212
+ const sanitizeReplacementState = (source, seen = /* @__PURE__ */ new WeakMap()) => {
213
+ if (typeof source !== "object" || source === null) return source;
214
+ const cached = seen.get(source);
215
+ if (cached) return cached;
216
+ if (Array.isArray(source)) {
217
+ const target = [];
218
+ target.length = source.length;
219
+ seen.set(source, target);
220
+ for (let index = 0; index < source.length; index += 1) if (Object.prototype.hasOwnProperty.call(source, index)) target[index] = sanitizeReplacementState(source[index], seen);
221
+ for (const key of getOwnEnumerableKeys(source)) {
222
+ if (isArrayIndexKey$1(key) || typeof key === "string" && isUnsafeKey(key)) continue;
223
+ const value = source[key];
224
+ if (typeof value === "function") continue;
225
+ setOwnEnumerable(target, key, sanitizeReplacementState(value, seen));
226
+ }
227
+ return target;
228
+ }
229
+ const prototype = Object.getPrototypeOf(source);
230
+ if (prototype !== Object.prototype && prototype !== null) return source;
231
+ const target = Object.create(prototype);
232
+ seen.set(source, target);
233
+ for (const key of getOwnEnumerableKeys(source)) {
234
+ if (typeof key === "string" && isUnsafeKey(key)) continue;
235
+ const value = source[key];
236
+ if (typeof value === "function") continue;
237
+ setOwnEnumerable(target, key, sanitizeReplacementState(value, seen));
238
+ }
239
+ return target;
240
+ };
241
+ const sanitizeInitialStateValue = (source, seen = /* @__PURE__ */ new WeakMap()) => {
242
+ if (typeof source !== "object" || source === null) return source;
243
+ const cached = seen.get(source);
244
+ if (cached) return cached;
245
+ if (Array.isArray(source)) {
246
+ const target = [];
247
+ target.length = source.length;
248
+ seen.set(source, target);
249
+ for (let index = 0; index < source.length; index += 1) if (Object.prototype.hasOwnProperty.call(source, index)) target[index] = sanitizeInitialStateValue(source[index], seen);
250
+ for (const key of getOwnEnumerableKeys(source)) {
251
+ if (isArrayIndexKey$1(key) || typeof key === "string" && isUnsafeKey(key)) continue;
252
+ setOwnEnumerable(target, key, sanitizeInitialStateValue(source[key], seen));
253
+ }
254
+ return target;
255
+ }
256
+ const prototype = Object.getPrototypeOf(source);
257
+ if (prototype !== Object.prototype && prototype !== null) return source;
258
+ const target = Object.create(prototype);
259
+ seen.set(source, target);
260
+ for (const key of getOwnEnumerableKeys(source)) {
261
+ if (typeof key === "string" && isUnsafeKey(key)) continue;
262
+ setOwnEnumerable(target, key, sanitizeInitialStateValue(source[key], seen));
263
+ }
264
+ return target;
265
+ };
266
+ //#endregion
267
+ //#region packages/core/src/externalMutableAdapterUtils.ts
268
+ const getMutableAdapterOwnEnumerableKeys = (value) => Reflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key));
269
+ const isMutableAdapterUnsafeKey = (key) => typeof key === "string" && isUnsafeKey(key);
270
+ const isArrayIndexKey = (key) => {
271
+ if (typeof key !== "string") return false;
272
+ const index = Number(key);
273
+ return Number.isInteger(index) && index >= 0 && index < 2 ** 32 - 1 && String(index) === key;
274
+ };
275
+ const isObjectRecord = (value) => Object.prototype.toString.call(value) === "[object Object]";
276
+ const assertCanSetMutableAdapterPublicStateKey = (publicState, key) => {
277
+ if (Object.prototype.hasOwnProperty.call(publicState, key)) return;
278
+ if (Object.isExtensible(publicState)) return;
279
+ throw new StateSchemaError(`Unknown state key '${String(key)}' cannot be added after store initialization. Coaction state schema is fixed.`);
280
+ };
281
+ const ensureMutableAdapterRawDescriptor = (rawState, mutableState, publicState, key) => {
282
+ if (rawState === mutableState) return;
283
+ const rawDescriptor = Object.getOwnPropertyDescriptor(rawState, key);
284
+ if (rawDescriptor?.get && rawDescriptor.set) return;
285
+ const publicDescriptor = Object.getOwnPropertyDescriptor(publicState, key);
286
+ if (!publicDescriptor || rawDescriptor?.configurable === false) return;
287
+ Object.defineProperty(rawState, key, {
288
+ get: () => mutableState[key],
289
+ set: (value) => {
290
+ mutableState[key] = value;
291
+ },
292
+ configurable: true,
293
+ enumerable: publicDescriptor.enumerable
294
+ });
295
+ };
296
+ const replaceMutableAdapterState = (rawState, mutableState, publicState, source) => {
297
+ const nextKeys = /* @__PURE__ */ new Set();
298
+ for (const key of getMutableAdapterOwnEnumerableKeys(source)) {
299
+ if (isMutableAdapterUnsafeKey(key)) continue;
300
+ if (typeof source[key] === "function") continue;
301
+ nextKeys.add(key);
302
+ }
303
+ nextKeys.forEach((key) => {
304
+ assertCanSetMutableAdapterPublicStateKey(publicState, key);
305
+ });
306
+ for (const key of getMutableAdapterOwnEnumerableKeys(rawState)) {
307
+ if (isMutableAdapterUnsafeKey(key)) {
308
+ delete rawState[key];
309
+ delete mutableState[key];
310
+ continue;
311
+ }
312
+ if (typeof rawState[key] === "function") continue;
313
+ if (!nextKeys.has(key)) {
314
+ delete rawState[key];
315
+ delete mutableState[key];
316
+ }
317
+ }
318
+ const rawSeen = /* @__PURE__ */ new WeakMap();
319
+ const mutableSeen = /* @__PURE__ */ new WeakMap();
320
+ const publicSeen = /* @__PURE__ */ new WeakMap();
321
+ rawSeen.set(source, rawState);
322
+ mutableSeen.set(source, mutableState);
323
+ publicSeen.set(source, publicState);
324
+ nextKeys.forEach((key) => {
325
+ ensureMutableAdapterRawDescriptor(rawState, mutableState, publicState, key);
326
+ rawState[key] = sanitizeReplacementState(source[key], rawSeen);
327
+ mutableState[key] = sanitizeReplacementState(source[key], mutableSeen);
328
+ publicState[key] = sanitizeReplacementState(source[key], publicSeen);
329
+ });
330
+ };
331
+ const applyMutableAdapterPatches = (baseState, patches, rawState, mutableState, publicState, validateState) => {
332
+ assertSafePatches(patches, "mutable adapter apply()");
333
+ const nextState = apply(toMutableAdapterSnapshot(baseState === publicState ? rawState : baseState), patches);
334
+ validateState?.(nextState);
335
+ replaceMutableAdapterState(rawState, mutableState, publicState, nextState);
336
+ };
337
+ const toMutableAdapterSnapshot = (value, visited = /* @__PURE__ */ new WeakMap()) => {
338
+ if (Array.isArray(value)) {
339
+ if (visited.has(value)) return visited.get(value);
340
+ const next = [];
341
+ next.length = value.length;
342
+ visited.set(value, next);
343
+ for (let index = 0; index < value.length; index += 1) if (Object.prototype.hasOwnProperty.call(value, index)) next[index] = toMutableAdapterSnapshot(value[index], visited);
344
+ const source = value;
345
+ const target = next;
346
+ for (const key of getMutableAdapterOwnEnumerableKeys(value)) {
347
+ if (isArrayIndexKey(key) || isMutableAdapterUnsafeKey(key)) continue;
348
+ const child = source[key];
349
+ if (typeof child !== "function") target[key] = toMutableAdapterSnapshot(child, visited);
350
+ }
351
+ return next;
352
+ }
353
+ if (typeof value === "object" && value !== null) {
354
+ if (!isObjectRecord(value)) return value;
355
+ if (visited.has(value)) return visited.get(value);
356
+ const next = {};
357
+ visited.set(value, next);
358
+ for (const key of getMutableAdapterOwnEnumerableKeys(value)) {
359
+ if (isMutableAdapterUnsafeKey(key)) continue;
360
+ const child = value[key];
361
+ if (typeof child !== "function") next[key] = toMutableAdapterSnapshot(child, visited);
362
+ }
363
+ return next;
364
+ }
365
+ return value;
366
+ };
367
+ const snapshotMutableAdapterPureState = (store) => toMutableAdapterSnapshot(store.getPureState());
368
+ const isEqualMutableAdapterSnapshot = (left, right, visited = /* @__PURE__ */ new WeakMap()) => {
369
+ if (Object.is(left, right)) return true;
370
+ if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) return false;
371
+ const leftIsArray = Array.isArray(left);
372
+ const rightIsArray = Array.isArray(right);
373
+ if (leftIsArray || rightIsArray) {
374
+ if (!leftIsArray || !rightIsArray || left.length !== right.length) return false;
375
+ } else if (!isObjectRecord(left) || !isObjectRecord(right)) return false;
376
+ let seenTargets = visited.get(left);
377
+ if (!seenTargets) {
378
+ seenTargets = /* @__PURE__ */ new WeakSet();
379
+ visited.set(left, seenTargets);
380
+ } else if (seenTargets.has(right)) return true;
381
+ seenTargets.add(right);
382
+ const leftRecord = left;
383
+ const rightRecord = right;
384
+ const leftKeys = getMutableAdapterOwnEnumerableKeys(left);
385
+ const rightKeys = getMutableAdapterOwnEnumerableKeys(right);
386
+ if (leftKeys.length !== rightKeys.length) return false;
387
+ for (const key of leftKeys) {
388
+ if (!Object.prototype.hasOwnProperty.call(rightRecord, key)) return false;
389
+ if (!isEqualMutableAdapterSnapshot(leftRecord[key], rightRecord[key], visited)) return false;
390
+ }
391
+ return true;
392
+ };
393
+ //#endregion
394
+ //#region packages/core/src/reactiveTracker.ts
395
+ const ReactiveFlags = alienSignalsSystem.ReactiveFlags;
396
+ const unwatch = (node) => {
397
+ if (!(node.flags & ReactiveFlags.Mutable)) {
398
+ node.depsTail = void 0;
399
+ node.flags = 0;
400
+ purgeDeps(node);
401
+ const sub = node.subs;
402
+ if (sub !== void 0) unlink(sub);
403
+ return;
404
+ }
405
+ if (node.depsTail !== void 0) {
406
+ node.depsTail = void 0;
407
+ node.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty;
408
+ purgeDeps(node);
409
+ }
410
+ };
411
+ const unlink = (link, sub = link.sub) => {
412
+ const dep = link.dep;
413
+ const prevDep = link.prevDep;
414
+ const nextDep = link.nextDep;
415
+ const nextSub = link.nextSub;
416
+ const prevSub = link.prevSub;
417
+ if (nextDep !== void 0) nextDep.prevDep = prevDep;
418
+ else sub.depsTail = prevDep;
419
+ if (prevDep !== void 0) prevDep.nextDep = nextDep;
420
+ else sub.deps = nextDep;
421
+ if (nextSub !== void 0) nextSub.prevSub = prevSub;
422
+ else dep.subsTail = prevSub;
423
+ if (prevSub !== void 0) prevSub.nextSub = nextSub;
424
+ else if ((dep.subs = nextSub) === void 0) unwatch(dep);
425
+ return nextDep;
426
+ };
427
+ const purgeDeps = (sub) => {
428
+ const depsTail = sub.depsTail;
429
+ let dep = depsTail !== void 0 ? depsTail.nextDep : sub.deps;
430
+ while (dep !== void 0) dep = unlink(dep, sub);
431
+ };
432
+ /**
433
+ * Create a low-level signal dependency tracker for framework adapters.
434
+ *
435
+ * @remarks
436
+ * Adapter and framework authors import this helper from `coaction/adapter`.
437
+ */
438
+ const createReactiveTracker = () => {
439
+ let version = 0;
440
+ let disposed = false;
441
+ const listeners = /* @__PURE__ */ new Set();
442
+ const node = {
443
+ deps: void 0,
444
+ depsTail: void 0,
445
+ subs: void 0,
446
+ subsTail: void 0,
447
+ flags: ReactiveFlags.Watching,
448
+ fn: () => {
449
+ if (disposed) return;
450
+ version += 1;
451
+ listeners.forEach((listener) => listener());
452
+ }
453
+ };
454
+ const dispose = () => {
455
+ if (disposed) return;
456
+ disposed = true;
457
+ listeners.clear();
458
+ node.depsTail = void 0;
459
+ purgeDeps(node);
460
+ node.flags = 0;
461
+ };
462
+ return {
463
+ getSnapshot: () => version,
464
+ subscribe(listener) {
465
+ if (disposed) return () => void 0;
466
+ listeners.add(listener);
467
+ return () => {
468
+ listeners.delete(listener);
469
+ };
470
+ },
471
+ track(fn) {
472
+ if (disposed) return fn();
473
+ node.depsTail = void 0;
474
+ node.flags = ReactiveFlags.Watching | ReactiveFlags.RecursedCheck;
475
+ const prevSub = setActiveSub(node);
476
+ try {
477
+ return fn();
478
+ } finally {
479
+ setActiveSub(prevSub);
480
+ node.flags &= ~ReactiveFlags.RecursedCheck;
481
+ purgeDeps(node);
482
+ }
483
+ },
484
+ dispose
485
+ };
486
+ };
487
+ //#endregion
488
+ //#region packages/core/src/lifecycle.ts
489
+ const readyStores = /* @__PURE__ */ new WeakSet();
490
+ const readyCallbacks = /* @__PURE__ */ new WeakMap();
491
+ const onStoreReady = (store, callback) => {
492
+ if (readyStores.has(store)) {
493
+ callback();
494
+ return () => void 0;
495
+ }
496
+ let callbacks = readyCallbacks.get(store);
497
+ if (!callbacks) {
498
+ callbacks = /* @__PURE__ */ new Set();
499
+ readyCallbacks.set(store, callbacks);
500
+ }
501
+ callbacks.add(callback);
502
+ return () => {
503
+ callbacks?.delete(callback);
504
+ };
505
+ };
506
+ //#endregion
507
+ //#region packages/core/src/replaceExternalStoreState.ts
508
+ const replaceExternalStoreState = (store, internal, source, { syncImmutable = true } = {}) => {
509
+ internal.validateReplacementSource?.(source);
510
+ const [nextState, patches, inversePatches] = create(internal.rootState, (draft) => {
511
+ replaceOwnEnumerable(draft, source);
512
+ }, { enablePatches: true });
513
+ internal.validateState?.(nextState);
514
+ const safePatches = sanitizeCheckedPatches((store.patch ? store.patch({
515
+ patches,
516
+ inversePatches
517
+ }) : {
518
+ patches,
519
+ inversePatches
520
+ }).patches, "store.patch()");
521
+ if (!safePatches.length) return;
522
+ const updateImmutable = internal.updateImmutable;
523
+ if (!syncImmutable) internal.updateImmutable = void 0;
524
+ try {
525
+ store.apply(internal.rootState, safePatches);
526
+ } finally {
527
+ internal.updateImmutable = updateImmutable;
528
+ }
529
+ internal.emitPatches?.(safePatches);
530
+ };
531
+ //#endregion
532
+ //#region packages/core/src/wrapStore.ts
533
+ /**
534
+ * Convert a store object into Coaction's callable store shape.
535
+ *
536
+ * @remarks
537
+ * Framework bindings use this to attach selector-aware readers while
538
+ * preserving the underlying store API on the returned function object. Most
539
+ * applications should use a public `create` entry instead of calling
540
+ * `wrapStore()` directly. Framework authors import this helper from
541
+ * `coaction/local` or `coaction/adapter`.
542
+ */
543
+ const wrapStore = (store, getState = () => store.getState()) => {
544
+ const { name, ..._store } = store;
545
+ return Object.assign({ [name]: (...args) => getState(...args) }[name], _store);
546
+ };
547
+ //#endregion
548
+ export { StateSchemaError, applyMutableAdapterPatches, applyRootReplacementWithPatches, createBinder, createReactiveTracker, createRootReplacementPatches, defineExternalStoreAdapter, getMutableAdapterOwnEnumerableKeys, isEqualMutableAdapterSnapshot, isMutableAdapterUnsafeKey, isStateSchemaError, onStoreReady, replaceExternalStoreState, replaceMutableAdapterState, replaceOwnEnumerable, sanitizeInitialStateValue, sanitizeReplacementState, snapshotMutableAdapterPureState, toMutableAdapterSnapshot, wrapStore };