coaction 2.1.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/README.md +28 -4
- package/adapter.d.ts +1 -0
- package/adapter.js +3 -0
- package/dist/adapter.d.mts +512 -0
- package/dist/adapter.d.ts +512 -0
- package/dist/adapter.js +686 -0
- package/dist/adapter.mjs +640 -0
- package/dist/index.d.mts +36 -216
- package/dist/index.d.ts +36 -216
- package/dist/index.js +1350 -1025
- package/dist/index.mjs +1353 -991
- package/dist/local.d.mts +344 -0
- package/dist/local.d.ts +344 -0
- package/dist/local.js +1421 -0
- package/dist/local.mjs +1352 -0
- package/dist/shared.d.mts +446 -0
- package/dist/shared.d.ts +446 -0
- package/dist/shared.js +2190 -0
- package/dist/shared.mjs +2114 -0
- package/local.d.ts +1 -0
- package/local.js +3 -0
- package/package.json +41 -2
- package/shared.d.ts +1 -0
- package/shared.js +3 -0
package/dist/index.js
CHANGED
|
@@ -1,58 +1,65 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
//#region \0rolldown/runtime.js
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
-
key = keys[i];
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
-
get: ((k) => from[k]).bind(null, key),
|
|
14
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
-
value: mod,
|
|
21
|
-
enumerable: true
|
|
22
|
-
}) : target, mod));
|
|
23
|
-
//#endregion
|
|
24
|
-
let mutative = require("mutative");
|
|
25
2
|
let data_transport = require("data-transport");
|
|
26
3
|
let alien_signals = require("alien-signals");
|
|
27
|
-
let
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
let _global;
|
|
32
|
-
if (typeof window !== "undefined") _global = window;
|
|
33
|
-
else if (typeof global !== "undefined") _global = global;
|
|
34
|
-
else if (typeof self !== "undefined") _global = self;
|
|
35
|
-
else _global = {};
|
|
36
|
-
return _global;
|
|
4
|
+
let mutative = require("mutative");
|
|
5
|
+
//#region packages/core/src/lifecycle.ts
|
|
6
|
+
const reportLifecycleError = (error) => {
|
|
7
|
+
if (process.env.NODE_ENV === "development") console.error(error);
|
|
37
8
|
};
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
9
|
+
const tryDestroyStore = (store) => {
|
|
10
|
+
try {
|
|
11
|
+
store.destroy?.();
|
|
12
|
+
} catch (error) {
|
|
13
|
+
reportLifecycleError(error);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const failStoreSetup = (store, error) => {
|
|
17
|
+
tryDestroyStore(store);
|
|
18
|
+
throw error;
|
|
19
|
+
};
|
|
20
|
+
const failTransportInitialization = (transport, error) => {
|
|
21
|
+
try {
|
|
22
|
+
transport?.dispose?.();
|
|
23
|
+
} catch (disposeError) {
|
|
24
|
+
reportLifecycleError(disposeError);
|
|
25
|
+
}
|
|
26
|
+
throw error;
|
|
27
|
+
};
|
|
28
|
+
const storeReadyRuntimeSymbol = Symbol.for("coaction.lifecycle.ready");
|
|
29
|
+
const getStoreReadyRuntime = (store, create = false) => {
|
|
30
|
+
const target = store;
|
|
31
|
+
const existing = target[storeReadyRuntimeSymbol];
|
|
32
|
+
if (existing || !create) return existing;
|
|
33
|
+
const runtime = {
|
|
34
|
+
callbacks: /* @__PURE__ */ new Set(),
|
|
35
|
+
ready: false
|
|
36
|
+
};
|
|
37
|
+
Object.defineProperty(target, storeReadyRuntimeSymbol, {
|
|
38
|
+
configurable: true,
|
|
39
|
+
enumerable: true,
|
|
40
|
+
value: runtime,
|
|
41
|
+
writable: true
|
|
42
|
+
});
|
|
43
|
+
return runtime;
|
|
44
|
+
};
|
|
45
|
+
const onStoreReady = (store, callback) => {
|
|
46
|
+
const runtime = getStoreReadyRuntime(store, true);
|
|
47
|
+
if (runtime.ready) {
|
|
48
|
+
callback();
|
|
49
|
+
return () => void 0;
|
|
50
|
+
}
|
|
51
|
+
runtime.callbacks.add(callback);
|
|
52
|
+
return () => {
|
|
53
|
+
runtime.callbacks.delete(callback);
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
const markStoreReady = (store) => {
|
|
57
|
+
const runtime = getStoreReadyRuntime(store, true);
|
|
58
|
+
if (runtime.ready) return;
|
|
59
|
+
runtime.ready = true;
|
|
60
|
+
const callbacks = [...runtime.callbacks];
|
|
61
|
+
runtime.callbacks.clear();
|
|
62
|
+
callbacks.forEach((callback) => callback());
|
|
56
63
|
};
|
|
57
64
|
//#endregion
|
|
58
65
|
//#region packages/core/src/utils.ts
|
|
@@ -87,9 +94,10 @@ const warnDroppedUnsafePatches = (unsafePatches, source) => {
|
|
|
87
94
|
};
|
|
88
95
|
const sanitizePatches = (patches, options = {}) => {
|
|
89
96
|
if (options.warnOnDropped) warnDroppedUnsafePatches(getUnsafePatchPaths(patches), options.source ?? "patches");
|
|
97
|
+
const seen = /* @__PURE__ */ new WeakMap();
|
|
90
98
|
return patches?.filter((patch) => !hasUnsafePatchPath(patch.path)).map((patch) => Object.prototype.hasOwnProperty.call(patch, "value") ? {
|
|
91
99
|
...patch,
|
|
92
|
-
value: sanitizeReplacementState(patch.value)
|
|
100
|
+
value: sanitizeReplacementState(patch.value, seen)
|
|
93
101
|
} : patch);
|
|
94
102
|
};
|
|
95
103
|
const sanitizeCheckedPatches = (patches, source) => {
|
|
@@ -144,47 +152,6 @@ const createRootReplacementPatches = (currentState, nextState) => {
|
|
|
144
152
|
inversePatches
|
|
145
153
|
};
|
|
146
154
|
};
|
|
147
|
-
const createRootStateFromPatches = (currentState, patches) => {
|
|
148
|
-
const nextState = sanitizeReplacementState(currentState);
|
|
149
|
-
const seen = /* @__PURE__ */ new WeakMap();
|
|
150
|
-
for (const patch of patches) {
|
|
151
|
-
if (!Array.isArray(patch.path) || patch.path.length !== 1 || ![
|
|
152
|
-
"add",
|
|
153
|
-
"remove",
|
|
154
|
-
"replace"
|
|
155
|
-
].includes(patch.op)) return;
|
|
156
|
-
const key = patch.path[0];
|
|
157
|
-
if (patch.op === "remove") {
|
|
158
|
-
delete nextState[key];
|
|
159
|
-
continue;
|
|
160
|
-
}
|
|
161
|
-
nextState[key] = sanitizeReplacementState(patch.value, seen);
|
|
162
|
-
}
|
|
163
|
-
return nextState;
|
|
164
|
-
};
|
|
165
|
-
const applyRootReplacementWithPatches = (store, nextState, options = {}) => {
|
|
166
|
-
const { patches, inversePatches } = createRootReplacementPatches(store.getPureState(), nextState);
|
|
167
|
-
const finalPatches = store.patch ? store.patch({
|
|
168
|
-
patches,
|
|
169
|
-
inversePatches
|
|
170
|
-
}) : {
|
|
171
|
-
patches,
|
|
172
|
-
inversePatches
|
|
173
|
-
};
|
|
174
|
-
const safePatches = sanitizeCheckedPatches(finalPatches.patches, "store.patch()");
|
|
175
|
-
const safeInversePatches = sanitizeCheckedPatches(finalPatches.inversePatches, "store.patch() inverse patches");
|
|
176
|
-
if (safePatches.length) {
|
|
177
|
-
const applyExactReplacement = options.applyExactReplacement;
|
|
178
|
-
const exactReplacementState = applyExactReplacement ? createRootStateFromPatches(store.getPureState(), safePatches) : void 0;
|
|
179
|
-
if (applyExactReplacement && exactReplacementState) applyExactReplacement(exactReplacementState);
|
|
180
|
-
else store.apply(store.getPureState(), safePatches);
|
|
181
|
-
}
|
|
182
|
-
return [
|
|
183
|
-
store.getPureState(),
|
|
184
|
-
safePatches,
|
|
185
|
-
safeInversePatches
|
|
186
|
-
];
|
|
187
|
-
};
|
|
188
155
|
const setOwnEnumerable = (target, key, value) => {
|
|
189
156
|
if (typeof key === "string" && isUnsafeKey(key)) return;
|
|
190
157
|
target[key] = value;
|
|
@@ -245,7 +212,7 @@ const assertKnownStateShape = (source, rootState, schema, isSliceStore, options
|
|
|
245
212
|
for (const sliceKey of getOwnEnumerableKeys(slice)) assertKnownSchemaKey(knownSliceKeys, sliceKey, [key]);
|
|
246
213
|
}
|
|
247
214
|
};
|
|
248
|
-
const isArrayIndexKey
|
|
215
|
+
const isArrayIndexKey = (key) => {
|
|
249
216
|
if (typeof key !== "string") return false;
|
|
250
217
|
const index = Number(key);
|
|
251
218
|
return Number.isInteger(index) && index >= 0 && index < 2 ** 32 - 1 && String(index) === key;
|
|
@@ -254,20 +221,6 @@ const assignOwnEnumerable = (target, source, seen = /* @__PURE__ */ new WeakMap(
|
|
|
254
221
|
if (!seen.has(source)) seen.set(source, target);
|
|
255
222
|
for (const key of getOwnEnumerableKeys(source)) setOwnEnumerable(target, key, sanitizeReplacementState(source[key], seen));
|
|
256
223
|
};
|
|
257
|
-
const replaceOwnEnumerable = (target, source) => {
|
|
258
|
-
const seen = /* @__PURE__ */ new WeakMap();
|
|
259
|
-
seen.set(source, target);
|
|
260
|
-
const nextKeys = /* @__PURE__ */ new Set();
|
|
261
|
-
for (const key of getOwnEnumerableKeys(source)) {
|
|
262
|
-
if (typeof key === "string" && isUnsafeKey(key)) continue;
|
|
263
|
-
if (typeof source[key] === "function") continue;
|
|
264
|
-
nextKeys.add(key);
|
|
265
|
-
}
|
|
266
|
-
for (const key of getOwnEnumerableKeys(target)) if (!nextKeys.has(key)) delete target[key];
|
|
267
|
-
nextKeys.forEach((key) => {
|
|
268
|
-
setOwnEnumerable(target, key, sanitizeReplacementState(source[key], seen));
|
|
269
|
-
});
|
|
270
|
-
};
|
|
271
224
|
const cloneOwnEnumerable = (source) => {
|
|
272
225
|
const target = {};
|
|
273
226
|
assignOwnEnumerable(target, source);
|
|
@@ -283,7 +236,7 @@ const sanitizeReplacementState = (source, seen = /* @__PURE__ */ new WeakMap())
|
|
|
283
236
|
seen.set(source, target);
|
|
284
237
|
for (let index = 0; index < source.length; index += 1) if (Object.prototype.hasOwnProperty.call(source, index)) target[index] = sanitizeReplacementState(source[index], seen);
|
|
285
238
|
for (const key of getOwnEnumerableKeys(source)) {
|
|
286
|
-
if (isArrayIndexKey
|
|
239
|
+
if (isArrayIndexKey(key) || typeof key === "string" && isUnsafeKey(key)) continue;
|
|
287
240
|
const value = source[key];
|
|
288
241
|
if (typeof value === "function") continue;
|
|
289
242
|
setOwnEnumerable(target, key, sanitizeReplacementState(value, seen));
|
|
@@ -312,7 +265,7 @@ const sanitizeInitialStateValue = (source, seen = /* @__PURE__ */ new WeakMap())
|
|
|
312
265
|
seen.set(source, target);
|
|
313
266
|
for (let index = 0; index < source.length; index += 1) if (Object.prototype.hasOwnProperty.call(source, index)) target[index] = sanitizeInitialStateValue(source[index], seen);
|
|
314
267
|
for (const key of getOwnEnumerableKeys(source)) {
|
|
315
|
-
if (isArrayIndexKey
|
|
268
|
+
if (isArrayIndexKey(key) || typeof key === "string" && isUnsafeKey(key)) continue;
|
|
316
269
|
setOwnEnumerable(target, key, sanitizeInitialStateValue(source[key], seen));
|
|
317
270
|
}
|
|
318
271
|
return target;
|
|
@@ -357,320 +310,628 @@ const uuid = () => {
|
|
|
357
310
|
});
|
|
358
311
|
};
|
|
359
312
|
//#endregion
|
|
313
|
+
//#region packages/core/src/computed.ts
|
|
314
|
+
const isObjectLike = (value) => typeof value === "object" && value !== null;
|
|
315
|
+
const runComputedRead = (internal, read) => {
|
|
316
|
+
internal.computedReadDepth = (internal.computedReadDepth ?? 0) + 1;
|
|
317
|
+
try {
|
|
318
|
+
return read();
|
|
319
|
+
} finally {
|
|
320
|
+
internal.computedReadDepth -= 1;
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
var Computed = class {
|
|
324
|
+
deps;
|
|
325
|
+
fn;
|
|
326
|
+
constructor(deps, fn) {
|
|
327
|
+
this.deps = deps;
|
|
328
|
+
this.fn = fn;
|
|
329
|
+
}
|
|
330
|
+
createGetter({ internal }) {
|
|
331
|
+
const memoByReceiver = /* @__PURE__ */ new WeakMap();
|
|
332
|
+
const lastArgs = /* @__PURE__ */ new WeakMap();
|
|
333
|
+
const lastResult = /* @__PURE__ */ new WeakMap();
|
|
334
|
+
const fallbackReceiver = {};
|
|
335
|
+
const evaluate = (receiver) => {
|
|
336
|
+
const args = this.deps(internal.module);
|
|
337
|
+
if (!lastArgs.has(receiver) || !areShallowEqualWithArray(lastArgs.get(receiver), args)) lastResult.set(receiver, this.fn.apply(receiver, args));
|
|
338
|
+
lastArgs.set(receiver, args);
|
|
339
|
+
return lastResult.get(receiver);
|
|
340
|
+
};
|
|
341
|
+
return function() {
|
|
342
|
+
const receiver = typeof this === "object" && this !== null ? this : fallbackReceiver;
|
|
343
|
+
if (internal.isBatching) return evaluate(receiver);
|
|
344
|
+
let accessor = memoByReceiver.get(receiver);
|
|
345
|
+
if (!accessor) {
|
|
346
|
+
accessor = (0, alien_signals.computed)(() => runComputedRead(internal, () => evaluate(receiver)));
|
|
347
|
+
memoByReceiver.set(receiver, accessor);
|
|
348
|
+
}
|
|
349
|
+
return accessor();
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
const createCachedGetter = (internal, getter) => {
|
|
354
|
+
const accessors = /* @__PURE__ */ new WeakMap();
|
|
355
|
+
const fallbackReceiver = {};
|
|
356
|
+
return function() {
|
|
357
|
+
const receiver = typeof this === "object" && this !== null ? this : fallbackReceiver;
|
|
358
|
+
if (internal.isBatching) return getter.call(receiver);
|
|
359
|
+
let accessor = accessors.get(receiver);
|
|
360
|
+
if (!accessor) {
|
|
361
|
+
accessor = (0, alien_signals.computed)(() => runComputedRead(internal, () => getter.call(receiver)));
|
|
362
|
+
accessors.set(receiver, accessor);
|
|
363
|
+
}
|
|
364
|
+
return accessor();
|
|
365
|
+
};
|
|
366
|
+
};
|
|
367
|
+
const createTrackedStateReader = (internal, read, initialValue) => {
|
|
368
|
+
const slotSignal = (0, alien_signals.signal)(initialValue);
|
|
369
|
+
const slotVersionSignal = (0, alien_signals.signal)(0);
|
|
370
|
+
let slotVersion = 0;
|
|
371
|
+
(internal.signalSlots ??= /* @__PURE__ */ new Set()).add({ refresh: () => {
|
|
372
|
+
const nextValue = read();
|
|
373
|
+
slotSignal(nextValue);
|
|
374
|
+
if (internal.mutableInstance && isObjectLike(nextValue)) {
|
|
375
|
+
slotVersion += 1;
|
|
376
|
+
slotVersionSignal(slotVersion);
|
|
377
|
+
}
|
|
378
|
+
} });
|
|
379
|
+
return () => {
|
|
380
|
+
const currentValue = slotSignal();
|
|
381
|
+
if (internal.mutableInstance && isObjectLike(currentValue)) slotVersionSignal();
|
|
382
|
+
return read();
|
|
383
|
+
};
|
|
384
|
+
};
|
|
385
|
+
const refreshSignalSlots = (internal) => {
|
|
386
|
+
if (!internal.signalSlots?.size) return;
|
|
387
|
+
(0, alien_signals.startBatch)();
|
|
388
|
+
try {
|
|
389
|
+
internal.signalSlots.forEach((slot) => slot.refresh());
|
|
390
|
+
} finally {
|
|
391
|
+
(0, alien_signals.endBatch)();
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
//#endregion
|
|
360
395
|
//#region packages/core/src/sharedState.ts
|
|
361
|
-
const
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
|
|
396
|
+
const formatPath = (path) => path.length ? path.map((key) => String(key)).join(".") : "<root>";
|
|
397
|
+
const unsupported = (label, path) => {
|
|
398
|
+
throw new TypeError(`${label} is not supported in shared store mode because transport synchronization uses JSON. Found unsupported value at ${formatPath(path)}.`);
|
|
399
|
+
};
|
|
400
|
+
const getDescriptors = (value, path) => {
|
|
401
|
+
try {
|
|
402
|
+
return Object.getOwnPropertyDescriptors(value);
|
|
403
|
+
} catch {
|
|
404
|
+
return unsupported("Uninspectable state", path);
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
const getPrototype = (value, path) => {
|
|
408
|
+
try {
|
|
409
|
+
return Object.getPrototypeOf(value);
|
|
410
|
+
} catch {
|
|
411
|
+
return unsupported("Uninspectable state prototype", path);
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
const assertNoInheritedToJson = (prototype, path) => {
|
|
415
|
+
let current = prototype;
|
|
416
|
+
while (current) {
|
|
417
|
+
let descriptor;
|
|
418
|
+
try {
|
|
419
|
+
descriptor = Object.getOwnPropertyDescriptor(current, "toJSON");
|
|
420
|
+
} catch {
|
|
421
|
+
unsupported("Uninspectable inherited toJSON state", path);
|
|
422
|
+
}
|
|
423
|
+
if (descriptor) {
|
|
424
|
+
if (!Object.prototype.hasOwnProperty.call(descriptor, "value") || typeof descriptor.value === "function") unsupported("Inherited toJSON state", path);
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
current = getPrototype(current, path);
|
|
428
|
+
}
|
|
365
429
|
};
|
|
366
|
-
const
|
|
367
|
-
if (key === "") return false;
|
|
430
|
+
const isArrayIndex = (key, length) => {
|
|
368
431
|
const index = Number(key);
|
|
369
|
-
return Number.
|
|
370
|
-
};
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
if (
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
432
|
+
return key !== "" && Number.isSafeInteger(index) && index >= 0 && index < length && String(index) === key;
|
|
433
|
+
};
|
|
434
|
+
const pushDataProperty = (work, descriptor, key, path, actionRoot = false) => {
|
|
435
|
+
const nextPath = [...path, key];
|
|
436
|
+
if (!descriptor) return unsupported("Sparse array state", nextPath);
|
|
437
|
+
if (!descriptor.enumerable) return unsupported("Non-enumerable data state", nextPath);
|
|
438
|
+
if (!Object.prototype.hasOwnProperty.call(descriptor, "value")) return unsupported("Accessor-backed state", nextPath);
|
|
439
|
+
work.push({
|
|
440
|
+
actionRoot,
|
|
441
|
+
path: nextPath,
|
|
442
|
+
value: descriptor.value
|
|
443
|
+
});
|
|
444
|
+
};
|
|
445
|
+
const assertSharedJsonWork = (work, isSliceStore = false) => {
|
|
446
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
447
|
+
while (work.length) {
|
|
448
|
+
const { actionRoot = false, path, value } = work.pop();
|
|
449
|
+
if (value === null) continue;
|
|
450
|
+
switch (typeof value) {
|
|
451
|
+
case "string":
|
|
452
|
+
case "boolean": continue;
|
|
453
|
+
case "number":
|
|
454
|
+
if (!Number.isFinite(value)) unsupported("NaN or infinite number state", path);
|
|
455
|
+
if (Object.is(value, -0)) unsupported("Negative zero state", path);
|
|
456
|
+
continue;
|
|
457
|
+
case "bigint": unsupported("BigInt-valued state", path);
|
|
458
|
+
case "undefined": unsupported("Undefined-valued state", path);
|
|
459
|
+
case "function": unsupported("Function-valued state", path);
|
|
460
|
+
case "symbol": throw new TypeError(`Symbol-valued state is not supported in shared store mode because transport synchronization uses JSON. Found symbol value at ${formatPath(path)}.`);
|
|
461
|
+
default: break;
|
|
462
|
+
}
|
|
463
|
+
const object = value;
|
|
464
|
+
if (seen.has(object)) unsupported("Repeated state reference", path);
|
|
465
|
+
seen.add(object);
|
|
466
|
+
const descriptors = getDescriptors(object, path);
|
|
467
|
+
if (Array.isArray(object)) {
|
|
468
|
+
const prototype = getPrototype(object, path);
|
|
469
|
+
if (prototype !== Array.prototype) unsupported("Non-plain array state", path);
|
|
470
|
+
assertNoInheritedToJson(prototype, path);
|
|
471
|
+
const length = descriptors.length?.value;
|
|
472
|
+
if (!Number.isSafeInteger(length) || length < 0) unsupported("Invalid array state", path);
|
|
473
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
474
|
+
if (key === "length") continue;
|
|
475
|
+
if (typeof key === "symbol") throw new TypeError(`Symbol-keyed state is not supported in shared store mode because transport synchronization uses JSON and string action paths. Found symbol key at ${formatPath([...path, key])}.`);
|
|
476
|
+
if (!isArrayIndex(key, length)) unsupported("Non-index array property state", [...path, key]);
|
|
477
|
+
}
|
|
478
|
+
for (let index = 0; index < length; index += 1) pushDataProperty(work, descriptors[index], index, path);
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
const prototype = getPrototype(object, path);
|
|
482
|
+
if (prototype !== Object.prototype && prototype !== null) unsupported("Non-plain object state", path);
|
|
483
|
+
assertNoInheritedToJson(prototype, path);
|
|
484
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
485
|
+
if (typeof key === "symbol") throw new TypeError(`Symbol-keyed state is not supported in shared store mode because transport synchronization uses JSON and string action paths. Found symbol key at ${formatPath([...path, key])}.`);
|
|
486
|
+
if (isUnsafeKey(key)) unsupported("Unsafe-keyed state", [...path, key]);
|
|
487
|
+
const descriptor = descriptors[key];
|
|
488
|
+
if (actionRoot && descriptor) {
|
|
489
|
+
const isDataProperty = Object.prototype.hasOwnProperty.call(descriptor, "value");
|
|
490
|
+
if (isDataProperty && typeof descriptor.value === "function") continue;
|
|
491
|
+
if (actionRoot === "initial" && (!isDataProperty || descriptor.value instanceof Computed)) continue;
|
|
492
|
+
}
|
|
493
|
+
pushDataProperty(work, descriptor, key, path, isSliceStore && path.length === 0 ? "initial" : false);
|
|
386
494
|
}
|
|
387
495
|
}
|
|
388
496
|
};
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
497
|
+
const assertSharedJsonValue = (root) => {
|
|
498
|
+
assertSharedJsonWork([{
|
|
499
|
+
path: [],
|
|
500
|
+
value: root
|
|
501
|
+
}]);
|
|
502
|
+
};
|
|
503
|
+
const validateSharedInitialState = (root, isSliceStore = false) => {
|
|
504
|
+
assertSharedJsonWork([{
|
|
505
|
+
actionRoot: isSliceStore ? false : "initial",
|
|
506
|
+
path: [],
|
|
507
|
+
value: root
|
|
508
|
+
}], isSliceStore);
|
|
509
|
+
};
|
|
510
|
+
const validateSharedReplacementSource = (root) => {
|
|
511
|
+
if (typeof root !== "object" || root === null || Array.isArray(root)) unsupported("Non-record replacement state", []);
|
|
512
|
+
assertSharedJsonWork([{
|
|
513
|
+
actionRoot: "replacement",
|
|
514
|
+
path: [],
|
|
515
|
+
value: root
|
|
516
|
+
}]);
|
|
517
|
+
};
|
|
518
|
+
const encodeSharedJson = (value) => {
|
|
519
|
+
assertSharedJsonValue(value);
|
|
520
|
+
const encoded = JSON.stringify(value);
|
|
521
|
+
if (typeof encoded !== "string") throw new TypeError("Shared transport value could not be encoded as JSON.");
|
|
522
|
+
return encoded;
|
|
523
|
+
};
|
|
524
|
+
const decodeSharedJson = (encoded) => {
|
|
525
|
+
if (typeof encoded !== "string") throw new TypeError("Shared transport payload must be a JSON string.");
|
|
526
|
+
let value;
|
|
527
|
+
try {
|
|
528
|
+
value = JSON.parse(encoded);
|
|
529
|
+
} catch {
|
|
530
|
+
throw new TypeError("Shared transport payload is not valid JSON.");
|
|
412
531
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
if (
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
532
|
+
assertSharedJsonValue(value);
|
|
533
|
+
return value;
|
|
534
|
+
};
|
|
535
|
+
const validateSharedActionPaths = (state, isSliceStore = false) => {
|
|
536
|
+
const actions = /* @__PURE__ */ new Set();
|
|
537
|
+
const work = [{
|
|
538
|
+
actionRoot: !isSliceStore,
|
|
539
|
+
path: [],
|
|
540
|
+
value: state
|
|
541
|
+
}];
|
|
542
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
543
|
+
while (work.length) {
|
|
544
|
+
const { actionRoot, path, value } = work.pop();
|
|
545
|
+
if (typeof value !== "object" || value === null || seen.has(value)) continue;
|
|
546
|
+
seen.add(value);
|
|
547
|
+
const descriptors = getDescriptors(value, path);
|
|
548
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
549
|
+
if (typeof key === "symbol") throw new TypeError(`Symbol-keyed state is not supported in shared store mode because transport synchronization uses JSON and string action paths. Found symbol key at ${formatPath([...path, key])}.`);
|
|
550
|
+
const descriptor = descriptors[key];
|
|
551
|
+
if (descriptor && Object.prototype.hasOwnProperty.call(descriptor, "value")) {
|
|
552
|
+
const nextPath = [...path, key];
|
|
553
|
+
if (actionRoot && typeof descriptor.value === "function") {
|
|
554
|
+
actions.add(JSON.stringify(nextPath));
|
|
555
|
+
continue;
|
|
556
|
+
}
|
|
557
|
+
work.push({
|
|
558
|
+
actionRoot: isSliceStore && path.length === 0,
|
|
559
|
+
path: nextPath,
|
|
560
|
+
value: descriptor.value
|
|
561
|
+
});
|
|
562
|
+
}
|
|
436
563
|
}
|
|
437
|
-
ancestors.delete(value);
|
|
438
|
-
return;
|
|
439
564
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
565
|
+
return actions;
|
|
566
|
+
};
|
|
567
|
+
const validateSharedStateSerializable = assertSharedJsonValue;
|
|
568
|
+
const hasOwn = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
569
|
+
const asRecord = (value, message) => {
|
|
570
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError(message);
|
|
571
|
+
return value;
|
|
572
|
+
};
|
|
573
|
+
const decodeMessage = (encoded, type) => {
|
|
574
|
+
const message = asRecord(decodeSharedJson(encoded), "Invalid transport message");
|
|
575
|
+
if (message.v !== 1 || message.type !== type) throw new TypeError("Invalid transport message");
|
|
576
|
+
return message;
|
|
577
|
+
};
|
|
578
|
+
const readEpoch = (message) => {
|
|
579
|
+
if (typeof message.epoch !== "string" || message.epoch.length === 0) throw new TypeError("Invalid transport epoch");
|
|
580
|
+
return message.epoch;
|
|
581
|
+
};
|
|
582
|
+
const readSequence = (message) => {
|
|
583
|
+
if (typeof message.sequence !== "number" || !Number.isSafeInteger(message.sequence) || message.sequence < 0) throw new TypeError("Invalid transport sequence");
|
|
584
|
+
return message.sequence;
|
|
585
|
+
};
|
|
586
|
+
const readAction = (value) => {
|
|
587
|
+
if (!Array.isArray(value) || value.length === 0 || value.some((key) => typeof key !== "string" || isUnsafePathSegment(key))) throw new TypeError("Invalid transport action");
|
|
588
|
+
return [...value];
|
|
589
|
+
};
|
|
590
|
+
const readPath = (value, { allowUnsafe = false } = {}) => {
|
|
591
|
+
if (!Array.isArray(value) || value.length === 0) throw new TypeError("Invalid transport patch path");
|
|
592
|
+
const path = [];
|
|
593
|
+
for (const segment of value) {
|
|
594
|
+
if (typeof segment !== "string" && (typeof segment !== "number" || !Number.isSafeInteger(segment) || segment < 0) || !allowUnsafe && isUnsafePathSegment(segment)) throw new TypeError("Invalid transport patch path");
|
|
595
|
+
path.push(segment);
|
|
596
|
+
}
|
|
597
|
+
return path;
|
|
598
|
+
};
|
|
599
|
+
const readPatches = (value, options = {}) => {
|
|
600
|
+
if (!Array.isArray(value)) throw new TypeError("Invalid transport patches");
|
|
601
|
+
return value.map((candidate) => {
|
|
602
|
+
const patch = asRecord(candidate, "Invalid transport patch");
|
|
603
|
+
const path = readPath(patch.path, { allowUnsafe: options.allowUnsafePaths });
|
|
604
|
+
if (patch.op === "remove") {
|
|
605
|
+
if (hasOwn(patch, "value")) throw new TypeError("Invalid remove patch");
|
|
606
|
+
return {
|
|
607
|
+
op: "remove",
|
|
608
|
+
path
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
if (patch.op !== "add" && patch.op !== "replace" || !hasOwn(patch, "value")) throw new TypeError("Invalid transport patch");
|
|
612
|
+
return {
|
|
613
|
+
op: patch.op,
|
|
614
|
+
path,
|
|
615
|
+
value: patch.value
|
|
616
|
+
};
|
|
617
|
+
});
|
|
618
|
+
};
|
|
619
|
+
const validateUpdatePatches = (patches) => {
|
|
620
|
+
assertSharedJsonValue(patches);
|
|
621
|
+
readPatches(patches, { allowUnsafePaths: true });
|
|
622
|
+
};
|
|
623
|
+
const encodeExecuteRequest = (action, args) => encodeSharedJson({
|
|
624
|
+
action: readAction([...action]),
|
|
625
|
+
args,
|
|
626
|
+
type: "execute",
|
|
627
|
+
v: 1
|
|
628
|
+
});
|
|
629
|
+
const decodeExecuteRequest = (encoded) => {
|
|
630
|
+
const message = decodeMessage(encoded, "execute");
|
|
631
|
+
if (!Array.isArray(message.args)) throw new TypeError("Invalid transport arguments");
|
|
632
|
+
return {
|
|
633
|
+
action: readAction(message.action),
|
|
634
|
+
args: [...message.args]
|
|
443
635
|
};
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
636
|
+
};
|
|
637
|
+
const encodeExecuteResponse = (response) => encodeSharedJson({
|
|
638
|
+
...response,
|
|
639
|
+
type: "execute-result",
|
|
640
|
+
v: 1
|
|
641
|
+
});
|
|
642
|
+
const decodeExecuteResponse = (encoded) => {
|
|
643
|
+
const message = decodeMessage(encoded, "execute-result");
|
|
644
|
+
const base = {
|
|
645
|
+
epoch: readEpoch(message),
|
|
646
|
+
sequence: readSequence(message)
|
|
447
647
|
};
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
648
|
+
if (message.ok === true) return hasOwn(message, "value") ? {
|
|
649
|
+
...base,
|
|
650
|
+
ok: true,
|
|
651
|
+
value: message.value
|
|
652
|
+
} : {
|
|
653
|
+
...base,
|
|
654
|
+
ok: true
|
|
655
|
+
};
|
|
656
|
+
if (message.ok !== false || typeof message.error !== "string" || message.error.length === 0) throw new TypeError("Invalid execute response");
|
|
657
|
+
return {
|
|
658
|
+
...base,
|
|
659
|
+
error: message.error,
|
|
660
|
+
ok: false
|
|
661
|
+
};
|
|
662
|
+
};
|
|
663
|
+
const encodeFullSyncRequest = () => encodeSharedJson({
|
|
664
|
+
type: "full-sync",
|
|
665
|
+
v: 1
|
|
666
|
+
});
|
|
667
|
+
const decodeFullSyncRequest = (encoded) => {
|
|
668
|
+
decodeMessage(encoded, "full-sync");
|
|
669
|
+
};
|
|
670
|
+
const encodeFullSyncResponse = (response) => encodeSharedJson({
|
|
671
|
+
...response,
|
|
672
|
+
type: "full-sync-result",
|
|
673
|
+
v: 1
|
|
674
|
+
});
|
|
675
|
+
const decodeFullSyncResponse = (encoded) => {
|
|
676
|
+
const message = decodeMessage(encoded, "full-sync-result");
|
|
677
|
+
return {
|
|
678
|
+
epoch: readEpoch(message),
|
|
679
|
+
sequence: readSequence(message),
|
|
680
|
+
state: asRecord(message.state, "Invalid fullSync state")
|
|
681
|
+
};
|
|
682
|
+
};
|
|
683
|
+
const encodeUpdateMessage = (epoch, sequence, patches) => {
|
|
684
|
+
return encodeSharedJson({
|
|
685
|
+
epoch,
|
|
686
|
+
patches: readPatches(patches.map((patch) => patch.op === "remove" ? {
|
|
687
|
+
op: patch.op,
|
|
688
|
+
path: patch.path
|
|
689
|
+
} : {
|
|
690
|
+
op: patch.op,
|
|
691
|
+
path: patch.path,
|
|
692
|
+
value: patch.value
|
|
693
|
+
})),
|
|
694
|
+
sequence,
|
|
695
|
+
type: "update",
|
|
696
|
+
v: 1
|
|
697
|
+
});
|
|
474
698
|
};
|
|
475
|
-
const
|
|
476
|
-
const
|
|
477
|
-
|
|
478
|
-
|
|
699
|
+
const decodeUpdateMessage = (encoded) => {
|
|
700
|
+
const message = decodeMessage(encoded, "update");
|
|
701
|
+
return {
|
|
702
|
+
epoch: readEpoch(message),
|
|
703
|
+
patches: readPatches(message.patches),
|
|
704
|
+
sequence: readSequence(message)
|
|
705
|
+
};
|
|
479
706
|
};
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
707
|
+
//#endregion
|
|
708
|
+
//#region packages/core/src/wrapStore.ts
|
|
709
|
+
/**
|
|
710
|
+
* Convert a store object into Coaction's callable store shape.
|
|
711
|
+
*
|
|
712
|
+
* @remarks
|
|
713
|
+
* Framework bindings use this to attach selector-aware readers while
|
|
714
|
+
* preserving the underlying store API on the returned function object. Most
|
|
715
|
+
* applications should use a public `create` entry instead of calling
|
|
716
|
+
* `wrapStore()` directly. Framework authors import this helper from
|
|
717
|
+
* `coaction/local` or `coaction/adapter`.
|
|
718
|
+
*/
|
|
719
|
+
const wrapStore = (store, getState = () => store.getState()) => {
|
|
720
|
+
const { name, ..._store } = store;
|
|
721
|
+
return Object.assign({ [name]: (...args) => getState(...args) }[name], _store);
|
|
486
722
|
};
|
|
487
723
|
//#endregion
|
|
488
724
|
//#region packages/core/src/asyncClientStore.ts
|
|
489
|
-
const parseFullSyncState$1 = (state) => {
|
|
490
|
-
const parsed = JSON.parse(state);
|
|
491
|
-
if (typeof parsed !== "object" || parsed === null) throw new Error("Invalid fullSync payload");
|
|
492
|
-
return sanitizeReplacementState(parsed);
|
|
493
|
-
};
|
|
494
725
|
const clientApplyErrorMessage = "apply() cannot be called in the client store. Client stores are mirrors; use a store method to update the main store instead.";
|
|
495
|
-
const createAsyncClientStore = (createStore,
|
|
496
|
-
|
|
497
|
-
|
|
726
|
+
const createAsyncClientStore = (createStore, options) => {
|
|
727
|
+
let createdStore;
|
|
728
|
+
try {
|
|
729
|
+
createdStore = createStore({ share: "client" });
|
|
730
|
+
} catch (error) {
|
|
731
|
+
return failTransportInitialization(options.clientTransport, error);
|
|
732
|
+
}
|
|
733
|
+
const { store, internal } = createdStore;
|
|
734
|
+
let canApplyClientState = false;
|
|
498
735
|
const previousAssertMutationAllowed = internal.assertMutationAllowed;
|
|
499
736
|
internal.assertMutationAllowed = (operation) => {
|
|
500
|
-
if (operation === "apply"
|
|
737
|
+
if (operation === "apply") {
|
|
738
|
+
if (!canApplyClientState) throw new Error(clientApplyErrorMessage);
|
|
739
|
+
canApplyClientState = false;
|
|
740
|
+
}
|
|
501
741
|
previousAssertMutationAllowed?.(operation);
|
|
502
742
|
};
|
|
503
|
-
const baseApply =
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
return baseApply(state, patches);
|
|
743
|
+
const baseApply = store.apply.bind(store);
|
|
744
|
+
store.apply = () => {
|
|
745
|
+
throw new Error(clientApplyErrorMessage);
|
|
507
746
|
};
|
|
508
747
|
internal.applyClientState = (...args) => {
|
|
509
|
-
|
|
748
|
+
canApplyClientState = true;
|
|
510
749
|
try {
|
|
511
750
|
baseApply(...args);
|
|
512
751
|
} finally {
|
|
513
|
-
|
|
752
|
+
canApplyClientState = false;
|
|
514
753
|
}
|
|
515
754
|
};
|
|
516
|
-
const isSharedWorker = typeof SharedWorker !== "undefined" &&
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
syncingPromise = null;
|
|
538
|
-
});
|
|
539
|
-
return syncingPromise;
|
|
540
|
-
};
|
|
541
|
-
if (typeof transport.onConnect !== "function") throw new Error("transport.onConnect is required");
|
|
542
|
-
transport.onConnect?.(() => {
|
|
543
|
-
awaitingReconnectSync = true;
|
|
544
|
-
reconnectSequenceBaseline = internal.sequence;
|
|
545
|
-
fullSync(true).catch((error) => {
|
|
546
|
-
if (process.env.NODE_ENV === "development") console.error(error);
|
|
547
|
-
});
|
|
755
|
+
const isSharedWorker = typeof SharedWorker !== "undefined" && options.worker instanceof SharedWorker;
|
|
756
|
+
let transport;
|
|
757
|
+
try {
|
|
758
|
+
transport = options.worker ? (0, data_transport.createTransport)(isSharedWorker ? "SharedWorkerClient" : "WebWorkerClient", {
|
|
759
|
+
worker: options.worker,
|
|
760
|
+
prefix: store.name
|
|
761
|
+
}) : options.clientTransport;
|
|
762
|
+
} catch (error) {
|
|
763
|
+
return failStoreSetup(store, error);
|
|
764
|
+
}
|
|
765
|
+
if (!transport) return failStoreSetup(store, /* @__PURE__ */ new Error("transport is required"));
|
|
766
|
+
try {
|
|
767
|
+
store.transport = transport;
|
|
768
|
+
if (typeof transport.onConnect !== "function") throw new Error("transport.onConnect is required");
|
|
769
|
+
} catch (error) {
|
|
770
|
+
return failStoreSetup(store, error);
|
|
771
|
+
}
|
|
772
|
+
const destroyedMarker = Symbol("destroyed client transport");
|
|
773
|
+
let resolveDestroyed;
|
|
774
|
+
const destroyedSignal = new Promise((resolve) => {
|
|
775
|
+
resolveDestroyed = () => resolve(destroyedMarker);
|
|
548
776
|
});
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
internal.sequence = options.sequence;
|
|
567
|
-
awaitingReconnectSync = false;
|
|
568
|
-
reconnectSequenceBaseline = null;
|
|
569
|
-
return;
|
|
570
|
-
} else {
|
|
571
|
-
shouldFullSync = true;
|
|
572
|
-
allowLowerSequence = awaitingReconnectSync;
|
|
573
|
-
}
|
|
574
|
-
if (shouldFullSync) await fullSync(allowLowerSequence);
|
|
777
|
+
const disposers = /* @__PURE__ */ new Set();
|
|
778
|
+
let destroyed = false;
|
|
779
|
+
let connectGeneration = 0;
|
|
780
|
+
let connectSync = null;
|
|
781
|
+
let syncTail = Promise.resolve();
|
|
782
|
+
const registerDisposer = (value) => {
|
|
783
|
+
if (typeof value === "function") disposers.add(value);
|
|
784
|
+
};
|
|
785
|
+
const cleanup = () => {
|
|
786
|
+
if (destroyed) return;
|
|
787
|
+
destroyed = true;
|
|
788
|
+
connectGeneration += 1;
|
|
789
|
+
resolveDestroyed();
|
|
790
|
+
const callbacks = [...disposers];
|
|
791
|
+
disposers.clear();
|
|
792
|
+
for (const dispose of callbacks) try {
|
|
793
|
+
dispose();
|
|
575
794
|
} catch (error) {
|
|
576
|
-
|
|
577
|
-
await fullSync(awaitingReconnectSync);
|
|
578
|
-
} catch (syncError) {
|
|
579
|
-
if (process.env.NODE_ENV === "development") console.error(syncError);
|
|
580
|
-
}
|
|
581
|
-
if (process.env.NODE_ENV === "development") console.error(error);
|
|
795
|
+
reportLifecycleError(error);
|
|
582
796
|
}
|
|
583
|
-
}
|
|
584
|
-
|
|
797
|
+
};
|
|
798
|
+
const awaitActive = async (value) => {
|
|
799
|
+
const result = await Promise.race([Promise.resolve(value), destroyedSignal]);
|
|
800
|
+
if (result === destroyedMarker) throw new Error("Client transport was destroyed");
|
|
801
|
+
return result;
|
|
802
|
+
};
|
|
803
|
+
internal.awaitClientTransport = awaitActive;
|
|
804
|
+
const applyFullSync = (state, epoch, sequence) => {
|
|
805
|
+
const previousEpoch = internal.transportEpoch;
|
|
806
|
+
const previousSequence = internal.sequence;
|
|
807
|
+
internal.transportEpoch = epoch;
|
|
808
|
+
internal.sequence = sequence;
|
|
809
|
+
try {
|
|
810
|
+
internal.applyClientState(state);
|
|
811
|
+
} catch (error) {
|
|
812
|
+
internal.transportEpoch = previousEpoch;
|
|
813
|
+
internal.sequence = previousSequence;
|
|
814
|
+
throw error;
|
|
815
|
+
}
|
|
816
|
+
};
|
|
817
|
+
const fullSync = (expectedEpoch, minimumSequence = 0, generation = connectGeneration) => {
|
|
818
|
+
const execute = async () => {
|
|
819
|
+
if (destroyed || generation !== connectGeneration) return;
|
|
820
|
+
const encoded = await awaitActive(transport.emit("fullSync", encodeFullSyncRequest()));
|
|
821
|
+
if (destroyed || generation !== connectGeneration) return;
|
|
822
|
+
const snapshot = decodeFullSyncResponse(encoded);
|
|
823
|
+
if (expectedEpoch && snapshot.epoch !== expectedEpoch) throw new Error("Mismatched fullSync epoch");
|
|
824
|
+
if (snapshot.sequence < minimumSequence) throw new Error("Stale fullSync sequence");
|
|
825
|
+
if (snapshot.epoch === internal.transportEpoch && snapshot.sequence < internal.sequence) return;
|
|
826
|
+
applyFullSync(snapshot.state, snapshot.epoch, snapshot.sequence);
|
|
827
|
+
};
|
|
828
|
+
const run = syncTail.then(execute, execute);
|
|
829
|
+
syncTail = run.then(() => void 0, () => void 0);
|
|
830
|
+
return run;
|
|
831
|
+
};
|
|
832
|
+
internal.syncClientState = (expectedEpoch, minimumSequence) => fullSync(expectedEpoch, minimumSequence);
|
|
833
|
+
const applyUpdate = (update) => {
|
|
834
|
+
const previousEpoch = internal.transportEpoch;
|
|
835
|
+
const previousSequence = internal.sequence;
|
|
836
|
+
internal.transportEpoch = update.epoch;
|
|
837
|
+
internal.sequence = update.sequence;
|
|
838
|
+
try {
|
|
839
|
+
internal.applyClientState(void 0, update.patches);
|
|
840
|
+
} catch (error) {
|
|
841
|
+
internal.transportEpoch = previousEpoch;
|
|
842
|
+
internal.sequence = previousSequence;
|
|
843
|
+
throw error;
|
|
844
|
+
}
|
|
845
|
+
};
|
|
846
|
+
const handleUpdate = async (encoded) => {
|
|
847
|
+
if (destroyed) return;
|
|
848
|
+
const generation = connectGeneration;
|
|
849
|
+
const update = decodeUpdateMessage(encoded);
|
|
850
|
+
if (connectSync) await connectSync;
|
|
851
|
+
if (destroyed || generation !== connectGeneration) return;
|
|
852
|
+
if (update.epoch !== internal.transportEpoch) await fullSync(update.epoch, 0, generation);
|
|
853
|
+
if (destroyed || generation !== connectGeneration) return;
|
|
854
|
+
if (update.epoch !== internal.transportEpoch) throw new Error("Mismatched update epoch");
|
|
855
|
+
if (update.sequence <= internal.sequence) return;
|
|
856
|
+
if (update.sequence === internal.sequence + 1) {
|
|
857
|
+
applyUpdate(update);
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
await fullSync(update.epoch, update.sequence, generation);
|
|
861
|
+
};
|
|
862
|
+
internal.destroyCallbacks?.add(cleanup);
|
|
863
|
+
try {
|
|
864
|
+
registerDisposer(transport.listen("update", async (encoded) => {
|
|
865
|
+
try {
|
|
866
|
+
await handleUpdate(encoded);
|
|
867
|
+
} catch (error) {
|
|
868
|
+
if (!destroyed) {
|
|
869
|
+
try {
|
|
870
|
+
await fullSync();
|
|
871
|
+
} catch (syncError) {
|
|
872
|
+
reportLifecycleError(syncError);
|
|
873
|
+
}
|
|
874
|
+
reportLifecycleError(error);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
}));
|
|
878
|
+
registerDisposer(transport.onConnect(() => {
|
|
879
|
+
const pending = fullSync(void 0, 0, ++connectGeneration).finally(() => {
|
|
880
|
+
if (connectSync === pending) connectSync = null;
|
|
881
|
+
});
|
|
882
|
+
connectSync = pending;
|
|
883
|
+
pending.catch(reportLifecycleError);
|
|
884
|
+
return pending;
|
|
885
|
+
}));
|
|
886
|
+
markStoreReady(store);
|
|
887
|
+
internal.assertAlive?.("store initialization");
|
|
888
|
+
} catch (error) {
|
|
889
|
+
return failStoreSetup(store, error);
|
|
890
|
+
}
|
|
891
|
+
return wrapStore(store, () => store.getState());
|
|
585
892
|
};
|
|
586
893
|
const emit = (store, internal, patches) => {
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
internal.sequence += 1;
|
|
594
|
-
store.transport.emit({
|
|
894
|
+
if (!store.transport || !patches?.length || !internal.transportEpoch) return;
|
|
895
|
+
const sequence = internal.sequence + 1;
|
|
896
|
+
const encoded = encodeUpdateMessage(internal.transportEpoch, sequence, patches);
|
|
897
|
+
internal.sequence = sequence;
|
|
898
|
+
try {
|
|
899
|
+
const pending = store.transport.emit({
|
|
595
900
|
name: "update",
|
|
596
901
|
respond: false
|
|
597
|
-
},
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
}
|
|
602
|
-
};
|
|
603
|
-
const handleDraft = (store, internal) => {
|
|
604
|
-
internal.rootState = internal.backupState;
|
|
605
|
-
const [nextState, patches, inversePatches] = internal.finalizeDraft();
|
|
606
|
-
if (store.share === "main") validateSharedStateSerializable(nextState);
|
|
607
|
-
const safePatches = sanitizeCheckedPatches((store.patch ? store.patch({
|
|
608
|
-
patches,
|
|
609
|
-
inversePatches
|
|
610
|
-
}) : {
|
|
611
|
-
patches,
|
|
612
|
-
inversePatches
|
|
613
|
-
}).patches, "store.patch()");
|
|
614
|
-
if (safePatches.length) {
|
|
615
|
-
store.apply(internal.rootState, safePatches);
|
|
616
|
-
emit(store, internal, safePatches);
|
|
902
|
+
}, encoded);
|
|
903
|
+
Promise.resolve(pending).catch(reportLifecycleError);
|
|
904
|
+
} catch (error) {
|
|
905
|
+
reportLifecycleError(error);
|
|
617
906
|
}
|
|
618
907
|
};
|
|
619
908
|
//#endregion
|
|
620
|
-
//#region packages/core/src/
|
|
621
|
-
const
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
let state;
|
|
629
|
-
if (isStateFactory(stateOrFn)) state = stateOrFn(store.setState, store.getState, store);
|
|
630
|
-
else if (isObject(stateOrFn)) state = stateOrFn;
|
|
631
|
-
else {
|
|
632
|
-
if (process.env.NODE_ENV !== "production") throw new Error(formatInvalidStateMessage("value", stateOrFn, key));
|
|
633
|
-
return {};
|
|
634
|
-
}
|
|
635
|
-
if (hasGetState(state)) state = state.getState();
|
|
636
|
-
else if (typeof state === "function") state = state();
|
|
637
|
-
if (hasBindState(state)) {
|
|
638
|
-
if (store.isSliceStore) throw new Error("Third-party state binding does not support Slices mode. Please inject a whole store instead.");
|
|
639
|
-
const binder = state[bindSymbol];
|
|
640
|
-
const rawState = binder.bind(state);
|
|
641
|
-
binder.handleStore(store, rawState, state, internal, key);
|
|
642
|
-
delete state[bindSymbol];
|
|
643
|
-
return rawState;
|
|
644
|
-
}
|
|
645
|
-
if (!isObject(state)) {
|
|
646
|
-
if (process.env.NODE_ENV !== "production") throw new Error(formatInvalidStateMessage("result", state, key));
|
|
647
|
-
return {};
|
|
648
|
-
}
|
|
649
|
-
return state;
|
|
650
|
-
};
|
|
651
|
-
if (!store.isSliceStore) return makeState(createState);
|
|
652
|
-
return getOwnEnumerableKeys(createState).reduce((stateTree, key) => {
|
|
653
|
-
if (typeof key === "string" && isUnsafeKey(key)) return stateTree;
|
|
654
|
-
setOwnEnumerable(stateTree, key, makeState(createState[key], key));
|
|
655
|
-
return stateTree;
|
|
656
|
-
}, {});
|
|
909
|
+
//#region packages/core/src/global.ts
|
|
910
|
+
const getGlobal = () => {
|
|
911
|
+
let _global;
|
|
912
|
+
if (typeof window !== "undefined") _global = window;
|
|
913
|
+
else if (typeof global !== "undefined") _global = global;
|
|
914
|
+
else if (typeof self !== "undefined") _global = self;
|
|
915
|
+
else _global = {};
|
|
916
|
+
return _global;
|
|
657
917
|
};
|
|
658
918
|
//#endregion
|
|
919
|
+
//#region packages/core/src/constant.ts
|
|
920
|
+
const WorkerType = getGlobal().SharedWorkerGlobalScope ? "SharedWorkerInternal" : globalThis.WorkerGlobalScope ? "WebWorkerInternal" : null;
|
|
921
|
+
const bindSymbol = Symbol("bind");
|
|
922
|
+
//#endregion
|
|
659
923
|
//#region packages/core/src/getRawStateClientAction.ts
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
if (typeof value !== "object" || value === null) return false;
|
|
672
|
-
const candidate = value;
|
|
673
|
-
return typeof candidate.$$Error === "string" && candidate.$$Error.length > 0 && Object.keys(candidate).length === 1;
|
|
924
|
+
/**
|
|
925
|
+
* The authority changed while a remote action was in flight, so its side-effect
|
|
926
|
+
* outcome cannot be determined safely from the current client mirror.
|
|
927
|
+
*/
|
|
928
|
+
var ActionAuthorityChangedError = class extends Error {
|
|
929
|
+
code = "COACTION_ACTION_AUTHORITY_CHANGED";
|
|
930
|
+
outcome = "unknown";
|
|
931
|
+
constructor(action) {
|
|
932
|
+
super(`The authority changed while action '${action}' was in flight. The action may have completed on the previous authority; retry only if it is idempotent.`);
|
|
933
|
+
this.name = "ActionAuthorityChangedError";
|
|
934
|
+
}
|
|
674
935
|
};
|
|
675
936
|
const createClientAction = ({ clientExecuteSyncTimeoutMs, internal, key, store, sliceKey }) => {
|
|
676
937
|
return (...args) => {
|
|
@@ -712,58 +973,309 @@ const createClientAction = ({ clientExecuteSyncTimeoutMs, internal, key, store,
|
|
|
712
973
|
}
|
|
713
974
|
};
|
|
714
975
|
if (typeof sliceKey === "symbol") throw new Error("Symbol-keyed slice actions are not supported in client store mode.");
|
|
715
|
-
const
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
const
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
store.transport.emit("fullSync").then((latest) => {
|
|
746
|
-
if (typeof latest !== "object" || latest === null) throw new Error("Invalid fullSync payload");
|
|
747
|
-
const next = latest;
|
|
748
|
-
if (typeof next.state !== "string" || typeof next.sequence !== "number") throw new Error("Invalid fullSync payload");
|
|
749
|
-
if (next.sequence >= sequence) {
|
|
750
|
-
(internal.applyClientState ?? store.apply.bind(store))(parseFullSyncState(next.state));
|
|
751
|
-
internal.sequence = next.sequence;
|
|
752
|
-
finishResolve();
|
|
753
|
-
return;
|
|
754
|
-
}
|
|
755
|
-
finishReject(/* @__PURE__ */ new Error(`Stale fullSync sequence: expected >= ${sequence}, got ${next.sequence}`));
|
|
756
|
-
}).catch((error) => {
|
|
757
|
-
finishReject(error);
|
|
976
|
+
const encoded = encodeExecuteRequest(typeof sliceKey === "undefined" ? [key] : [String(sliceKey), key], args);
|
|
977
|
+
const requestEpoch = internal.transportEpoch;
|
|
978
|
+
return traceAction(() => {
|
|
979
|
+
const emitted = store.transport.emit("execute", encoded);
|
|
980
|
+
return (internal.awaitClientTransport ? internal.awaitClientTransport(emitted) : emitted).then(async (payload) => {
|
|
981
|
+
const response = decodeExecuteResponse(payload);
|
|
982
|
+
internal.assertAlive?.(`action ${key}`);
|
|
983
|
+
const syncClientState = internal.syncClientState;
|
|
984
|
+
if (!syncClientState) throw new Error("Client fullSync is not available");
|
|
985
|
+
if (internal.transportEpoch !== requestEpoch && response.epoch !== internal.transportEpoch) throw new ActionAuthorityChangedError(key);
|
|
986
|
+
if (response.epoch !== internal.transportEpoch) {
|
|
987
|
+
await syncClientState(response.epoch, response.sequence);
|
|
988
|
+
internal.assertAlive?.(`action ${key}`);
|
|
989
|
+
} else if (response.sequence > internal.sequence) {
|
|
990
|
+
await new Promise((resolve, reject) => {
|
|
991
|
+
let settled = false;
|
|
992
|
+
let unsubscribe = () => {};
|
|
993
|
+
let timeout;
|
|
994
|
+
const cancel = () => finish(/* @__PURE__ */ new Error("Client transport was destroyed"));
|
|
995
|
+
const finish = (error) => {
|
|
996
|
+
if (settled) return;
|
|
997
|
+
settled = true;
|
|
998
|
+
unsubscribe();
|
|
999
|
+
internal.destroyCallbacks?.delete(cancel);
|
|
1000
|
+
if (timeout) clearTimeout(timeout);
|
|
1001
|
+
if (typeof error === "undefined") resolve();
|
|
1002
|
+
else reject(error);
|
|
1003
|
+
};
|
|
1004
|
+
unsubscribe = store.subscribe(() => {
|
|
1005
|
+
if (internal.transportEpoch === response.epoch && internal.sequence >= response.sequence) finish();
|
|
758
1006
|
});
|
|
759
|
-
|
|
1007
|
+
internal.destroyCallbacks?.add(cancel);
|
|
1008
|
+
timeout = setTimeout(() => {
|
|
1009
|
+
syncClientState(response.epoch, response.sequence).then(() => finish(), (error) => finish(error));
|
|
1010
|
+
}, clientExecuteSyncTimeoutMs);
|
|
1011
|
+
if (internal.transportEpoch === response.epoch && internal.sequence >= response.sequence) finish();
|
|
1012
|
+
});
|
|
1013
|
+
internal.assertAlive?.(`action ${key}`);
|
|
1014
|
+
}
|
|
1015
|
+
if (!response.ok) throw new Error(response.error);
|
|
1016
|
+
return response.value;
|
|
1017
|
+
});
|
|
1018
|
+
});
|
|
1019
|
+
};
|
|
1020
|
+
};
|
|
1021
|
+
//#endregion
|
|
1022
|
+
//#region packages/core/src/handleMainTransport.ts
|
|
1023
|
+
const publicErrorMessages = /* @__PURE__ */ new Set([
|
|
1024
|
+
"Remote action is not allowed",
|
|
1025
|
+
"The function is not found",
|
|
1026
|
+
"Transport request is not authorized",
|
|
1027
|
+
"Transport request was cancelled after store destroy"
|
|
1028
|
+
]);
|
|
1029
|
+
const getErrorMessage = async (error, request, policy) => {
|
|
1030
|
+
if (error instanceof Error && publicErrorMessages.has(error.message)) return error.message;
|
|
1031
|
+
if (request && policy?.mapError) try {
|
|
1032
|
+
const message = await policy.mapError(error, request);
|
|
1033
|
+
if (typeof message === "string" && message) return message;
|
|
1034
|
+
} catch (mapError) {
|
|
1035
|
+
if (process.env.NODE_ENV === "development") console.error(mapError);
|
|
1036
|
+
}
|
|
1037
|
+
return "Remote action failed";
|
|
1038
|
+
};
|
|
1039
|
+
const handleMainTransport = (store, internal, storeTransport, workerType, checkEnablePatches, policy) => {
|
|
1040
|
+
const transport = storeTransport ?? (workerType === "SharedWorkerInternal" || workerType === "WebWorkerInternal" ? (0, data_transport.createTransport)(workerType, { prefix: store.name }) : void 0);
|
|
1041
|
+
if (!transport) return;
|
|
1042
|
+
if (checkEnablePatches) throw new Error("enablePatches: true is required for the transport");
|
|
1043
|
+
const epoch = uuid();
|
|
1044
|
+
internal.transportEpoch = epoch;
|
|
1045
|
+
let destroyed = false;
|
|
1046
|
+
const disposers = /* @__PURE__ */ new Set();
|
|
1047
|
+
const registerDisposer = (value) => {
|
|
1048
|
+
if (typeof value === "function") disposers.add(value);
|
|
1049
|
+
};
|
|
1050
|
+
const cleanup = () => {
|
|
1051
|
+
if (destroyed) return;
|
|
1052
|
+
destroyed = true;
|
|
1053
|
+
const callbacks = [...disposers];
|
|
1054
|
+
disposers.clear();
|
|
1055
|
+
for (const dispose of callbacks) try {
|
|
1056
|
+
dispose();
|
|
1057
|
+
} catch (error) {
|
|
1058
|
+
if (process.env.NODE_ENV === "development") console.error(error);
|
|
1059
|
+
}
|
|
1060
|
+
};
|
|
1061
|
+
const assertActive = () => {
|
|
1062
|
+
if (destroyed) throw new Error("Transport request was cancelled after store destroy");
|
|
1063
|
+
};
|
|
1064
|
+
store.transport = transport;
|
|
1065
|
+
internal.emitPatches = (patches) => emit(store, internal, patches);
|
|
1066
|
+
internal.destroyCallbacks?.add(cleanup);
|
|
1067
|
+
try {
|
|
1068
|
+
registerDisposer(transport.listen("execute", async (encoded) => {
|
|
1069
|
+
let policyRequest;
|
|
1070
|
+
try {
|
|
1071
|
+
assertActive();
|
|
1072
|
+
const request = decodeExecuteRequest(encoded);
|
|
1073
|
+
if (!internal.sharedActionPaths?.has(JSON.stringify(request.action))) throw new Error("Remote action is not allowed");
|
|
1074
|
+
if (policy?.allowedActions && !policy.allowedActions.some((allowed) => allowed.length === request.action.length && allowed.every((key, index) => key === request.action[index]))) throw new Error("Remote action is not allowed");
|
|
1075
|
+
policyRequest = {
|
|
1076
|
+
...request,
|
|
1077
|
+
type: "execute"
|
|
1078
|
+
};
|
|
1079
|
+
if (policy?.authorize && await policy.authorize(policyRequest) !== true) throw new Error("Transport request is not authorized");
|
|
1080
|
+
assertActive();
|
|
1081
|
+
let action = store.getState();
|
|
1082
|
+
let receiver;
|
|
1083
|
+
for (const key of request.action) {
|
|
1084
|
+
if (isUnsafePathSegment(key) || typeof action !== "object" && typeof action !== "function" || action === null || !Object.prototype.hasOwnProperty.call(action, key)) throw new Error("The function is not found");
|
|
1085
|
+
receiver = action;
|
|
1086
|
+
action = action[key];
|
|
1087
|
+
}
|
|
1088
|
+
if (typeof action !== "function") throw new Error("The function is not found");
|
|
1089
|
+
const value = await Reflect.apply(action, receiver, request.args);
|
|
1090
|
+
assertActive();
|
|
1091
|
+
return encodeExecuteResponse({
|
|
1092
|
+
epoch,
|
|
1093
|
+
ok: true,
|
|
1094
|
+
sequence: internal.sequence,
|
|
1095
|
+
...typeof value === "undefined" ? {} : { value }
|
|
1096
|
+
});
|
|
1097
|
+
} catch (error) {
|
|
1098
|
+
if (process.env.NODE_ENV === "development") console.error(error);
|
|
1099
|
+
return encodeExecuteResponse({
|
|
1100
|
+
epoch,
|
|
1101
|
+
error: await getErrorMessage(error, policyRequest, policy),
|
|
1102
|
+
ok: false,
|
|
1103
|
+
sequence: internal.sequence
|
|
760
1104
|
});
|
|
761
1105
|
}
|
|
762
|
-
if (isTransportErrorEnvelope(result)) throw new Error(result.message);
|
|
763
|
-
if (isLegacyTransportErrorEnvelope(result)) throw new Error(result.$$Error);
|
|
764
|
-
return result;
|
|
765
1106
|
}));
|
|
1107
|
+
registerDisposer(transport.listen("fullSync", async (encoded) => {
|
|
1108
|
+
assertActive();
|
|
1109
|
+
decodeFullSyncRequest(encoded);
|
|
1110
|
+
if (policy?.authorize && await policy.authorize({ type: "fullSync" }) !== true) throw new Error("Transport request is not authorized");
|
|
1111
|
+
assertActive();
|
|
1112
|
+
const state = internal.getTransportState?.() ?? internal.rootState;
|
|
1113
|
+
validateSharedStateSerializable(state);
|
|
1114
|
+
if (typeof state !== "object" || state === null || Array.isArray(state)) throw new TypeError("Shared store state must be a JSON object");
|
|
1115
|
+
return encodeFullSyncResponse({
|
|
1116
|
+
epoch,
|
|
1117
|
+
sequence: internal.sequence,
|
|
1118
|
+
state
|
|
1119
|
+
});
|
|
1120
|
+
}));
|
|
1121
|
+
} catch (error) {
|
|
1122
|
+
internal.destroyCallbacks?.delete(cleanup);
|
|
1123
|
+
cleanup();
|
|
1124
|
+
store.transport = void 0;
|
|
1125
|
+
try {
|
|
1126
|
+
transport.dispose?.();
|
|
1127
|
+
} catch (disposeError) {
|
|
1128
|
+
if (process.env.NODE_ENV === "development") console.error(disposeError);
|
|
1129
|
+
}
|
|
1130
|
+
throw error;
|
|
1131
|
+
}
|
|
1132
|
+
};
|
|
1133
|
+
//#endregion
|
|
1134
|
+
//#region packages/core/src/applyMiddlewares.ts
|
|
1135
|
+
const isStoreLike = (value) => {
|
|
1136
|
+
if (!value || typeof value !== "object") return false;
|
|
1137
|
+
const candidate = value;
|
|
1138
|
+
return typeof candidate.setState === "function" && typeof candidate.getState === "function" && typeof candidate.subscribe === "function" && typeof candidate.destroy === "function" && typeof candidate.apply === "function" && typeof candidate.getPureState === "function";
|
|
1139
|
+
};
|
|
1140
|
+
const applyMiddlewares = (store, middlewares) => {
|
|
1141
|
+
return middlewares.reduce((store, middleware, index) => {
|
|
1142
|
+
if (process.env.NODE_ENV === "development") {
|
|
1143
|
+
if (typeof middleware !== "function") throw new Error(`middlewares[${index}] should be a function`);
|
|
1144
|
+
}
|
|
1145
|
+
const nextStore = middleware(store);
|
|
1146
|
+
if (process.env.NODE_ENV === "development") {
|
|
1147
|
+
if (!isStoreLike(nextStore)) throw new Error(`middlewares[${index}] should return a store-like object`);
|
|
1148
|
+
}
|
|
1149
|
+
return nextStore;
|
|
1150
|
+
}, store);
|
|
1151
|
+
};
|
|
1152
|
+
//#endregion
|
|
1153
|
+
//#region packages/core/src/getInitialState.ts
|
|
1154
|
+
const isObject = (value) => typeof value === "object" && value !== null;
|
|
1155
|
+
const isStateFactory = (value) => typeof value === "function";
|
|
1156
|
+
const hasGetState = (value) => (typeof value === "object" || typeof value === "function") && value !== null && typeof value.getState === "function";
|
|
1157
|
+
const hasBindState = (value) => isObject(value) && !!value[bindSymbol];
|
|
1158
|
+
const formatInvalidStateMessage = (type, stateOrFn, key) => `Invalid state ${type} encountered in makeState: ${typeof key !== "undefined" ? `for key ${String(key)}, ` : ""}${typeof stateOrFn}`;
|
|
1159
|
+
const getInitialState = (store, createState, internal) => {
|
|
1160
|
+
const makeState = (stateOrFn, key) => {
|
|
1161
|
+
let state;
|
|
1162
|
+
if (isStateFactory(stateOrFn)) state = stateOrFn(store.setState, store.getState, store);
|
|
1163
|
+
else if (isObject(stateOrFn)) state = stateOrFn;
|
|
1164
|
+
else {
|
|
1165
|
+
if (process.env.NODE_ENV !== "production") throw new Error(formatInvalidStateMessage("value", stateOrFn, key));
|
|
1166
|
+
return {};
|
|
1167
|
+
}
|
|
1168
|
+
if (hasGetState(state)) state = state.getState();
|
|
1169
|
+
else if (typeof state === "function") state = state();
|
|
1170
|
+
if (hasBindState(state)) {
|
|
1171
|
+
if (store.isSliceStore) throw new Error("Third-party state binding does not support Slices mode. Please inject a whole store instead.");
|
|
1172
|
+
const binder = state[bindSymbol];
|
|
1173
|
+
const rawState = binder.bind(state);
|
|
1174
|
+
binder.handleStore(store, rawState, state, internal, key);
|
|
1175
|
+
delete state[bindSymbol];
|
|
1176
|
+
return rawState;
|
|
1177
|
+
}
|
|
1178
|
+
if (!isObject(state)) {
|
|
1179
|
+
if (process.env.NODE_ENV !== "production") throw new Error(formatInvalidStateMessage("result", state, key));
|
|
1180
|
+
return {};
|
|
1181
|
+
}
|
|
1182
|
+
return state;
|
|
1183
|
+
};
|
|
1184
|
+
if (!store.isSliceStore) return makeState(createState);
|
|
1185
|
+
return getOwnEnumerableKeys(createState).reduce((stateTree, key) => {
|
|
1186
|
+
if (typeof key === "string" && isUnsafeKey(key)) return stateTree;
|
|
1187
|
+
setOwnEnumerable(stateTree, key, makeState(createState[key], key));
|
|
1188
|
+
return stateTree;
|
|
1189
|
+
}, {});
|
|
1190
|
+
};
|
|
1191
|
+
//#endregion
|
|
1192
|
+
//#region packages/core/src/storeCommit.ts
|
|
1193
|
+
const storeCommitRuntimeSymbol = Symbol.for("coaction.storeCommit.runtime");
|
|
1194
|
+
const getStoreCommitRuntime = (store, create = false) => {
|
|
1195
|
+
const target = store;
|
|
1196
|
+
const existing = target[storeCommitRuntimeSymbol];
|
|
1197
|
+
if (existing || !create) return existing;
|
|
1198
|
+
const runtime = {
|
|
1199
|
+
disposed: false,
|
|
1200
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
1201
|
+
prepareListeners: /* @__PURE__ */ new Set()
|
|
1202
|
+
};
|
|
1203
|
+
Object.defineProperty(target, storeCommitRuntimeSymbol, {
|
|
1204
|
+
configurable: true,
|
|
1205
|
+
enumerable: true,
|
|
1206
|
+
value: runtime,
|
|
1207
|
+
writable: true
|
|
1208
|
+
});
|
|
1209
|
+
return runtime;
|
|
1210
|
+
};
|
|
1211
|
+
/** @internal */
|
|
1212
|
+
const hasStoreCommitListeners = (store) => Boolean(getStoreCommitRuntime(store)?.listeners.size);
|
|
1213
|
+
/** @internal */
|
|
1214
|
+
const publishStoreCommit = (store, commit) => {
|
|
1215
|
+
const runtime = getStoreCommitRuntime(store);
|
|
1216
|
+
if (!runtime || runtime.disposed || !runtime.listeners.size) return;
|
|
1217
|
+
for (const listener of [...runtime.listeners]) listener(commit);
|
|
1218
|
+
};
|
|
1219
|
+
/** @internal */
|
|
1220
|
+
const prepareStoreCommit = (store, commit) => {
|
|
1221
|
+
const runtime = getStoreCommitRuntime(store);
|
|
1222
|
+
if (!runtime || runtime.disposed || !runtime.prepareListeners.size) return false;
|
|
1223
|
+
let replace = false;
|
|
1224
|
+
for (const listener of runtime.prepareListeners) replace = listener(commit) === true || replace;
|
|
1225
|
+
return replace;
|
|
1226
|
+
};
|
|
1227
|
+
/** @internal */
|
|
1228
|
+
const getStoreCommitSource = (store, fallback) => getStoreCommitRuntime(store)?.source ?? fallback;
|
|
1229
|
+
/** @internal */
|
|
1230
|
+
const runWithStoreCommitSource = (store, source, callback) => {
|
|
1231
|
+
const runtime = getStoreCommitRuntime(store, true);
|
|
1232
|
+
const previousSource = runtime.source;
|
|
1233
|
+
runtime.source = source;
|
|
1234
|
+
try {
|
|
1235
|
+
return callback();
|
|
1236
|
+
} finally {
|
|
1237
|
+
runtime.source = previousSource;
|
|
1238
|
+
}
|
|
1239
|
+
};
|
|
1240
|
+
/** @internal */
|
|
1241
|
+
const registerStorePatchReplayer = (store, replay) => {
|
|
1242
|
+
const runtime = getStoreCommitRuntime(store, true);
|
|
1243
|
+
runtime.replay = replay;
|
|
1244
|
+
};
|
|
1245
|
+
/** @internal */
|
|
1246
|
+
const disposeStoreCommitRuntime = (store) => {
|
|
1247
|
+
const runtime = getStoreCommitRuntime(store);
|
|
1248
|
+
if (!runtime) return;
|
|
1249
|
+
runtime.disposed = true;
|
|
1250
|
+
runtime.listeners.clear();
|
|
1251
|
+
runtime.prepareListeners.clear();
|
|
1252
|
+
runtime.source = void 0;
|
|
1253
|
+
runtime.replay = void 0;
|
|
1254
|
+
};
|
|
1255
|
+
//#endregion
|
|
1256
|
+
//#region packages/core/src/handleDraft.ts
|
|
1257
|
+
const handleDraft = (store, internal) => {
|
|
1258
|
+
internal.rootState = internal.backupState;
|
|
1259
|
+
const [, patches, inversePatches] = internal.finalizeDraft();
|
|
1260
|
+
const finalPatches = store.patch ? store.patch({
|
|
1261
|
+
patches,
|
|
1262
|
+
inversePatches
|
|
1263
|
+
}) : {
|
|
1264
|
+
patches,
|
|
1265
|
+
inversePatches
|
|
766
1266
|
};
|
|
1267
|
+
const safePatches = sanitizeCheckedPatches(finalPatches.patches, "store.patch()");
|
|
1268
|
+
const safeInversePatches = sanitizeCheckedPatches(finalPatches.inversePatches, "store.patch() inverse patches");
|
|
1269
|
+
if (safePatches.length) {
|
|
1270
|
+
store.apply(internal.rootState, safePatches);
|
|
1271
|
+
internal.emitPatches?.(safePatches);
|
|
1272
|
+
publishStoreCommit(store, {
|
|
1273
|
+
state: internal.rootState,
|
|
1274
|
+
patches: safePatches,
|
|
1275
|
+
inversePatches: safeInversePatches,
|
|
1276
|
+
source: "mutableAction"
|
|
1277
|
+
});
|
|
1278
|
+
}
|
|
767
1279
|
};
|
|
768
1280
|
//#endregion
|
|
769
1281
|
//#region packages/core/src/getRawStateLocalAction.ts
|
|
@@ -809,7 +1321,7 @@ const createLocalAction = ({ fn, internal, key, options, store, sliceKey }) => {
|
|
|
809
1321
|
throw error;
|
|
810
1322
|
}
|
|
811
1323
|
};
|
|
812
|
-
const enablePatches = store.transport ?? options.enablePatches;
|
|
1324
|
+
const enablePatches = Boolean(store.transport ?? options.enablePatches) || hasStoreCommitListeners(store);
|
|
813
1325
|
return traceAction(() => {
|
|
814
1326
|
if (internal.mutableInstance && !internal.isBatching && enablePatches) {
|
|
815
1327
|
let result;
|
|
@@ -851,78 +1363,64 @@ const createLocalAction = ({ fn, internal, key, options, store, sliceKey }) => {
|
|
|
851
1363
|
});
|
|
852
1364
|
};
|
|
853
1365
|
};
|
|
854
|
-
//#endregion
|
|
855
|
-
//#region packages/core/src/
|
|
856
|
-
const
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
};
|
|
887
|
-
const createCachedGetter = (internal, getter) => {
|
|
888
|
-
const accessors = /* @__PURE__ */ new WeakMap();
|
|
889
|
-
const fallbackReceiver = {};
|
|
890
|
-
return function() {
|
|
891
|
-
const receiver = typeof this === "object" && this !== null ? this : fallbackReceiver;
|
|
892
|
-
if (internal.isBatching) return getter.call(receiver);
|
|
893
|
-
let accessor = accessors.get(receiver);
|
|
894
|
-
if (!accessor) {
|
|
895
|
-
accessor = (0, alien_signals.computed)(() => getter.call(receiver));
|
|
896
|
-
accessors.set(receiver, accessor);
|
|
897
|
-
}
|
|
898
|
-
return accessor();
|
|
899
|
-
};
|
|
900
|
-
};
|
|
901
|
-
const createTrackedStateReader = (internal, read, initialValue) => {
|
|
902
|
-
const slotSignal = (0, alien_signals.signal)(initialValue);
|
|
903
|
-
const slotVersionSignal = (0, alien_signals.signal)(0);
|
|
904
|
-
let slotVersion = 0;
|
|
905
|
-
(internal.signalSlots ??= /* @__PURE__ */ new Set()).add({ refresh: () => {
|
|
906
|
-
const nextValue = read();
|
|
907
|
-
slotSignal(nextValue);
|
|
908
|
-
if (internal.mutableInstance && isObjectLike(nextValue)) {
|
|
909
|
-
slotVersion += 1;
|
|
910
|
-
slotVersionSignal(slotVersion);
|
|
1366
|
+
//#endregion
|
|
1367
|
+
//#region packages/core/src/immutableState.ts
|
|
1368
|
+
const isImmutableStateObject = (value) => {
|
|
1369
|
+
if (typeof value !== "object" || value === null) return false;
|
|
1370
|
+
if (Array.isArray(value)) return true;
|
|
1371
|
+
const prototype = Object.getPrototypeOf(value);
|
|
1372
|
+
return prototype === Object.prototype || prototype === null;
|
|
1373
|
+
};
|
|
1374
|
+
const getImmutableStateSnapshot = (value, cache) => {
|
|
1375
|
+
if (!isImmutableStateObject(value)) return value;
|
|
1376
|
+
const cached = cache.get(value);
|
|
1377
|
+
if (cached) return cached;
|
|
1378
|
+
const isArray = Array.isArray(value);
|
|
1379
|
+
const snapshot = isArray ? new Array(value.length) : Object.create(Object.getPrototypeOf(value));
|
|
1380
|
+
cache.set(value, snapshot);
|
|
1381
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
1382
|
+
if (isArray && key === "length") continue;
|
|
1383
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
1384
|
+
if (Object.prototype.hasOwnProperty.call(descriptor, "value")) descriptor.value = getImmutableStateSnapshot(descriptor.value, cache);
|
|
1385
|
+
Object.defineProperty(snapshot, key, descriptor);
|
|
1386
|
+
}
|
|
1387
|
+
return Object.freeze(snapshot);
|
|
1388
|
+
};
|
|
1389
|
+
const createImmutableSnapshotPatches = (patches, cache) => patches.map((patch) => Object.prototype.hasOwnProperty.call(patch, "value") ? {
|
|
1390
|
+
...patch,
|
|
1391
|
+
value: getImmutableStateSnapshot(patch.value, cache)
|
|
1392
|
+
} : patch);
|
|
1393
|
+
const finalizeImmutableStateSnapshot = (state, snapshot, patches, cache, sources) => {
|
|
1394
|
+
const mapPair = (value, snapshotValue) => {
|
|
1395
|
+
if (isImmutableStateObject(value) && isImmutableStateObject(snapshotValue)) {
|
|
1396
|
+
cache.set(value, snapshotValue);
|
|
1397
|
+
sources?.set(snapshotValue, value);
|
|
911
1398
|
}
|
|
912
|
-
} });
|
|
913
|
-
return () => {
|
|
914
|
-
const currentValue = slotSignal();
|
|
915
|
-
if (internal.mutableInstance && isObjectLike(currentValue)) slotVersionSignal();
|
|
916
|
-
return read();
|
|
917
1399
|
};
|
|
1400
|
+
mapPair(state, snapshot);
|
|
1401
|
+
for (const patch of patches) {
|
|
1402
|
+
let value = state;
|
|
1403
|
+
let snapshotValue = snapshot;
|
|
1404
|
+
const ancestors = [];
|
|
1405
|
+
if (isImmutableStateObject(snapshotValue)) ancestors.push(snapshotValue);
|
|
1406
|
+
for (const key of patch.path) {
|
|
1407
|
+
if (!isImmutableStateObject(value) || !isImmutableStateObject(snapshotValue)) break;
|
|
1408
|
+
value = value[key];
|
|
1409
|
+
snapshotValue = snapshotValue[key];
|
|
1410
|
+
mapPair(value, snapshotValue);
|
|
1411
|
+
if (isImmutableStateObject(snapshotValue)) ancestors.push(snapshotValue);
|
|
1412
|
+
}
|
|
1413
|
+
for (let index = ancestors.length - 1; index >= 0; index -= 1) if (!Object.isFrozen(ancestors[index])) Object.freeze(ancestors[index]);
|
|
1414
|
+
}
|
|
918
1415
|
};
|
|
919
|
-
const
|
|
920
|
-
if (!
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
(
|
|
1416
|
+
const indexImmutableStateSnapshot = (state, snapshot, sources, seen = /* @__PURE__ */ new WeakSet()) => {
|
|
1417
|
+
if (!isImmutableStateObject(state) || !isImmutableStateObject(snapshot) || seen.has(snapshot)) return;
|
|
1418
|
+
seen.add(snapshot);
|
|
1419
|
+
sources.set(snapshot, state);
|
|
1420
|
+
for (const key of Reflect.ownKeys(state)) {
|
|
1421
|
+
const stateDescriptor = Object.getOwnPropertyDescriptor(state, key);
|
|
1422
|
+
const snapshotDescriptor = Object.getOwnPropertyDescriptor(snapshot, key);
|
|
1423
|
+
if (stateDescriptor && snapshotDescriptor && Object.prototype.hasOwnProperty.call(stateDescriptor, "value") && Object.prototype.hasOwnProperty.call(snapshotDescriptor, "value")) indexImmutableStateSnapshot(stateDescriptor.value, snapshotDescriptor.value, sources, seen);
|
|
926
1424
|
}
|
|
927
1425
|
};
|
|
928
1426
|
//#endregion
|
|
@@ -932,12 +1430,6 @@ const assertImmutableStateMutationAllowed = (internal) => {
|
|
|
932
1430
|
throw new Error("Direct state mutation is not allowed in immutable Coaction stores. Wrap mutations in set(() => { ... }).");
|
|
933
1431
|
};
|
|
934
1432
|
const readonlyProxyCache = /* @__PURE__ */ new WeakMap();
|
|
935
|
-
const isReadonlyProxyable = (value) => {
|
|
936
|
-
if (typeof value !== "object" || value === null) return false;
|
|
937
|
-
if (Array.isArray(value)) return true;
|
|
938
|
-
const prototype = Object.getPrototypeOf(value);
|
|
939
|
-
return prototype === Object.prototype || prototype === null;
|
|
940
|
-
};
|
|
941
1433
|
const getReadonlyProxyCache = (internal) => {
|
|
942
1434
|
let cache = readonlyProxyCache.get(internal);
|
|
943
1435
|
if (!cache) {
|
|
@@ -954,7 +1446,12 @@ const getPublicStateObject = (internal, value, sliceKey) => {
|
|
|
954
1446
|
if (rootState[sliceKey] === value) return module[sliceKey];
|
|
955
1447
|
};
|
|
956
1448
|
const toReadonlyStateValue = (internal, value, sliceKey) => {
|
|
957
|
-
if (internal.mutableInstance || internal.isBatching || !
|
|
1449
|
+
if (internal.mutableInstance || internal.isBatching || !isImmutableStateObject(value)) return value;
|
|
1450
|
+
if (internal.computedReadDepth) {
|
|
1451
|
+
const cache = internal.computedSnapshotCache ??= /* @__PURE__ */ new WeakMap();
|
|
1452
|
+
if (isImmutableStateObject(internal.rootState) && !cache.has(internal.rootState)) getImmutableStateSnapshot(internal.rootState, cache);
|
|
1453
|
+
return getImmutableStateSnapshot(value, cache);
|
|
1454
|
+
}
|
|
958
1455
|
const publicValue = getPublicStateObject(internal, value, sliceKey);
|
|
959
1456
|
if (publicValue) return publicValue;
|
|
960
1457
|
const cache = getReadonlyProxyCache(internal);
|
|
@@ -984,6 +1481,18 @@ const toReadonlyStateValue = (internal, value, sliceKey) => {
|
|
|
984
1481
|
cache.set(value, proxy);
|
|
985
1482
|
return proxy;
|
|
986
1483
|
};
|
|
1484
|
+
const toPublicComputedValue = (internal, value, sliceKey) => {
|
|
1485
|
+
if (!isImmutableStateObject(value)) return value;
|
|
1486
|
+
const rootSnapshot = internal.computedSnapshotCache?.get(internal.rootState);
|
|
1487
|
+
const sources = internal.computedSnapshotSources ??= /* @__PURE__ */ new WeakMap();
|
|
1488
|
+
let source = sources.get(value);
|
|
1489
|
+
if (!source && Object.isFrozen(value) && rootSnapshot) {
|
|
1490
|
+
indexImmutableStateSnapshot(internal.rootState, rootSnapshot, sources);
|
|
1491
|
+
source = sources.get(value);
|
|
1492
|
+
}
|
|
1493
|
+
if (source) internal.computedIdentityRequired = true;
|
|
1494
|
+
return source ? toReadonlyStateValue(internal, source, sliceKey) : value;
|
|
1495
|
+
};
|
|
987
1496
|
const prepareStateDescriptor = ({ descriptor, initialStateSeen, internal, key, rawState, sliceKey }) => {
|
|
988
1497
|
const isComputed = descriptor.value instanceof Computed;
|
|
989
1498
|
const readStateValue = () => typeof sliceKey !== "undefined" ? internal.rootState[sliceKey][key] : internal.rootState[key];
|
|
@@ -1004,7 +1513,10 @@ const prepareStateDescriptor = ({ descriptor, initialStateSeen, internal, key, r
|
|
|
1004
1513
|
});
|
|
1005
1514
|
if (isComputed) {
|
|
1006
1515
|
if (internal.mutableInstance) throw new Error("Computed is not supported with mutable instance");
|
|
1007
|
-
|
|
1516
|
+
const getComputed = descriptor.value.createGetter({ internal });
|
|
1517
|
+
descriptor.get = function() {
|
|
1518
|
+
return toPublicComputedValue(internal, getComputed.call(this), sliceKey);
|
|
1519
|
+
};
|
|
1008
1520
|
} else if (typeof sliceKey !== "undefined") {
|
|
1009
1521
|
const read = createTrackedStateReader(internal, readStateValue, initialValue);
|
|
1010
1522
|
descriptor.get = () => toReadonlyStateValue(internal, read(), sliceKey);
|
|
@@ -1023,9 +1535,12 @@ const prepareStateDescriptor = ({ descriptor, initialStateSeen, internal, key, r
|
|
|
1023
1535
|
delete descriptor.value;
|
|
1024
1536
|
delete descriptor.writable;
|
|
1025
1537
|
};
|
|
1026
|
-
const prepareAccessorDescriptor = ({ descriptor, internal }) => {
|
|
1538
|
+
const prepareAccessorDescriptor = ({ descriptor, internal, sliceKey }) => {
|
|
1027
1539
|
if (internal.mutableInstance || typeof descriptor.get !== "function") return;
|
|
1028
|
-
|
|
1540
|
+
const getComputed = createCachedGetter(internal, descriptor.get);
|
|
1541
|
+
descriptor.get = function() {
|
|
1542
|
+
return toPublicComputedValue(internal, getComputed.call(this), sliceKey);
|
|
1543
|
+
};
|
|
1029
1544
|
};
|
|
1030
1545
|
//#endregion
|
|
1031
1546
|
//#region packages/core/src/getRawState.ts
|
|
@@ -1040,7 +1555,7 @@ const getClientExecuteSyncTimeoutMs = (options) => {
|
|
|
1040
1555
|
if (!Number.isFinite(timeout) || timeout < 0) throw new Error("executeSyncTimeoutMs must be a finite number greater than or equal to 0");
|
|
1041
1556
|
return timeout;
|
|
1042
1557
|
};
|
|
1043
|
-
const getRawState = (store, internal, initialState, options) => {
|
|
1558
|
+
const getRawState = (store, internal, initialState, options, createClientAction) => {
|
|
1044
1559
|
const clientExecuteSyncTimeoutMs = getClientExecuteSyncTimeoutMs(options);
|
|
1045
1560
|
const rawState = {};
|
|
1046
1561
|
const handle = (_rawState, _initialState, sliceKey) => {
|
|
@@ -1059,7 +1574,8 @@ const getRawState = (store, internal, initialState, options) => {
|
|
|
1059
1574
|
if (!Object.prototype.hasOwnProperty.call(descriptor, "value")) {
|
|
1060
1575
|
prepareAccessorDescriptor({
|
|
1061
1576
|
descriptor,
|
|
1062
|
-
internal
|
|
1577
|
+
internal,
|
|
1578
|
+
sliceKey
|
|
1063
1579
|
});
|
|
1064
1580
|
return;
|
|
1065
1581
|
}
|
|
@@ -1077,6 +1593,7 @@ const getRawState = (store, internal, initialState, options) => {
|
|
|
1077
1593
|
}
|
|
1078
1594
|
if (store.share === "client") {
|
|
1079
1595
|
if (typeof key !== "string") return;
|
|
1596
|
+
if (!createClientAction) throw new Error("Client action runtime is not configured");
|
|
1080
1597
|
descriptor.value = createClientAction({
|
|
1081
1598
|
clientExecuteSyncTimeoutMs,
|
|
1082
1599
|
internal,
|
|
@@ -1111,8 +1628,13 @@ const getRawState = (store, internal, initialState, options) => {
|
|
|
1111
1628
|
//#endregion
|
|
1112
1629
|
//#region packages/core/src/handleState.ts
|
|
1113
1630
|
const handleState = (store, internal, options) => {
|
|
1631
|
+
let defaultResultValidated = false;
|
|
1632
|
+
let pendingCommitSource;
|
|
1114
1633
|
const defaultUpdater = (next) => {
|
|
1634
|
+
defaultResultValidated = false;
|
|
1635
|
+
let producedState;
|
|
1115
1636
|
const merge = (_next = next) => {
|
|
1637
|
+
if (_next !== next) internal.validateState?.(_next);
|
|
1116
1638
|
assertKnownStateShape(_next, internal.rootState, internal.stateSchema, store.isSliceStore);
|
|
1117
1639
|
mergeObject(internal.rootState, _next, store.isSliceStore);
|
|
1118
1640
|
};
|
|
@@ -1124,14 +1646,16 @@ const handleState = (store, internal, options) => {
|
|
|
1124
1646
|
}
|
|
1125
1647
|
if (typeof returnValue === "object" && returnValue !== null) merge(returnValue);
|
|
1126
1648
|
} : merge;
|
|
1127
|
-
if (!(store.transport ?? options.enablePatches) && internal.mutableInstance) {
|
|
1649
|
+
if (!(Boolean(store.transport ?? options.enablePatches) || hasStoreCommitListeners(store)) && internal.mutableInstance) {
|
|
1128
1650
|
if (internal.actMutable) {
|
|
1129
1651
|
internal.actMutable(() => {
|
|
1130
1652
|
fn.apply(null);
|
|
1131
1653
|
});
|
|
1654
|
+
defaultResultValidated = true;
|
|
1132
1655
|
return [];
|
|
1133
1656
|
}
|
|
1134
1657
|
fn.apply(null);
|
|
1658
|
+
defaultResultValidated = true;
|
|
1135
1659
|
return [];
|
|
1136
1660
|
}
|
|
1137
1661
|
internal.backupState = internal.rootState;
|
|
@@ -1143,22 +1667,40 @@ const handleState = (store, internal, options) => {
|
|
|
1143
1667
|
return fn.apply(null);
|
|
1144
1668
|
}, { enablePatches: true });
|
|
1145
1669
|
assertKnownStateShape(result[0], internal.backupState, internal.stateSchema, store.isSliceStore, { requireSliceRoots: true });
|
|
1146
|
-
|
|
1670
|
+
internal.validateState?.(internal.getTransportState?.() ?? result[0]);
|
|
1671
|
+
producedState = result[0];
|
|
1147
1672
|
patches = result[1];
|
|
1148
1673
|
inversePatches = result[2];
|
|
1149
1674
|
} finally {
|
|
1150
1675
|
internal.rootState = internal.backupState;
|
|
1151
1676
|
}
|
|
1152
|
-
const
|
|
1677
|
+
const patch = store.patch;
|
|
1678
|
+
const finalPatches = patch ? patch({
|
|
1153
1679
|
patches,
|
|
1154
1680
|
inversePatches
|
|
1155
1681
|
}) : {
|
|
1156
1682
|
patches,
|
|
1157
1683
|
inversePatches
|
|
1158
1684
|
};
|
|
1685
|
+
if (!patch) internal.validatePatches?.(finalPatches.patches);
|
|
1159
1686
|
const safePatches = sanitizeCheckedPatches(finalPatches.patches, "store.patch()");
|
|
1160
1687
|
const safeInversePatches = sanitizeCheckedPatches(finalPatches.inversePatches, "store.patch() inverse patches");
|
|
1161
|
-
if (safePatches.
|
|
1688
|
+
if (producedState && safePatches.some((patch) => typeof patch.value === "object" && patch.value !== null) && prepareStoreCommit(store, {
|
|
1689
|
+
state: producedState,
|
|
1690
|
+
patches: safePatches,
|
|
1691
|
+
inversePatches: safeInversePatches,
|
|
1692
|
+
source: "setState"
|
|
1693
|
+
})) {
|
|
1694
|
+
runWithStoreCommitSource(store, "setState", () => {
|
|
1695
|
+
store.apply(producedState);
|
|
1696
|
+
});
|
|
1697
|
+
defaultResultValidated = true;
|
|
1698
|
+
return [];
|
|
1699
|
+
}
|
|
1700
|
+
if (safePatches.length) {
|
|
1701
|
+
defaultResultValidated = internal.applyValidatedPatches?.(internal.rootState, safePatches, !patch) ?? false;
|
|
1702
|
+
if (!internal.applyValidatedPatches) store.apply(internal.rootState, safePatches);
|
|
1703
|
+
} else defaultResultValidated = true;
|
|
1162
1704
|
return [
|
|
1163
1705
|
internal.rootState,
|
|
1164
1706
|
safePatches,
|
|
@@ -1166,17 +1708,26 @@ const handleState = (store, internal, options) => {
|
|
|
1166
1708
|
];
|
|
1167
1709
|
};
|
|
1168
1710
|
const setState = (next, updater = defaultUpdater) => {
|
|
1711
|
+
const commitSource = pendingCommitSource ?? "setState";
|
|
1712
|
+
pendingCommitSource = void 0;
|
|
1169
1713
|
internal.assertAlive?.("setState");
|
|
1170
1714
|
internal.assertMutationAllowed?.("setState");
|
|
1171
1715
|
if (store.share === "client") throw new Error(`setState() cannot be called in the client store. To update the state, please trigger a store method with setState() instead.`);
|
|
1172
1716
|
if (internal.isBatching) throw new Error("setState cannot be called within the updater");
|
|
1173
1717
|
if (next === null) return [];
|
|
1174
|
-
if (typeof next === "object")
|
|
1718
|
+
if (typeof next === "object") {
|
|
1719
|
+
internal.validateState?.(next);
|
|
1720
|
+
assertKnownStateShape(next, internal.rootState, internal.stateSchema, store.isSliceStore);
|
|
1721
|
+
}
|
|
1175
1722
|
internal.isBatching = true;
|
|
1176
|
-
if (!store.share && !options.enablePatches && !internal.mutableInstance && updater === defaultUpdater) try {
|
|
1723
|
+
if (!store.share && !options.enablePatches && !hasStoreCommitListeners(store) && !internal.mutableInstance && updater === defaultUpdater) try {
|
|
1177
1724
|
if (typeof next === "function") try {
|
|
1178
1725
|
internal.backupState = internal.rootState;
|
|
1179
|
-
const
|
|
1726
|
+
const snapshotCache = internal.computedSnapshotCache;
|
|
1727
|
+
const snapshotSources = internal.computedIdentityRequired ? internal.computedSnapshotSources : void 0;
|
|
1728
|
+
const snapshot = snapshotCache?.get(internal.rootState);
|
|
1729
|
+
const updateSnapshot = Boolean(snapshot && snapshotCache);
|
|
1730
|
+
const produced = (0, mutative.create)(internal.rootState, (draft) => {
|
|
1180
1731
|
internal.rootState = draft;
|
|
1181
1732
|
const returnValue = next(internal.module);
|
|
1182
1733
|
if (returnValue instanceof Promise) {
|
|
@@ -1187,8 +1738,13 @@ const handleState = (store, internal, options) => {
|
|
|
1187
1738
|
assertKnownStateShape(returnValue, internal.rootState, internal.stateSchema, store.isSliceStore);
|
|
1188
1739
|
mergeObject(internal.rootState, returnValue, store.isSliceStore);
|
|
1189
1740
|
}
|
|
1190
|
-
});
|
|
1741
|
+
}, { enablePatches: updateSnapshot });
|
|
1742
|
+
const nextState = updateSnapshot ? produced[0] : produced;
|
|
1191
1743
|
assertKnownStateShape(nextState, internal.backupState, internal.stateSchema, store.isSliceStore, { requireSliceRoots: true });
|
|
1744
|
+
if (updateSnapshot) {
|
|
1745
|
+
const patches = produced[1];
|
|
1746
|
+
finalizeImmutableStateSnapshot(nextState, (0, mutative.apply)(snapshot, createImmutableSnapshotPatches(patches, snapshotCache)), patches, snapshotCache, snapshotSources);
|
|
1747
|
+
}
|
|
1192
1748
|
internal.rootState = nextState;
|
|
1193
1749
|
} catch (error) {
|
|
1194
1750
|
internal.rootState = internal.backupState;
|
|
@@ -1226,7 +1782,7 @@ const handleState = (store, internal, options) => {
|
|
|
1226
1782
|
if (isDrafted) handleDraft(store, internal);
|
|
1227
1783
|
result = updater(next);
|
|
1228
1784
|
if (internal.mutableInstance) assertKnownStateShape(internal.rootState, internal.backupState ?? internal.rootState, internal.stateSchema, store.isSliceStore, { requireSliceRoots: true });
|
|
1229
|
-
if (
|
|
1785
|
+
if (!(updater === defaultUpdater && defaultResultValidated)) internal.validateState?.(internal.getTransportState?.() ?? internal.rootState);
|
|
1230
1786
|
if (isDrafted) {
|
|
1231
1787
|
internal.backupState = internal.rootState;
|
|
1232
1788
|
const [draft, finalize] = (0, mutative.create)(internal.rootState, { enablePatches: true });
|
|
@@ -1236,110 +1792,267 @@ const handleState = (store, internal, options) => {
|
|
|
1236
1792
|
} finally {
|
|
1237
1793
|
internal.isBatching = false;
|
|
1238
1794
|
}
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1795
|
+
const trustedDefaultResult = updater === defaultUpdater && defaultResultValidated;
|
|
1796
|
+
if (result?.length && !trustedDefaultResult) {
|
|
1797
|
+
internal.validatePatches?.(result[1]);
|
|
1798
|
+
result = [
|
|
1799
|
+
result[0],
|
|
1800
|
+
sanitizeCheckedPatches(result[1], "setState updater result"),
|
|
1801
|
+
sanitizeCheckedPatches(result[2], "setState updater inverse result")
|
|
1802
|
+
];
|
|
1803
|
+
}
|
|
1804
|
+
if (result?.length === 3) {
|
|
1805
|
+
const [, patches, inversePatches] = result;
|
|
1806
|
+
internal.emitPatches?.(patches);
|
|
1807
|
+
if (patches.length || inversePatches.length) publishStoreCommit(store, {
|
|
1808
|
+
state: internal.rootState,
|
|
1809
|
+
patches,
|
|
1810
|
+
inversePatches,
|
|
1811
|
+
source: commitSource
|
|
1812
|
+
});
|
|
1813
|
+
}
|
|
1245
1814
|
return result;
|
|
1246
1815
|
};
|
|
1816
|
+
const replayPatches = ({ patches, inversePatches }, replaySetState = setState) => {
|
|
1817
|
+
const previousSource = pendingCommitSource;
|
|
1818
|
+
pendingCommitSource = "replay";
|
|
1819
|
+
try {
|
|
1820
|
+
replaySetState(internal.rootState, () => {
|
|
1821
|
+
const inputPatches = patches.map((patch) => ({
|
|
1822
|
+
...patch,
|
|
1823
|
+
path: Array.isArray(patch.path) ? [...patch.path] : patch.path
|
|
1824
|
+
}));
|
|
1825
|
+
const inputInversePatches = inversePatches.map((patch) => ({
|
|
1826
|
+
...patch,
|
|
1827
|
+
path: Array.isArray(patch.path) ? [...patch.path] : patch.path
|
|
1828
|
+
}));
|
|
1829
|
+
const finalPatches = store.patch ? store.patch({
|
|
1830
|
+
patches: inputPatches,
|
|
1831
|
+
inversePatches: inputInversePatches
|
|
1832
|
+
}) : {
|
|
1833
|
+
patches: inputPatches,
|
|
1834
|
+
inversePatches: inputInversePatches
|
|
1835
|
+
};
|
|
1836
|
+
const safePatches = sanitizeCheckedPatches(finalPatches.patches, "store.patch()");
|
|
1837
|
+
const safeInversePatches = sanitizeCheckedPatches(finalPatches.inversePatches, "store.patch() inverse patches");
|
|
1838
|
+
if (safePatches.length) {
|
|
1839
|
+
internal.applyValidatedPatches?.(internal.rootState, safePatches, false);
|
|
1840
|
+
if (!internal.applyValidatedPatches) store.apply(internal.rootState, safePatches);
|
|
1841
|
+
}
|
|
1842
|
+
return [
|
|
1843
|
+
internal.rootState,
|
|
1844
|
+
safePatches,
|
|
1845
|
+
safeInversePatches
|
|
1846
|
+
];
|
|
1847
|
+
});
|
|
1848
|
+
return internal.rootState;
|
|
1849
|
+
} finally {
|
|
1850
|
+
pendingCommitSource = previousSource;
|
|
1851
|
+
}
|
|
1852
|
+
};
|
|
1247
1853
|
const getState = (deps, selector) => deps && selector ? new Computed(deps, selector) : internal.module;
|
|
1248
1854
|
return {
|
|
1249
1855
|
setState,
|
|
1250
|
-
getState
|
|
1856
|
+
getState,
|
|
1857
|
+
replayPatches
|
|
1251
1858
|
};
|
|
1252
1859
|
};
|
|
1253
1860
|
//#endregion
|
|
1254
|
-
//#region packages/core/src/
|
|
1255
|
-
const
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
if (process.env.NODE_ENV === "development") {
|
|
1267
|
-
if (!isStoreLike(nextStore)) throw new Error(`middlewares[${index}] should return a store-like object`);
|
|
1268
|
-
}
|
|
1269
|
-
return nextStore;
|
|
1270
|
-
}, store);
|
|
1271
|
-
};
|
|
1272
|
-
//#endregion
|
|
1273
|
-
//#region packages/core/src/handleMainTransport.ts
|
|
1274
|
-
const getErrorMessage = (error) => {
|
|
1275
|
-
if (error instanceof Error) return error.message;
|
|
1276
|
-
return String(error);
|
|
1861
|
+
//#region packages/core/src/storeFactory.ts
|
|
1862
|
+
const namespaceMap = /* @__PURE__ */ new Map();
|
|
1863
|
+
let hasWarnedAmbiguousFunctionMap = false;
|
|
1864
|
+
const warnAmbiguousFunctionMap = () => {
|
|
1865
|
+
if (hasWarnedAmbiguousFunctionMap || process.env.NODE_ENV === "production" || process.env.NODE_ENV === "test") return;
|
|
1866
|
+
hasWarnedAmbiguousFunctionMap = true;
|
|
1867
|
+
console.warn([
|
|
1868
|
+
`sliceMode: 'auto' inferred slices from an object of functions.`,
|
|
1869
|
+
`This shape is ambiguous with a single store that only contains methods.`,
|
|
1870
|
+
`Use create({ ping() {} }, { sliceMode: 'single' }) for a plain method store,`,
|
|
1871
|
+
`or create({ counter: (set) => ({ count: 0 }) }, { sliceMode: 'slices' }) for slices.`
|
|
1872
|
+
].join(" "));
|
|
1277
1873
|
};
|
|
1278
|
-
const
|
|
1279
|
-
const
|
|
1280
|
-
const
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1874
|
+
const createStore = (createState, options, runtime = {}) => {
|
|
1875
|
+
const { share, validatePatches, validateReplacementSource, validateState } = runtime;
|
|
1876
|
+
const store = {};
|
|
1877
|
+
const internal = {
|
|
1878
|
+
sequence: 0,
|
|
1879
|
+
isBatching: false,
|
|
1880
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
1881
|
+
destroyCallbacks: /* @__PURE__ */ new Set(),
|
|
1882
|
+
validatePatches,
|
|
1883
|
+
validateReplacementSource,
|
|
1884
|
+
validateState
|
|
1885
|
+
};
|
|
1886
|
+
internal.notifyStateChange = () => {
|
|
1887
|
+
refreshSignalSlots(internal);
|
|
1888
|
+
internal.listeners.forEach((listener) => listener());
|
|
1889
|
+
};
|
|
1890
|
+
const name = options.name ?? "default";
|
|
1891
|
+
const shouldTrackName = share === "main" && process.env.NODE_ENV !== "test";
|
|
1892
|
+
const releaseStoreName = () => {
|
|
1893
|
+
if (shouldTrackName) namespaceMap.delete(name);
|
|
1894
|
+
};
|
|
1895
|
+
if (shouldTrackName) {
|
|
1896
|
+
if (namespaceMap.get(name)) throw new Error(`Store name '${name}' is not unique.`);
|
|
1897
|
+
namespaceMap.set(name, true);
|
|
1898
|
+
}
|
|
1899
|
+
try {
|
|
1900
|
+
const { setState, getState, replayPatches } = handleState(store, internal, options);
|
|
1901
|
+
const subscribe = (listener) => {
|
|
1902
|
+
internal.assertAlive?.("subscribe");
|
|
1903
|
+
internal.listeners.add(listener);
|
|
1904
|
+
return () => internal.listeners.delete(listener);
|
|
1905
|
+
};
|
|
1906
|
+
let isDestroyed = false;
|
|
1907
|
+
internal.assertAlive = (operation) => {
|
|
1908
|
+
if (isDestroyed) throw new Error(`${operation} cannot be called after store.destroy().`);
|
|
1909
|
+
};
|
|
1910
|
+
const destroy = () => {
|
|
1911
|
+
if (isDestroyed) return;
|
|
1912
|
+
isDestroyed = true;
|
|
1913
|
+
let firstError;
|
|
1914
|
+
const callbacks = [...internal.destroyCallbacks ?? []];
|
|
1915
|
+
internal.destroyCallbacks?.clear();
|
|
1916
|
+
for (const callback of callbacks) try {
|
|
1917
|
+
callback();
|
|
1918
|
+
} catch (error) {
|
|
1919
|
+
firstError ??= error;
|
|
1292
1920
|
}
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1921
|
+
internal.listeners.clear();
|
|
1922
|
+
disposeStoreCommitRuntime(store);
|
|
1923
|
+
try {
|
|
1924
|
+
store.transport?.dispose();
|
|
1925
|
+
} catch (error) {
|
|
1926
|
+
firstError ??= error;
|
|
1927
|
+
} finally {
|
|
1928
|
+
releaseStoreName();
|
|
1929
|
+
}
|
|
1930
|
+
if (firstError) throw firstError;
|
|
1931
|
+
};
|
|
1932
|
+
const applyState = (state, patches, prepared = false, skipFinalValidation = false) => {
|
|
1933
|
+
internal.assertAlive?.("apply");
|
|
1934
|
+
internal.assertMutationAllowed?.("apply");
|
|
1935
|
+
if (patches && !prepared) validatePatches?.(patches);
|
|
1936
|
+
if (!prepared) assertSafePatches(patches, "store.apply()");
|
|
1937
|
+
const safePatches = prepared ? patches : sanitizePatches(patches);
|
|
1938
|
+
const baseState = state === internal.module ? internal.rootState : state;
|
|
1939
|
+
if (baseState !== internal.rootState) validateReplacementSource?.(baseState);
|
|
1940
|
+
const appliedState = safePatches ? (0, mutative.apply)(baseState, safePatches) : baseState;
|
|
1941
|
+
const nextState = prepared ? appliedState : sanitizeReplacementState(appliedState);
|
|
1942
|
+
if (!skipFinalValidation) {
|
|
1943
|
+
assertKnownStateShape(nextState, internal.rootState, internal.stateSchema, store.isSliceStore, { requireSliceRoots: true });
|
|
1944
|
+
validateState?.(internal.getTransportState?.() ?? nextState);
|
|
1945
|
+
}
|
|
1946
|
+
internal.rootState = nextState;
|
|
1947
|
+
refreshSignalSlots(internal);
|
|
1948
|
+
if (internal.updateImmutable) internal.updateImmutable(internal.rootState);
|
|
1949
|
+
else internal.listeners.forEach((listener) => listener());
|
|
1950
|
+
};
|
|
1951
|
+
const apply = (state = internal.rootState, patches) => {
|
|
1952
|
+
const observeReplacement = patches === void 0 && hasStoreCommitListeners(store);
|
|
1953
|
+
const previousState = internal.rootState;
|
|
1954
|
+
applyState(state, patches);
|
|
1955
|
+
if (!observeReplacement) return;
|
|
1956
|
+
const replacement = createRootReplacementPatches(previousState, internal.rootState);
|
|
1957
|
+
const safePatches = sanitizeCheckedPatches(replacement.patches, "store.apply() replacement");
|
|
1958
|
+
const safeInversePatches = sanitizeCheckedPatches(replacement.inversePatches, "store.apply() replacement inverse patches");
|
|
1959
|
+
if (!safePatches.length && !safeInversePatches.length) return;
|
|
1960
|
+
internal.emitPatches?.(safePatches);
|
|
1961
|
+
publishStoreCommit(store, {
|
|
1962
|
+
state: internal.rootState,
|
|
1963
|
+
patches: safePatches,
|
|
1964
|
+
inversePatches: safeInversePatches,
|
|
1965
|
+
source: getStoreCommitSource(store, "external")
|
|
1966
|
+
});
|
|
1967
|
+
};
|
|
1968
|
+
internal.applyValidatedPatches = (state, patches, skipFinalValidation) => {
|
|
1969
|
+
if (store.apply !== apply) {
|
|
1970
|
+
store.apply(state, patches);
|
|
1971
|
+
return false;
|
|
1972
|
+
}
|
|
1973
|
+
applyState(state, patches, true, skipFinalValidation);
|
|
1974
|
+
return true;
|
|
1975
|
+
};
|
|
1976
|
+
const getPureState = () => internal.rootState;
|
|
1977
|
+
const isFunctionMapObject = () => {
|
|
1978
|
+
if (typeof createState !== "object" || createState === null) return false;
|
|
1979
|
+
const values = getOwnEnumerableKeys(createState).map((key) => createState[key]);
|
|
1980
|
+
return values.length > 0 && values.every((value) => typeof value === "function");
|
|
1981
|
+
};
|
|
1982
|
+
const getIsSliceStore = () => {
|
|
1983
|
+
const sliceMode = options.sliceMode ?? "auto";
|
|
1984
|
+
if (sliceMode === "single") return false;
|
|
1985
|
+
if (sliceMode === "slices") {
|
|
1986
|
+
if (!isFunctionMapObject()) throw new Error(`sliceMode: 'slices' requires createState to be an object of slice functions.`);
|
|
1987
|
+
return true;
|
|
1988
|
+
}
|
|
1989
|
+
if (isFunctionMapObject()) {
|
|
1990
|
+
warnAmbiguousFunctionMap();
|
|
1991
|
+
return true;
|
|
1992
|
+
}
|
|
1993
|
+
return false;
|
|
1994
|
+
};
|
|
1995
|
+
const isSliceStore = getIsSliceStore();
|
|
1996
|
+
Object.assign(store, {
|
|
1997
|
+
name,
|
|
1998
|
+
share: share ?? false,
|
|
1999
|
+
setState,
|
|
2000
|
+
getState,
|
|
2001
|
+
subscribe,
|
|
2002
|
+
destroy,
|
|
2003
|
+
apply,
|
|
2004
|
+
isSliceStore,
|
|
2005
|
+
getPureState
|
|
2006
|
+
});
|
|
2007
|
+
const middlewareStore = applyMiddlewares(store, options.middlewares ?? []);
|
|
2008
|
+
if (middlewareStore !== store) Object.assign(store, middlewareStore);
|
|
2009
|
+
registerStorePatchReplayer(store, replayPatches);
|
|
2010
|
+
internal.assertAlive?.("store initialization");
|
|
2011
|
+
if (validatePatches && store.patch) {
|
|
2012
|
+
const patch = store.patch.bind(store);
|
|
2013
|
+
store.patch = (options) => {
|
|
2014
|
+
const result = patch(options);
|
|
2015
|
+
validatePatches(result.patches);
|
|
2016
|
+
return result;
|
|
2017
|
+
};
|
|
1301
2018
|
}
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
2019
|
+
const initialState = getInitialState(store, createState, internal);
|
|
2020
|
+
internal.assertAlive?.("store initialization");
|
|
2021
|
+
internal.sharedActionPaths = runtime.collectActionPaths?.(initialState, store.isSliceStore);
|
|
2022
|
+
if (!internal.getTransportState) runtime.validateInitialState?.(initialState, store.isSliceStore);
|
|
2023
|
+
store.getInitialState = () => initialState;
|
|
2024
|
+
internal.rootState = getRawState(store, internal, initialState, options, runtime.clientAction);
|
|
2025
|
+
if (validatePatches && store.apply !== apply) {
|
|
2026
|
+
const applyWithAdapter = store.apply.bind(store);
|
|
2027
|
+
store.apply = (state, patches) => {
|
|
2028
|
+
internal.assertAlive?.("apply");
|
|
2029
|
+
internal.assertMutationAllowed?.("apply");
|
|
2030
|
+
if (typeof state !== "undefined" && state !== internal.rootState && state !== internal.module) validateReplacementSource?.(state);
|
|
2031
|
+
if (patches) {
|
|
2032
|
+
validatePatches(patches);
|
|
2033
|
+
assertSafePatches(patches, "store.apply()");
|
|
2034
|
+
}
|
|
2035
|
+
applyWithAdapter(state, patches);
|
|
2036
|
+
};
|
|
2037
|
+
}
|
|
2038
|
+
internal.stateSchema = createStateSchema(internal.rootState, store.isSliceStore);
|
|
2039
|
+
validateState?.(internal.getTransportState?.() ?? internal.rootState);
|
|
1305
2040
|
return {
|
|
1306
|
-
|
|
1307
|
-
|
|
2041
|
+
store,
|
|
2042
|
+
internal
|
|
1308
2043
|
};
|
|
1309
|
-
})
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
if (readyStores.has(store)) {
|
|
1318
|
-
callback();
|
|
1319
|
-
return () => void 0;
|
|
1320
|
-
}
|
|
1321
|
-
let callbacks = readyCallbacks.get(store);
|
|
1322
|
-
if (!callbacks) {
|
|
1323
|
-
callbacks = /* @__PURE__ */ new Set();
|
|
1324
|
-
readyCallbacks.set(store, callbacks);
|
|
2044
|
+
} catch (error) {
|
|
2045
|
+
try {
|
|
2046
|
+
store.destroy?.();
|
|
2047
|
+
} catch (destroyError) {
|
|
2048
|
+
if (process.env.NODE_ENV === "development") console.error(destroyError);
|
|
2049
|
+
}
|
|
2050
|
+
releaseStoreName();
|
|
2051
|
+
throw error;
|
|
1325
2052
|
}
|
|
1326
|
-
callbacks.add(callback);
|
|
1327
|
-
return () => {
|
|
1328
|
-
callbacks?.delete(callback);
|
|
1329
|
-
};
|
|
1330
|
-
};
|
|
1331
|
-
const markStoreReady = (store) => {
|
|
1332
|
-
readyStores.add(store);
|
|
1333
|
-
const callbacks = readyCallbacks.get(store);
|
|
1334
|
-
if (!callbacks) return;
|
|
1335
|
-
readyCallbacks.delete(store);
|
|
1336
|
-
callbacks.forEach((callback) => callback());
|
|
1337
|
-
callbacks.clear();
|
|
1338
2053
|
};
|
|
1339
2054
|
//#endregion
|
|
1340
2055
|
//#region packages/core/src/create.ts
|
|
1341
|
-
const namespaceMap = /* @__PURE__ */ new Map();
|
|
1342
|
-
let hasWarnedAmbiguousFunctionMap = false;
|
|
1343
2056
|
const isMainWorkerType = (workerType) => workerType === "SharedWorkerInternal" || workerType === "WebWorkerInternal";
|
|
1344
2057
|
const isClientWorkerType = (workerType) => workerType === "SharedWorkerClient" || workerType === "WebWorkerClient";
|
|
1345
2058
|
const validateCreateModeOptions = (options) => {
|
|
@@ -1353,430 +2066,55 @@ const validateCreateModeOptions = (options) => {
|
|
|
1353
2066
|
if (isMainWorkerType(explicitWorkerType) && (clientTransport || worker)) throw new Error("main workerType cannot be combined with client transport settings.");
|
|
1354
2067
|
if (isClientWorkerType(explicitWorkerType) && storeTransport) throw new Error("client workerType cannot be combined with transport.");
|
|
1355
2068
|
};
|
|
1356
|
-
const warnAmbiguousFunctionMap = () => {
|
|
1357
|
-
if (hasWarnedAmbiguousFunctionMap || process.env.NODE_ENV === "production" || process.env.NODE_ENV === "test") return;
|
|
1358
|
-
hasWarnedAmbiguousFunctionMap = true;
|
|
1359
|
-
console.warn([
|
|
1360
|
-
`sliceMode: 'auto' inferred slices from an object of functions.`,
|
|
1361
|
-
`This shape is ambiguous with a single store that only contains methods.`,
|
|
1362
|
-
`Use create({ ping() {} }, { sliceMode: 'single' }) for a plain method store,`,
|
|
1363
|
-
`or create({ counter: (set) => ({ count: 0 }) }, { sliceMode: 'slices' }) for slices.`
|
|
1364
|
-
].join(" "));
|
|
1365
|
-
};
|
|
1366
2069
|
/**
|
|
1367
2070
|
* Create a local store, the main side of a shared store, or a client mirror of
|
|
1368
2071
|
* a shared store.
|
|
1369
2072
|
*
|
|
1370
2073
|
* @remarks
|
|
1371
|
-
*
|
|
1372
|
-
*
|
|
1373
|
-
*
|
|
1374
|
-
* to avoid ambiguous inference.
|
|
1375
|
-
* - When `clientTransport` or `worker` is provided, returned store methods
|
|
1376
|
-
* become promise-returning methods because execution happens on the main
|
|
1377
|
-
* shared store.
|
|
1378
|
-
* - New semantics should prefer explicit helpers or variants over adding more
|
|
1379
|
-
* ambiguous `create()` input forms.
|
|
2074
|
+
* Prefer the static `coaction/local` entry when transport support is not
|
|
2075
|
+
* required. It excludes the JSON protocol and reconnect runtime from the
|
|
2076
|
+
* consumer dependency graph.
|
|
1380
2077
|
*/
|
|
1381
2078
|
const create = (createState, options = {}) => {
|
|
1382
2079
|
const checkEnablePatches = Object.hasOwnProperty.call(options, "enablePatches") && !options.enablePatches;
|
|
1383
2080
|
validateCreateModeOptions(options);
|
|
1384
2081
|
const workerType = options.workerType ?? WorkerType;
|
|
1385
2082
|
const storeTransport = options.transport;
|
|
1386
|
-
const share = workerType
|
|
1387
|
-
const
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
refreshSignalSlots(internal);
|
|
1396
|
-
internal.listeners.forEach((listener) => listener());
|
|
1397
|
-
};
|
|
1398
|
-
const name = options.name ?? "default";
|
|
1399
|
-
const shouldTrackName = share === "main" && process.env.NODE_ENV !== "test";
|
|
1400
|
-
const releaseStoreName = () => {
|
|
1401
|
-
if (shouldTrackName) namespaceMap.delete(name);
|
|
1402
|
-
};
|
|
1403
|
-
if (shouldTrackName) {
|
|
1404
|
-
if (namespaceMap.get(name)) throw new Error(`Store name '${name}' is not unique.`);
|
|
1405
|
-
namespaceMap.set(name, true);
|
|
1406
|
-
}
|
|
1407
|
-
try {
|
|
1408
|
-
const { setState, getState } = handleState(store, internal, options);
|
|
1409
|
-
const subscribe = (listener) => {
|
|
1410
|
-
internal.assertAlive?.("subscribe");
|
|
1411
|
-
internal.listeners.add(listener);
|
|
1412
|
-
return () => internal.listeners.delete(listener);
|
|
1413
|
-
};
|
|
1414
|
-
let isDestroyed = false;
|
|
1415
|
-
internal.assertAlive = (operation) => {
|
|
1416
|
-
if (isDestroyed) throw new Error(`${operation} cannot be called after store.destroy().`);
|
|
1417
|
-
};
|
|
1418
|
-
const destroy = () => {
|
|
1419
|
-
if (isDestroyed) return;
|
|
1420
|
-
isDestroyed = true;
|
|
1421
|
-
internal.listeners.clear();
|
|
1422
|
-
store.transport?.dispose();
|
|
1423
|
-
releaseStoreName();
|
|
1424
|
-
};
|
|
1425
|
-
const apply = (state = internal.rootState, patches) => {
|
|
1426
|
-
internal.assertAlive?.("apply");
|
|
1427
|
-
internal.assertMutationAllowed?.("apply");
|
|
1428
|
-
assertSafePatches(patches, "store.apply()");
|
|
1429
|
-
const safePatches = sanitizePatches(patches);
|
|
1430
|
-
const baseState = state === internal.module ? internal.rootState : state;
|
|
1431
|
-
const nextState = sanitizeReplacementState(safePatches ? (0, mutative.apply)(baseState, safePatches) : baseState);
|
|
1432
|
-
assertKnownStateShape(nextState, internal.rootState, internal.stateSchema, store.isSliceStore, { requireSliceRoots: true });
|
|
1433
|
-
if (store.share === "main") validateSharedStateSerializable(nextState);
|
|
1434
|
-
internal.rootState = nextState;
|
|
1435
|
-
refreshSignalSlots(internal);
|
|
1436
|
-
if (internal.updateImmutable) internal.updateImmutable(internal.rootState);
|
|
1437
|
-
else internal.listeners.forEach((listener) => listener());
|
|
1438
|
-
};
|
|
1439
|
-
const getPureState = () => internal.rootState;
|
|
1440
|
-
const isFunctionMapObject = () => {
|
|
1441
|
-
if (typeof createState === "object" && createState !== null) {
|
|
1442
|
-
const values = getOwnEnumerableKeys(createState).map((key) => createState[key]);
|
|
1443
|
-
return values.length > 0 && values.every((value) => typeof value === "function");
|
|
1444
|
-
}
|
|
1445
|
-
return false;
|
|
1446
|
-
};
|
|
1447
|
-
const getIsSliceStore = () => {
|
|
1448
|
-
const sliceMode = options.sliceMode ?? "auto";
|
|
1449
|
-
if (sliceMode === "single") return false;
|
|
1450
|
-
if (sliceMode === "slices") {
|
|
1451
|
-
if (!isFunctionMapObject()) throw new Error(`sliceMode: 'slices' requires createState to be an object of slice functions.`);
|
|
1452
|
-
return true;
|
|
1453
|
-
}
|
|
1454
|
-
if (isFunctionMapObject()) {
|
|
1455
|
-
warnAmbiguousFunctionMap();
|
|
1456
|
-
return true;
|
|
1457
|
-
}
|
|
1458
|
-
return false;
|
|
1459
|
-
};
|
|
1460
|
-
const isSliceStore = getIsSliceStore();
|
|
1461
|
-
Object.assign(store, {
|
|
1462
|
-
name,
|
|
1463
|
-
share: share ?? false,
|
|
1464
|
-
setState,
|
|
1465
|
-
getState,
|
|
1466
|
-
subscribe,
|
|
1467
|
-
destroy,
|
|
1468
|
-
apply,
|
|
1469
|
-
isSliceStore,
|
|
1470
|
-
getPureState
|
|
1471
|
-
});
|
|
1472
|
-
const middlewareStore = applyMiddlewares(store, options.middlewares ?? []);
|
|
1473
|
-
if (middlewareStore !== store) Object.assign(store, middlewareStore);
|
|
1474
|
-
const initialState = getInitialState(store, createState, internal);
|
|
1475
|
-
if (share) validateSharedActionPaths(initialState);
|
|
1476
|
-
store.getInitialState = () => initialState;
|
|
1477
|
-
internal.rootState = getRawState(store, internal, initialState, options);
|
|
1478
|
-
internal.stateSchema = createStateSchema(internal.rootState, store.isSliceStore);
|
|
1479
|
-
if (share) validateSharedStateSerializable(internal.rootState);
|
|
1480
|
-
markStoreReady(store);
|
|
1481
|
-
return {
|
|
1482
|
-
store,
|
|
1483
|
-
internal
|
|
1484
|
-
};
|
|
1485
|
-
} catch (error) {
|
|
1486
|
-
releaseStoreName();
|
|
1487
|
-
throw error;
|
|
1488
|
-
}
|
|
1489
|
-
};
|
|
1490
|
-
if (options.clientTransport || options.worker || options.workerType === "WebWorkerClient" || options.workerType === "SharedWorkerClient") {
|
|
1491
|
-
if (checkEnablePatches) throw new Error(`enablePatches: true is required for the async store`);
|
|
1492
|
-
return wrapStore(createAsyncClientStore(createStore, options));
|
|
1493
|
-
}
|
|
1494
|
-
const { store, internal } = createStore({ share });
|
|
1495
|
-
handleMainTransport(store, internal, storeTransport, workerType, checkEnablePatches);
|
|
1496
|
-
return wrapStore(store);
|
|
1497
|
-
};
|
|
1498
|
-
//#endregion
|
|
1499
|
-
//#region packages/core/src/binder.ts
|
|
1500
|
-
const createExternalStoreAdapter = ({ handleState, handleStore }) => ((state) => {
|
|
1501
|
-
const { copyState, key, bind } = handleState(state);
|
|
1502
|
-
const value = typeof key !== "undefined" ? copyState[key] : copyState;
|
|
1503
|
-
Object.defineProperty(value, bindSymbol, {
|
|
1504
|
-
configurable: true,
|
|
1505
|
-
enumerable: typeof key !== "undefined",
|
|
1506
|
-
value: {
|
|
1507
|
-
handleStore,
|
|
1508
|
-
bind
|
|
1509
|
-
}
|
|
1510
|
-
});
|
|
1511
|
-
return copyState;
|
|
1512
|
-
});
|
|
1513
|
-
/**
|
|
1514
|
-
* Build an adapter helper for bridging an external store implementation into
|
|
1515
|
-
* Coaction.
|
|
1516
|
-
*
|
|
1517
|
-
* @remarks
|
|
1518
|
-
* Official bindings use this to integrate stores such as Redux, Jotai, Pinia,
|
|
1519
|
-
* Zustand, MobX, and Valtio. Binder-backed integrations are whole-store
|
|
1520
|
-
* adapters; they are not compatible with Coaction slices mode.
|
|
1521
|
-
*/
|
|
1522
|
-
function createBinder({ handleState, handleStore }) {
|
|
1523
|
-
return createExternalStoreAdapter({
|
|
1524
|
-
handleState,
|
|
1525
|
-
handleStore
|
|
2083
|
+
const share = isMainWorkerType(workerType) || storeTransport ? "main" : void 0;
|
|
2084
|
+
const buildStore = ({ share }) => createStore(createState, options, {
|
|
2085
|
+
share,
|
|
2086
|
+
clientAction: share === "client" ? createClientAction : void 0,
|
|
2087
|
+
collectActionPaths: share === "main" ? validateSharedActionPaths : void 0,
|
|
2088
|
+
validateInitialState: share ? validateSharedInitialState : void 0,
|
|
2089
|
+
validatePatches: share === "main" ? validateUpdatePatches : void 0,
|
|
2090
|
+
validateReplacementSource: share ? validateSharedReplacementSource : void 0,
|
|
2091
|
+
validateState: share ? validateSharedStateSerializable : void 0
|
|
1526
2092
|
});
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
* Coaction.
|
|
1531
|
-
*
|
|
1532
|
-
* @remarks
|
|
1533
|
-
* This is the stable 2.x name for adapter authors. `createBinder()` remains as
|
|
1534
|
-
* a compatibility alias for existing official and community integrations.
|
|
1535
|
-
*/
|
|
1536
|
-
function defineExternalStoreAdapter(options) {
|
|
1537
|
-
return createExternalStoreAdapter(options);
|
|
1538
|
-
}
|
|
1539
|
-
//#endregion
|
|
1540
|
-
//#region packages/core/src/reactiveTracker.ts
|
|
1541
|
-
const ReactiveFlags = alien_signals_system.ReactiveFlags;
|
|
1542
|
-
const unwatch = (node) => {
|
|
1543
|
-
if (!(node.flags & ReactiveFlags.Mutable)) {
|
|
1544
|
-
node.depsTail = void 0;
|
|
1545
|
-
node.flags = 0;
|
|
1546
|
-
purgeDeps(node);
|
|
1547
|
-
const sub = node.subs;
|
|
1548
|
-
if (sub !== void 0) unlink(sub);
|
|
1549
|
-
return;
|
|
1550
|
-
}
|
|
1551
|
-
if (node.depsTail !== void 0) {
|
|
1552
|
-
node.depsTail = void 0;
|
|
1553
|
-
node.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty;
|
|
1554
|
-
purgeDeps(node);
|
|
2093
|
+
if (options.clientTransport || options.worker || isClientWorkerType(options.workerType)) {
|
|
2094
|
+
if (checkEnablePatches) throw new Error("enablePatches: true is required for the async store");
|
|
2095
|
+
return wrapStore(createAsyncClientStore(buildStore, options));
|
|
1555
2096
|
}
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
const dep = link.dep;
|
|
1559
|
-
const prevDep = link.prevDep;
|
|
1560
|
-
const nextDep = link.nextDep;
|
|
1561
|
-
const nextSub = link.nextSub;
|
|
1562
|
-
const prevSub = link.prevSub;
|
|
1563
|
-
if (nextDep !== void 0) nextDep.prevDep = prevDep;
|
|
1564
|
-
else sub.depsTail = prevDep;
|
|
1565
|
-
if (prevDep !== void 0) prevDep.nextDep = nextDep;
|
|
1566
|
-
else sub.deps = nextDep;
|
|
1567
|
-
if (nextSub !== void 0) nextSub.prevSub = prevSub;
|
|
1568
|
-
else dep.subsTail = prevSub;
|
|
1569
|
-
if (prevSub !== void 0) prevSub.nextSub = nextSub;
|
|
1570
|
-
else if ((dep.subs = nextSub) === void 0) unwatch(dep);
|
|
1571
|
-
return nextDep;
|
|
1572
|
-
};
|
|
1573
|
-
const purgeDeps = (sub) => {
|
|
1574
|
-
const depsTail = sub.depsTail;
|
|
1575
|
-
let dep = depsTail !== void 0 ? depsTail.nextDep : sub.deps;
|
|
1576
|
-
while (dep !== void 0) dep = unlink(dep, sub);
|
|
1577
|
-
};
|
|
1578
|
-
const createReactiveTracker = () => {
|
|
1579
|
-
let version = 0;
|
|
1580
|
-
let disposed = false;
|
|
1581
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
1582
|
-
const node = {
|
|
1583
|
-
deps: void 0,
|
|
1584
|
-
depsTail: void 0,
|
|
1585
|
-
subs: void 0,
|
|
1586
|
-
subsTail: void 0,
|
|
1587
|
-
flags: ReactiveFlags.Watching,
|
|
1588
|
-
fn: () => {
|
|
1589
|
-
if (disposed) return;
|
|
1590
|
-
version += 1;
|
|
1591
|
-
listeners.forEach((listener) => listener());
|
|
1592
|
-
}
|
|
1593
|
-
};
|
|
1594
|
-
const dispose = () => {
|
|
1595
|
-
if (disposed) return;
|
|
1596
|
-
disposed = true;
|
|
1597
|
-
listeners.clear();
|
|
1598
|
-
node.depsTail = void 0;
|
|
1599
|
-
purgeDeps(node);
|
|
1600
|
-
node.flags = 0;
|
|
1601
|
-
};
|
|
1602
|
-
return {
|
|
1603
|
-
getSnapshot: () => version,
|
|
1604
|
-
subscribe(listener) {
|
|
1605
|
-
if (disposed) return () => void 0;
|
|
1606
|
-
listeners.add(listener);
|
|
1607
|
-
return () => {
|
|
1608
|
-
listeners.delete(listener);
|
|
1609
|
-
};
|
|
1610
|
-
},
|
|
1611
|
-
track(fn) {
|
|
1612
|
-
if (disposed) return fn();
|
|
1613
|
-
node.depsTail = void 0;
|
|
1614
|
-
node.flags = ReactiveFlags.Watching | ReactiveFlags.RecursedCheck;
|
|
1615
|
-
const prevSub = (0, alien_signals.setActiveSub)(node);
|
|
1616
|
-
try {
|
|
1617
|
-
return fn();
|
|
1618
|
-
} finally {
|
|
1619
|
-
(0, alien_signals.setActiveSub)(prevSub);
|
|
1620
|
-
node.flags &= ~ReactiveFlags.RecursedCheck;
|
|
1621
|
-
purgeDeps(node);
|
|
1622
|
-
}
|
|
1623
|
-
},
|
|
1624
|
-
dispose
|
|
1625
|
-
};
|
|
1626
|
-
};
|
|
1627
|
-
//#endregion
|
|
1628
|
-
//#region packages/core/src/replaceExternalStoreState.ts
|
|
1629
|
-
const replaceExternalStoreState = (store, internal, source, { syncImmutable = true } = {}) => {
|
|
1630
|
-
const [, patches, inversePatches] = (0, mutative.create)(internal.rootState, (draft) => {
|
|
1631
|
-
replaceOwnEnumerable(draft, source);
|
|
1632
|
-
}, { enablePatches: true });
|
|
1633
|
-
const safePatches = sanitizeCheckedPatches((store.patch ? store.patch({
|
|
1634
|
-
patches,
|
|
1635
|
-
inversePatches
|
|
1636
|
-
}) : {
|
|
1637
|
-
patches,
|
|
1638
|
-
inversePatches
|
|
1639
|
-
}).patches, "store.patch()");
|
|
1640
|
-
if (!safePatches.length) return;
|
|
1641
|
-
const updateImmutable = internal.updateImmutable;
|
|
1642
|
-
if (!syncImmutable) internal.updateImmutable = void 0;
|
|
2097
|
+
if (share === "main" && checkEnablePatches) throw new Error("enablePatches: true is required for the transport");
|
|
2098
|
+
let builtStore;
|
|
1643
2099
|
try {
|
|
1644
|
-
|
|
1645
|
-
}
|
|
1646
|
-
|
|
1647
|
-
}
|
|
1648
|
-
emit(store, internal, safePatches);
|
|
1649
|
-
};
|
|
1650
|
-
//#endregion
|
|
1651
|
-
//#region packages/core/src/externalMutableAdapterUtils.ts
|
|
1652
|
-
const getMutableAdapterOwnEnumerableKeys = (value) => Reflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key));
|
|
1653
|
-
const isMutableAdapterUnsafeKey = (key) => typeof key === "string" && isUnsafeKey(key);
|
|
1654
|
-
const isArrayIndexKey = (key) => {
|
|
1655
|
-
if (typeof key !== "string") return false;
|
|
1656
|
-
const index = Number(key);
|
|
1657
|
-
return Number.isInteger(index) && index >= 0 && index < 2 ** 32 - 1 && String(index) === key;
|
|
1658
|
-
};
|
|
1659
|
-
const isObjectRecord = (value) => Object.prototype.toString.call(value) === "[object Object]";
|
|
1660
|
-
const assertCanSetMutableAdapterPublicStateKey = (publicState, key) => {
|
|
1661
|
-
if (Object.prototype.hasOwnProperty.call(publicState, key)) return;
|
|
1662
|
-
if (Object.isExtensible(publicState)) return;
|
|
1663
|
-
throw new StateSchemaError(`Unknown state key '${String(key)}' cannot be added after store initialization. Coaction state schema is fixed.`);
|
|
1664
|
-
};
|
|
1665
|
-
const ensureMutableAdapterRawDescriptor = (rawState, mutableState, publicState, key) => {
|
|
1666
|
-
if (rawState === mutableState) return;
|
|
1667
|
-
const rawDescriptor = Object.getOwnPropertyDescriptor(rawState, key);
|
|
1668
|
-
if (rawDescriptor?.get && rawDescriptor.set) return;
|
|
1669
|
-
const publicDescriptor = Object.getOwnPropertyDescriptor(publicState, key);
|
|
1670
|
-
if (!publicDescriptor || rawDescriptor?.configurable === false) return;
|
|
1671
|
-
Object.defineProperty(rawState, key, {
|
|
1672
|
-
get: () => mutableState[key],
|
|
1673
|
-
set: (value) => {
|
|
1674
|
-
mutableState[key] = value;
|
|
1675
|
-
},
|
|
1676
|
-
configurable: true,
|
|
1677
|
-
enumerable: publicDescriptor.enumerable
|
|
1678
|
-
});
|
|
1679
|
-
};
|
|
1680
|
-
const replaceMutableAdapterState = (rawState, mutableState, publicState, source) => {
|
|
1681
|
-
const nextKeys = /* @__PURE__ */ new Set();
|
|
1682
|
-
for (const key of getMutableAdapterOwnEnumerableKeys(source)) {
|
|
1683
|
-
if (isMutableAdapterUnsafeKey(key)) continue;
|
|
1684
|
-
if (typeof source[key] === "function") continue;
|
|
1685
|
-
nextKeys.add(key);
|
|
2100
|
+
builtStore = buildStore({ share });
|
|
2101
|
+
} catch (error) {
|
|
2102
|
+
return failTransportInitialization(storeTransport, error);
|
|
1686
2103
|
}
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
continue;
|
|
1695
|
-
}
|
|
1696
|
-
if (typeof rawState[key] === "function") continue;
|
|
1697
|
-
if (!nextKeys.has(key)) {
|
|
1698
|
-
delete rawState[key];
|
|
1699
|
-
delete mutableState[key];
|
|
1700
|
-
}
|
|
1701
|
-
}
|
|
1702
|
-
const rawSeen = /* @__PURE__ */ new WeakMap();
|
|
1703
|
-
const mutableSeen = /* @__PURE__ */ new WeakMap();
|
|
1704
|
-
const publicSeen = /* @__PURE__ */ new WeakMap();
|
|
1705
|
-
rawSeen.set(source, rawState);
|
|
1706
|
-
mutableSeen.set(source, mutableState);
|
|
1707
|
-
publicSeen.set(source, publicState);
|
|
1708
|
-
nextKeys.forEach((key) => {
|
|
1709
|
-
ensureMutableAdapterRawDescriptor(rawState, mutableState, publicState, key);
|
|
1710
|
-
rawState[key] = sanitizeReplacementState(source[key], rawSeen);
|
|
1711
|
-
mutableState[key] = sanitizeReplacementState(source[key], mutableSeen);
|
|
1712
|
-
publicState[key] = sanitizeReplacementState(source[key], publicSeen);
|
|
1713
|
-
});
|
|
1714
|
-
};
|
|
1715
|
-
const applyMutableAdapterPatches = (baseState, patches, rawState, mutableState, publicState) => {
|
|
1716
|
-
assertSafePatches(patches, "mutable adapter apply()");
|
|
1717
|
-
replaceMutableAdapterState(rawState, mutableState, publicState, (0, mutative.apply)(toMutableAdapterSnapshot(baseState === publicState ? rawState : baseState), patches));
|
|
1718
|
-
};
|
|
1719
|
-
const toMutableAdapterSnapshot = (value, visited = /* @__PURE__ */ new WeakMap()) => {
|
|
1720
|
-
if (Array.isArray(value)) {
|
|
1721
|
-
if (visited.has(value)) return visited.get(value);
|
|
1722
|
-
const next = [];
|
|
1723
|
-
next.length = value.length;
|
|
1724
|
-
visited.set(value, next);
|
|
1725
|
-
for (let index = 0; index < value.length; index += 1) if (Object.prototype.hasOwnProperty.call(value, index)) next[index] = toMutableAdapterSnapshot(value[index], visited);
|
|
1726
|
-
const source = value;
|
|
1727
|
-
const target = next;
|
|
1728
|
-
for (const key of getMutableAdapterOwnEnumerableKeys(value)) {
|
|
1729
|
-
if (isArrayIndexKey(key) || isMutableAdapterUnsafeKey(key)) continue;
|
|
1730
|
-
const child = source[key];
|
|
1731
|
-
if (typeof child !== "function") target[key] = toMutableAdapterSnapshot(child, visited);
|
|
1732
|
-
}
|
|
1733
|
-
return next;
|
|
1734
|
-
}
|
|
1735
|
-
if (typeof value === "object" && value !== null) {
|
|
1736
|
-
if (!isObjectRecord(value)) return value;
|
|
1737
|
-
if (visited.has(value)) return visited.get(value);
|
|
1738
|
-
const next = {};
|
|
1739
|
-
visited.set(value, next);
|
|
1740
|
-
for (const key of getMutableAdapterOwnEnumerableKeys(value)) {
|
|
1741
|
-
if (isMutableAdapterUnsafeKey(key)) continue;
|
|
1742
|
-
const child = value[key];
|
|
1743
|
-
if (typeof child !== "function") next[key] = toMutableAdapterSnapshot(child, visited);
|
|
1744
|
-
}
|
|
1745
|
-
return next;
|
|
1746
|
-
}
|
|
1747
|
-
return value;
|
|
1748
|
-
};
|
|
1749
|
-
const snapshotMutableAdapterPureState = (store) => toMutableAdapterSnapshot(store.getPureState());
|
|
1750
|
-
const isEqualMutableAdapterSnapshot = (left, right, visited = /* @__PURE__ */ new WeakMap()) => {
|
|
1751
|
-
if (Object.is(left, right)) return true;
|
|
1752
|
-
if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) return false;
|
|
1753
|
-
const leftIsArray = Array.isArray(left);
|
|
1754
|
-
const rightIsArray = Array.isArray(right);
|
|
1755
|
-
if (leftIsArray || rightIsArray) {
|
|
1756
|
-
if (!leftIsArray || !rightIsArray || left.length !== right.length) return false;
|
|
1757
|
-
} else if (!isObjectRecord(left) || !isObjectRecord(right)) return false;
|
|
1758
|
-
let seenTargets = visited.get(left);
|
|
1759
|
-
if (!seenTargets) {
|
|
1760
|
-
seenTargets = /* @__PURE__ */ new WeakSet();
|
|
1761
|
-
visited.set(left, seenTargets);
|
|
1762
|
-
} else if (seenTargets.has(right)) return true;
|
|
1763
|
-
seenTargets.add(right);
|
|
1764
|
-
const leftRecord = left;
|
|
1765
|
-
const rightRecord = right;
|
|
1766
|
-
const leftKeys = getMutableAdapterOwnEnumerableKeys(left);
|
|
1767
|
-
const rightKeys = getMutableAdapterOwnEnumerableKeys(right);
|
|
1768
|
-
if (leftKeys.length !== rightKeys.length) return false;
|
|
1769
|
-
for (const key of leftKeys) {
|
|
1770
|
-
if (!Object.prototype.hasOwnProperty.call(rightRecord, key)) return false;
|
|
1771
|
-
if (!isEqualMutableAdapterSnapshot(leftRecord[key], rightRecord[key], visited)) return false;
|
|
2104
|
+
const { store, internal } = builtStore;
|
|
2105
|
+
try {
|
|
2106
|
+
handleMainTransport(store, internal, storeTransport, workerType, checkEnablePatches, options.transportPolicy);
|
|
2107
|
+
markStoreReady(store);
|
|
2108
|
+
internal.assertAlive?.("store initialization");
|
|
2109
|
+
} catch (error) {
|
|
2110
|
+
return failStoreSetup(store, error);
|
|
1772
2111
|
}
|
|
1773
|
-
return
|
|
2112
|
+
return wrapStore(store);
|
|
1774
2113
|
};
|
|
1775
2114
|
//#endregion
|
|
2115
|
+
exports.ActionAuthorityChangedError = ActionAuthorityChangedError;
|
|
1776
2116
|
exports.StateSchemaError = StateSchemaError;
|
|
1777
2117
|
exports.UnsafePatchPathError = UnsafePatchPathError;
|
|
1778
|
-
exports.applyMutableAdapterPatches = applyMutableAdapterPatches;
|
|
1779
|
-
exports.applyRootReplacementWithPatches = applyRootReplacementWithPatches;
|
|
1780
2118
|
exports.assertSafePatches = assertSafePatches;
|
|
1781
2119
|
Object.defineProperty(exports, "computed", {
|
|
1782
2120
|
enumerable: true,
|
|
@@ -1785,10 +2123,6 @@ Object.defineProperty(exports, "computed", {
|
|
|
1785
2123
|
}
|
|
1786
2124
|
});
|
|
1787
2125
|
exports.create = create;
|
|
1788
|
-
exports.createBinder = createBinder;
|
|
1789
|
-
exports.createReactiveTracker = createReactiveTracker;
|
|
1790
|
-
exports.createRootReplacementPatches = createRootReplacementPatches;
|
|
1791
|
-
exports.defineExternalStoreAdapter = defineExternalStoreAdapter;
|
|
1792
2126
|
Object.defineProperty(exports, "effect", {
|
|
1793
2127
|
enumerable: true,
|
|
1794
2128
|
get: function() {
|
|
@@ -1807,7 +2141,6 @@ Object.defineProperty(exports, "endBatch", {
|
|
|
1807
2141
|
return alien_signals.endBatch;
|
|
1808
2142
|
}
|
|
1809
2143
|
});
|
|
1810
|
-
exports.getMutableAdapterOwnEnumerableKeys = getMutableAdapterOwnEnumerableKeys;
|
|
1811
2144
|
Object.defineProperty(exports, "isComputed", {
|
|
1812
2145
|
enumerable: true,
|
|
1813
2146
|
get: function() {
|
|
@@ -1826,8 +2159,6 @@ Object.defineProperty(exports, "isEffectScope", {
|
|
|
1826
2159
|
return alien_signals.isEffectScope;
|
|
1827
2160
|
}
|
|
1828
2161
|
});
|
|
1829
|
-
exports.isEqualMutableAdapterSnapshot = isEqualMutableAdapterSnapshot;
|
|
1830
|
-
exports.isMutableAdapterUnsafeKey = isMutableAdapterUnsafeKey;
|
|
1831
2162
|
Object.defineProperty(exports, "isSignal", {
|
|
1832
2163
|
enumerable: true,
|
|
1833
2164
|
get: function() {
|
|
@@ -1836,9 +2167,6 @@ Object.defineProperty(exports, "isSignal", {
|
|
|
1836
2167
|
});
|
|
1837
2168
|
exports.isStateSchemaError = isStateSchemaError;
|
|
1838
2169
|
exports.onStoreReady = onStoreReady;
|
|
1839
|
-
exports.replaceExternalStoreState = replaceExternalStoreState;
|
|
1840
|
-
exports.replaceMutableAdapterState = replaceMutableAdapterState;
|
|
1841
|
-
exports.replaceOwnEnumerable = replaceOwnEnumerable;
|
|
1842
2170
|
exports.sanitizeInitialStateValue = sanitizeInitialStateValue;
|
|
1843
2171
|
exports.sanitizePatches = sanitizePatches;
|
|
1844
2172
|
exports.sanitizeReplacementState = sanitizeReplacementState;
|
|
@@ -1848,18 +2176,15 @@ Object.defineProperty(exports, "signal", {
|
|
|
1848
2176
|
return alien_signals.signal;
|
|
1849
2177
|
}
|
|
1850
2178
|
});
|
|
1851
|
-
exports.snapshotMutableAdapterPureState = snapshotMutableAdapterPureState;
|
|
1852
2179
|
Object.defineProperty(exports, "startBatch", {
|
|
1853
2180
|
enumerable: true,
|
|
1854
2181
|
get: function() {
|
|
1855
2182
|
return alien_signals.startBatch;
|
|
1856
2183
|
}
|
|
1857
2184
|
});
|
|
1858
|
-
exports.toMutableAdapterSnapshot = toMutableAdapterSnapshot;
|
|
1859
2185
|
Object.defineProperty(exports, "trigger", {
|
|
1860
2186
|
enumerable: true,
|
|
1861
2187
|
get: function() {
|
|
1862
2188
|
return alien_signals.trigger;
|
|
1863
2189
|
}
|
|
1864
2190
|
});
|
|
1865
|
-
exports.wrapStore = wrapStore;
|