@oxog/state 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2,6 +2,27 @@
2
2
 
3
3
  var react = require('react');
4
4
 
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(to, key) && key !== except)
20
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ }
22
+ return to;
23
+ };
24
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
25
+
5
26
  // src/utils/deep-clone.ts
6
27
  function deepClone(value, seen) {
7
28
  if (value === null || typeof value !== "object") {
@@ -37,6 +58,10 @@ function deepClone(value, seen) {
37
58
  }
38
59
  return value;
39
60
  }
61
+ var init_deep_clone = __esm({
62
+ "src/utils/deep-clone.ts"() {
63
+ }
64
+ });
40
65
 
41
66
  // src/utils/deep-equal.ts
42
67
  function deepEqual(a, b) {
@@ -73,6 +98,10 @@ function deepEqual(a, b) {
73
98
  }
74
99
  return true;
75
100
  }
101
+ var init_deep_equal = __esm({
102
+ "src/utils/deep-equal.ts"() {
103
+ }
104
+ });
76
105
 
77
106
  // src/utils/shallow-equal.ts
78
107
  function shallowEqual(a, b) {
@@ -94,6 +123,10 @@ function shallowEqual(a, b) {
94
123
  }
95
124
  return true;
96
125
  }
126
+ var init_shallow_equal = __esm({
127
+ "src/utils/shallow-equal.ts"() {
128
+ }
129
+ });
97
130
 
98
131
  // src/utils/deep-merge.ts
99
132
  function deepMerge(target, source) {
@@ -142,11 +175,20 @@ function cloneValue(value) {
142
175
  }
143
176
  return value;
144
177
  }
178
+ var init_deep_merge = __esm({
179
+ "src/utils/deep-merge.ts"() {
180
+ init_deep_clone();
181
+ }
182
+ });
145
183
 
146
184
  // src/utils/is-function.ts
147
185
  function isFunction(value) {
148
186
  return typeof value === "function";
149
187
  }
188
+ var init_is_function = __esm({
189
+ "src/utils/is-function.ts"() {
190
+ }
191
+ });
150
192
 
151
193
  // src/utils/pick.ts
152
194
  function pick(obj, keys) {
@@ -158,6 +200,10 @@ function pick(obj, keys) {
158
200
  }
159
201
  return result;
160
202
  }
203
+ var init_pick = __esm({
204
+ "src/utils/pick.ts"() {
205
+ }
206
+ });
161
207
 
162
208
  // src/utils/omit.ts
163
209
  function omit(obj, keys) {
@@ -167,227 +213,251 @@ function omit(obj, keys) {
167
213
  }
168
214
  return result;
169
215
  }
216
+ var init_omit = __esm({
217
+ "src/utils/omit.ts"() {
218
+ }
219
+ });
170
220
 
171
221
  // src/utils/identity.ts
172
222
  function identity(value) {
173
223
  return value;
174
224
  }
225
+ var init_identity = __esm({
226
+ "src/utils/identity.ts"() {
227
+ }
228
+ });
229
+
230
+ // src/utils/index.ts
231
+ var init_utils = __esm({
232
+ "src/utils/index.ts"() {
233
+ init_deep_clone();
234
+ init_deep_equal();
235
+ init_shallow_equal();
236
+ init_deep_merge();
237
+ init_is_function();
238
+ init_pick();
239
+ init_omit();
240
+ init_identity();
241
+ }
242
+ });
175
243
 
176
244
  // src/kernel.ts
177
- var EventBus = class {
178
- listeners = /* @__PURE__ */ new Map();
179
- /**
180
- * Subscribe to an event.
181
- *
182
- * @param event - Event name
183
- * @param handler - Event handler
184
- * @returns Unsubscribe function
185
- */
186
- on(event, handler) {
187
- if (!this.listeners.has(event)) {
188
- this.listeners.set(event, /* @__PURE__ */ new Set());
189
- }
190
- this.listeners.get(event).add(handler);
191
- return () => {
192
- this.listeners.get(event)?.delete(handler);
193
- };
194
- }
195
- /**
196
- * Emit an event to all subscribers.
197
- *
198
- * @param event - Event name
199
- * @param data - Event data
200
- */
201
- emit(event, data) {
202
- const handlers = this.listeners.get(event);
203
- if (handlers) {
204
- for (const handler of handlers) {
205
- try {
206
- handler(data);
207
- } catch (error) {
208
- console.error(`Error in ${event} handler:`, error);
245
+ function createKernel(config) {
246
+ return new Kernel(config);
247
+ }
248
+ var EventBus, Kernel;
249
+ var init_kernel = __esm({
250
+ "src/kernel.ts"() {
251
+ EventBus = class {
252
+ listeners = /* @__PURE__ */ new Map();
253
+ /**
254
+ * Subscribe to an event.
255
+ *
256
+ * @param event - Event name
257
+ * @param handler - Event handler
258
+ * @returns Unsubscribe function
259
+ */
260
+ on(event, handler) {
261
+ if (!this.listeners.has(event)) {
262
+ this.listeners.set(event, /* @__PURE__ */ new Set());
209
263
  }
264
+ this.listeners.get(event).add(handler);
265
+ return () => {
266
+ this.listeners.get(event)?.delete(handler);
267
+ };
210
268
  }
211
- }
212
- }
213
- /** Clear all listeners. */
214
- destroy() {
215
- this.listeners.clear();
216
- }
217
- };
218
- var Kernel = class {
219
- plugins = /* @__PURE__ */ new Map();
220
- eventBus = new EventBus();
221
- config;
222
- errorHandlers = /* @__PURE__ */ new Set();
223
- initializing = false;
224
- constructor(config) {
225
- this.config = config || {};
226
- }
227
- /**
228
- * Register a plugin.
229
- *
230
- * @param plugin - The plugin to register
231
- * @param options - Plugin options
232
- * @param store - The store instance
233
- * @throws {Error} If plugin already registered or dependencies missing
234
- */
235
- register(plugin, options, store) {
236
- if (!plugin.name || !plugin.version || typeof plugin.install !== "function") {
237
- throw new Error("Invalid plugin: must have name, version, and install function");
238
- }
239
- if (this.plugins.has(plugin.name)) {
240
- throw new Error(`Plugin '${plugin.name}' is already registered`);
241
- }
242
- if (plugin.dependencies) {
243
- for (const dep of plugin.dependencies) {
244
- if (!this.plugins.has(dep)) {
245
- throw new Error(
246
- `Plugin '${plugin.name}' requires '${dep}' to be registered first`
247
- );
269
+ /**
270
+ * Emit an event to all subscribers.
271
+ *
272
+ * @param event - Event name
273
+ * @param data - Event data
274
+ */
275
+ emit(event, data) {
276
+ const handlers = this.listeners.get(event);
277
+ if (handlers) {
278
+ for (const handler of handlers) {
279
+ try {
280
+ handler(data);
281
+ } catch (error) {
282
+ console.error(`Error in ${event} handler:`, error);
283
+ }
284
+ }
248
285
  }
249
286
  }
250
- }
251
- const instance = {
252
- plugin,
253
- options
254
- };
255
- try {
256
- plugin.install(store, options);
257
- } catch (error) {
258
- throw new Error(`Failed to install plugin '${plugin.name}': ${error}`);
259
- }
260
- this.plugins.set(plugin.name, instance);
261
- if (!this.initializing && plugin.onInit) {
262
- this.runOnInit(plugin, store);
263
- }
264
- }
265
- /**
266
- * Initialize all plugins.
267
- *
268
- * @param store - The store instance
269
- */
270
- async initializeAll(store) {
271
- this.initializing = true;
272
- const plugins = Array.from(this.plugins.values());
273
- for (const { plugin } of plugins) {
274
- if (plugin.onInit) {
275
- await this.runOnInit(plugin, store);
287
+ /** Clear all listeners. */
288
+ destroy() {
289
+ this.listeners.clear();
276
290
  }
277
- }
278
- this.initializing = false;
279
- }
280
- /**
281
- * Run plugin's onInit safely.
282
- */
283
- async runOnInit(plugin, store) {
284
- try {
285
- await plugin.onInit(store);
286
- } catch (error) {
287
- console.error(`Error in ${plugin.name} onInit:`, error);
288
- }
289
- }
290
- /**
291
- * Unregister a plugin.
292
- *
293
- * @param name - Plugin name
294
- */
295
- async unregister(name) {
296
- const instance = this.plugins.get(name);
297
- if (!instance) {
298
- return;
299
- }
300
- if (instance.plugin.onDestroy) {
301
- try {
302
- await instance.plugin.onDestroy();
303
- } catch (error) {
304
- console.error(`Error in ${name} onDestroy:`, error);
291
+ };
292
+ Kernel = class {
293
+ plugins = /* @__PURE__ */ new Map();
294
+ eventBus = new EventBus();
295
+ config;
296
+ errorHandlers = /* @__PURE__ */ new Set();
297
+ initializing = false;
298
+ constructor(config) {
299
+ this.config = config || {};
305
300
  }
306
- }
307
- this.plugins.delete(name);
308
- }
309
- /**
310
- * Emit a state change event.
311
- *
312
- * @param state - New state
313
- * @param prevState - Previous state
314
- */
315
- emitStateChange(state, prevState) {
316
- this.eventBus.emit("stateChange", { state, prevState });
317
- for (const { plugin } of this.plugins.values()) {
318
- if (plugin.onStateChange) {
301
+ /**
302
+ * Register a plugin.
303
+ *
304
+ * @param plugin - The plugin to register
305
+ * @param options - Plugin options
306
+ * @param store - The store instance
307
+ * @throws {Error} If plugin already registered or dependencies missing
308
+ */
309
+ register(plugin, options, store) {
310
+ if (!plugin.name || !plugin.version || typeof plugin.install !== "function") {
311
+ throw new Error("Invalid plugin: must have name, version, and install function");
312
+ }
313
+ if (this.plugins.has(plugin.name)) {
314
+ throw new Error(`Plugin '${plugin.name}' is already registered`);
315
+ }
316
+ if (plugin.dependencies) {
317
+ for (const dep of plugin.dependencies) {
318
+ if (!this.plugins.has(dep)) {
319
+ throw new Error(
320
+ `Plugin '${plugin.name}' requires '${dep}' to be registered first`
321
+ );
322
+ }
323
+ }
324
+ }
325
+ const instance = {
326
+ plugin,
327
+ options
328
+ };
319
329
  try {
320
- plugin.onStateChange(state, prevState);
330
+ plugin.install(store, options);
321
331
  } catch (error) {
322
- console.error(`Error in ${plugin.name} onStateChange:`, error);
332
+ throw new Error(`Failed to install plugin '${plugin.name}': ${error}`);
333
+ }
334
+ this.plugins.set(plugin.name, instance);
335
+ if (!this.initializing && plugin.onInit) {
336
+ this.runOnInit(plugin, store);
323
337
  }
324
338
  }
325
- }
326
- }
327
- /**
328
- * Emit an error event.
329
- *
330
- * @param error - The error
331
- */
332
- emitError(error) {
333
- this.eventBus.emit("error", error);
334
- for (const { plugin } of this.plugins.values()) {
335
- if (plugin.onError) {
339
+ /**
340
+ * Initialize all plugins.
341
+ *
342
+ * @param store - The store instance
343
+ */
344
+ async initializeAll(store) {
345
+ this.initializing = true;
346
+ const plugins = Array.from(this.plugins.values());
347
+ for (const { plugin } of plugins) {
348
+ if (plugin.onInit) {
349
+ await this.runOnInit(plugin, store);
350
+ }
351
+ }
352
+ this.initializing = false;
353
+ }
354
+ /**
355
+ * Run plugin's onInit safely.
356
+ */
357
+ async runOnInit(plugin, store) {
336
358
  try {
337
- plugin.onError(error);
338
- } catch (err) {
339
- console.error(`Error in ${plugin.name} onError:`, err);
359
+ await plugin.onInit(store);
360
+ } catch (error) {
361
+ console.error(`Error in ${plugin.name} onInit:`, error);
340
362
  }
341
363
  }
342
- }
343
- for (const handler of this.errorHandlers) {
344
- try {
345
- handler(error);
346
- } catch (err) {
347
- console.error("Error in error handler:", err);
364
+ /**
365
+ * Unregister a plugin.
366
+ *
367
+ * @param name - Plugin name
368
+ */
369
+ async unregister(name) {
370
+ const instance = this.plugins.get(name);
371
+ if (!instance) {
372
+ return;
373
+ }
374
+ if (instance.plugin.onDestroy) {
375
+ try {
376
+ await instance.plugin.onDestroy();
377
+ } catch (error) {
378
+ console.error(`Error in ${name} onDestroy:`, error);
379
+ }
380
+ }
381
+ this.plugins.delete(name);
382
+ }
383
+ /**
384
+ * Emit a state change event.
385
+ *
386
+ * @param state - New state
387
+ * @param prevState - Previous state
388
+ */
389
+ emitStateChange(state, prevState) {
390
+ this.eventBus.emit("stateChange", { state, prevState });
391
+ for (const { plugin } of this.plugins.values()) {
392
+ if (plugin.onStateChange) {
393
+ try {
394
+ plugin.onStateChange(state, prevState);
395
+ } catch (error) {
396
+ console.error(`Error in ${plugin.name} onStateChange:`, error);
397
+ }
398
+ }
399
+ }
400
+ }
401
+ /**
402
+ * Emit an error event.
403
+ *
404
+ * @param error - The error
405
+ */
406
+ emitError(error) {
407
+ this.eventBus.emit("error", error);
408
+ for (const { plugin } of this.plugins.values()) {
409
+ if (plugin.onError) {
410
+ try {
411
+ plugin.onError(error);
412
+ } catch (err) {
413
+ console.error(`Error in ${plugin.name} onError:`, err);
414
+ }
415
+ }
416
+ }
417
+ for (const handler of this.errorHandlers) {
418
+ try {
419
+ handler(error);
420
+ } catch (err) {
421
+ console.error("Error in error handler:", err);
422
+ }
423
+ }
424
+ }
425
+ /**
426
+ * Add an error handler.
427
+ *
428
+ * @param handler - Error handler function
429
+ * @returns Unsubscribe function
430
+ */
431
+ onError(handler) {
432
+ this.errorHandlers.add(handler);
433
+ return () => {
434
+ this.errorHandlers.delete(handler);
435
+ };
436
+ }
437
+ /**
438
+ * Subscribe to an event.
439
+ *
440
+ * @param event - Event name
441
+ * @param handler - Event handler
442
+ * @returns Unsubscribe function
443
+ */
444
+ on(event, handler) {
445
+ return this.eventBus.on(event, handler);
446
+ }
447
+ /** Destroy the kernel and cleanup. */
448
+ async destroy() {
449
+ const pluginNames = Array.from(this.plugins.keys());
450
+ for (const name of pluginNames) {
451
+ await this.unregister(name);
452
+ }
453
+ this.eventBus.destroy();
454
+ this.errorHandlers.clear();
348
455
  }
349
- }
350
- }
351
- /**
352
- * Add an error handler.
353
- *
354
- * @param handler - Error handler function
355
- * @returns Unsubscribe function
356
- */
357
- onError(handler) {
358
- this.errorHandlers.add(handler);
359
- return () => {
360
- this.errorHandlers.delete(handler);
361
456
  };
362
457
  }
363
- /**
364
- * Subscribe to an event.
365
- *
366
- * @param event - Event name
367
- * @param handler - Event handler
368
- * @returns Unsubscribe function
369
- */
370
- on(event, handler) {
371
- return this.eventBus.on(event, handler);
372
- }
373
- /** Destroy the kernel and cleanup. */
374
- async destroy() {
375
- const pluginNames = Array.from(this.plugins.keys());
376
- for (const name of pluginNames) {
377
- await this.unregister(name);
378
- }
379
- this.eventBus.destroy();
380
- this.errorHandlers.clear();
381
- }
382
- };
383
- function createKernel(config) {
384
- return new Kernel(config);
385
- }
458
+ });
386
459
 
387
460
  // src/batch-context.ts
388
- var batchDepth = 0;
389
- var batchStores = /* @__PURE__ */ new Set();
390
- var batchManagedStores = /* @__PURE__ */ new Set();
391
461
  function isBatching() {
392
462
  return batchDepth > 0;
393
463
  }
@@ -416,320 +486,94 @@ function addManagedStore(store) {
416
486
  function isStoreManaged(store) {
417
487
  return batchManagedStores.has(store);
418
488
  }
419
- var sharedBatchContext = {
420
- get depth() {
421
- return batchDepth;
422
- },
423
- get stores() {
424
- return batchStores;
425
- },
426
- get managedStores() {
427
- return batchManagedStores;
428
- },
429
- isBatching,
430
- batch(store, fn) {
431
- const wasAlreadyBatching = isStoreManaged(store);
432
- incrementBatchDepth();
433
- addBatchStore(store);
434
- if (!wasAlreadyBatching && "beginBatch" in store) {
435
- store.beginBatch();
436
- addManagedStore(store);
437
- }
438
- try {
439
- const result = fn();
440
- decrementBatchDepth();
441
- if (getBatchDepth() === 0) {
442
- for (const s of getBatchManagedStores()) {
443
- if ("flushNotifications" in s) {
444
- s.flushNotifications();
445
- }
446
- if ("endBatch" in s) {
447
- s.endBatch();
448
- }
489
+ var batchDepth, batchStores, batchManagedStores, sharedBatchContext;
490
+ var init_batch_context = __esm({
491
+ "src/batch-context.ts"() {
492
+ batchDepth = 0;
493
+ batchStores = /* @__PURE__ */ new Set();
494
+ batchManagedStores = /* @__PURE__ */ new Set();
495
+ sharedBatchContext = {
496
+ get depth() {
497
+ return batchDepth;
498
+ },
499
+ get stores() {
500
+ return batchStores;
501
+ },
502
+ get managedStores() {
503
+ return batchManagedStores;
504
+ },
505
+ isBatching,
506
+ batch(store, fn) {
507
+ const wasAlreadyBatching = isStoreManaged(store);
508
+ incrementBatchDepth();
509
+ addBatchStore(store);
510
+ if (!wasAlreadyBatching && "beginBatch" in store) {
511
+ store.beginBatch();
512
+ addManagedStore(store);
449
513
  }
450
- clearBatchStores();
451
- }
452
- return result;
453
- } catch (error) {
454
- decrementBatchDepth();
455
- if (getBatchDepth() === 0) {
456
- for (const s of getBatchManagedStores()) {
457
- if ("endBatch" in s) {
458
- s.endBatch();
514
+ try {
515
+ const result = fn();
516
+ decrementBatchDepth();
517
+ if (getBatchDepth() === 0) {
518
+ for (const s of getBatchManagedStores()) {
519
+ if ("flushNotifications" in s) {
520
+ s.flushNotifications();
521
+ }
522
+ if ("endBatch" in s) {
523
+ s.endBatch();
524
+ }
525
+ }
526
+ clearBatchStores();
527
+ }
528
+ return result;
529
+ } catch (error) {
530
+ decrementBatchDepth();
531
+ if (getBatchDepth() === 0) {
532
+ for (const s of getBatchManagedStores()) {
533
+ if ("endBatch" in s) {
534
+ s.endBatch();
535
+ }
536
+ }
537
+ clearBatchStores();
459
538
  }
539
+ throw error;
460
540
  }
461
- clearBatchStores();
462
541
  }
463
- throw error;
464
- }
542
+ };
465
543
  }
466
- };
544
+ });
467
545
 
468
546
  // src/types.ts
469
- var StoreErrorCode = /* @__PURE__ */ ((StoreErrorCode2) => {
470
- StoreErrorCode2["STORE_DESTROYED"] = "STORE_DESTROYED";
471
- StoreErrorCode2["PLUGIN_EXISTS"] = "PLUGIN_EXISTS";
472
- StoreErrorCode2["PLUGIN_DEPENDENCY_MISSING"] = "PLUGIN_DEPENDENCY_MISSING";
473
- StoreErrorCode2["INVALID_STATE_UPDATE"] = "INVALID_STATE_UPDATE";
474
- StoreErrorCode2["ACTION_ERROR"] = "ACTION_ERROR";
475
- return StoreErrorCode2;
476
- })(StoreErrorCode || {});
477
- var StoreError = class extends Error {
478
- constructor(code, message) {
479
- super(message);
480
- this.code = code;
481
- this.name = "StoreError";
482
- }
483
- };
484
-
485
- // src/store.ts
486
- var StoreImpl = class {
487
- state;
488
- initialState;
489
- listeners = /* @__PURE__ */ new Set();
490
- selectorSubscriptions = /* @__PURE__ */ new Map();
491
- kernel;
492
- destroyed = false;
493
- batchDepth = 0;
494
- pendingNotify = false;
495
- queuedState = null;
496
- queuedPrevState = null;
497
- actions = {};
498
- constructor(initialState, kernel) {
499
- this.state = deepClone(initialState);
500
- this.initialState = deepClone(initialState);
501
- this.kernel = kernel;
502
- this.kernel.onError((error) => {
503
- console.error("Store error:", error);
504
- });
505
- }
506
- /** Get current state snapshot. */
507
- getState() {
508
- this.checkNotDestroyed();
509
- return this.state;
510
- }
511
- /** Update state with partial object or function. */
512
- setState(partial) {
513
- this.checkNotDestroyed();
514
- const prevState = this.state;
515
- const update = typeof partial === "function" ? partial(this.state) : partial;
516
- this.state = { ...this.state, ...update };
517
- this.notifyOrQueue(this.state, prevState);
518
- }
519
- /** Deep merge state. */
520
- merge(partial) {
521
- this.checkNotDestroyed();
522
- const prevState = this.state;
523
- this.state = deepMerge(this.state, partial);
524
- this.notifyOrQueue(this.state, prevState);
525
- }
526
- /** Reset to initial state. */
527
- reset() {
528
- this.checkNotDestroyed();
529
- const prevState = this.state;
530
- this.state = deepClone(this.initialState);
531
- this.notifyOrQueue(this.state, prevState);
532
- }
533
- subscribe(arg1, arg2, arg3) {
534
- this.checkNotDestroyed();
535
- if (arg2 === void 0 && typeof arg1 === "function") {
536
- const listener2 = arg1;
537
- this.listeners.add(listener2);
538
- return () => {
539
- this.listeners.delete(listener2);
540
- };
541
- }
542
- const selector2 = arg1;
543
- const listener = arg2;
544
- const equalityFn = arg3 || shallowEqual;
545
- let subscription = this.selectorSubscriptions.get(selector2);
546
- if (!subscription) {
547
- const initialValue = selector2(this.state);
548
- subscription = {
549
- value: initialValue,
550
- listeners: /* @__PURE__ */ new Set(),
551
- selector: selector2,
552
- equalityFn
553
- };
554
- this.selectorSubscriptions.set(selector2, subscription);
555
- }
556
- subscription.listeners.add(listener);
557
- return () => {
558
- const sub = this.selectorSubscriptions.get(selector2);
559
- if (sub) {
560
- sub.listeners.delete(listener);
561
- if (sub.listeners.size === 0) {
562
- this.selectorSubscriptions.delete(selector2);
563
- }
564
- }
565
- };
566
- }
567
- /** Register a plugin. */
568
- use(plugin, options) {
569
- this.checkNotDestroyed();
570
- this.kernel.register(plugin, options, this);
571
- return this;
572
- }
573
- /** Destroy store and cleanup. */
574
- destroy() {
575
- if (this.destroyed) {
576
- return;
577
- }
578
- this.destroyed = true;
579
- this.kernel.destroy();
580
- this.listeners.clear();
581
- this.selectorSubscriptions.clear();
582
- this.actions = {};
583
- }
584
- /** Add an action (for fluent builder pattern). */
585
- addAction(name, fn) {
586
- this.actions[name] = fn;
587
- return this;
588
- }
589
- /** Get all actions. */
590
- getActions() {
591
- return this.actions;
592
- }
593
- /** Check if store is destroyed. */
594
- checkNotDestroyed() {
595
- if (this.destroyed) {
596
- throw new Error("Cannot use destroyed store");
597
- }
598
- }
599
- /** Notify listeners or queue if batching. */
600
- notifyOrQueue(state, prevState) {
601
- const inGlobalBatch = sharedBatchContext.isBatching();
602
- if (inGlobalBatch) {
603
- const managedStores = sharedBatchContext.managedStores;
604
- if (!managedStores.has(this)) {
605
- managedStores.add(this);
606
- }
607
- }
608
- if (this.batchDepth > 0 || inGlobalBatch) {
609
- this.queuedState = state;
610
- if (!this.pendingNotify) {
611
- this.queuedPrevState = prevState;
612
- }
613
- this.pendingNotify = true;
614
- } else {
615
- this.notify(state, prevState);
616
- }
617
- }
618
- /** Notify all listeners. */
619
- notify(state, prevState) {
620
- this.kernel.emitStateChange(state, prevState);
621
- for (const listener of this.listeners) {
622
- try {
623
- listener(state, prevState);
624
- } catch (error) {
625
- this.kernel.emitError(error);
626
- }
627
- }
628
- for (const subscription of this.selectorSubscriptions.values()) {
629
- const newValue = subscription.selector(state);
630
- if (!subscription.equalityFn(newValue, subscription.value)) {
631
- const prevValue = subscription.value;
632
- subscription.value = newValue;
633
- for (const listener of subscription.listeners) {
634
- try {
635
- listener(newValue, prevValue);
636
- } catch (error) {
637
- this.kernel.emitError(error);
638
- }
639
- }
640
- }
641
- }
642
- }
643
- /** Flush pending notifications (end of batch). */
644
- flushNotifications() {
645
- if (this.pendingNotify) {
646
- this.notify(this.queuedState, this.queuedPrevState);
647
- this.pendingNotify = false;
648
- this.queuedState = null;
649
- this.queuedPrevState = null;
650
- }
651
- }
652
- /** Start batching. */
653
- beginBatch() {
654
- this.batchDepth++;
655
- }
656
- /** End batching. */
657
- endBatch() {
658
- this.batchDepth--;
659
- if (this.batchDepth === 0) {
660
- this.flushNotifications();
661
- }
662
- }
663
- };
664
- var StoreBuilderImpl = class {
665
- store;
666
- constructor(initialState, kernel) {
667
- this.store = new StoreImpl(initialState, kernel);
668
- }
669
- getState() {
670
- return this.store.getState();
671
- }
672
- setState(partial) {
673
- this.store.setState(partial);
674
- }
675
- merge(partial) {
676
- this.store.merge(partial);
677
- }
678
- reset() {
679
- this.store.reset();
680
- }
681
- subscribe(arg1, arg2, arg3) {
682
- if (arg2 === void 0) {
683
- return this.store.subscribe(arg1);
684
- } else {
685
- return this.store.subscribe(arg1, arg2, arg3);
686
- }
687
- }
688
- use(plugin, options) {
689
- this.store.use(plugin, options);
690
- return this;
691
- }
692
- destroy() {
693
- this.store.destroy();
694
- }
695
- action(name, fn) {
696
- this.store.addAction(name, fn);
697
- this[name] = (...args) => {
698
- const currentState = this.getState();
699
- const result = fn(currentState, ...args);
700
- if (result instanceof Promise) {
701
- return result.then((partial) => {
702
- this.setState(partial);
703
- return partial;
704
- });
547
+ exports.StoreErrorCode = void 0; exports.StoreError = void 0;
548
+ var init_types = __esm({
549
+ "src/types.ts"() {
550
+ exports.StoreErrorCode = /* @__PURE__ */ ((StoreErrorCode2) => {
551
+ StoreErrorCode2["STORE_DESTROYED"] = "STORE_DESTROYED";
552
+ StoreErrorCode2["PLUGIN_EXISTS"] = "PLUGIN_EXISTS";
553
+ StoreErrorCode2["PLUGIN_DEPENDENCY_MISSING"] = "PLUGIN_DEPENDENCY_MISSING";
554
+ StoreErrorCode2["INVALID_STATE_UPDATE"] = "INVALID_STATE_UPDATE";
555
+ StoreErrorCode2["ACTION_ERROR"] = "ACTION_ERROR";
556
+ return StoreErrorCode2;
557
+ })(exports.StoreErrorCode || {});
558
+ exports.StoreError = class extends Error {
559
+ constructor(code, message) {
560
+ super(message);
561
+ this.code = code;
562
+ this.name = "StoreError";
705
563
  }
706
- this.setState(result);
707
- return result;
708
564
  };
709
- return this;
710
- }
711
- /** Add action (internal use). */
712
- addAction(name, fn) {
713
- this.store.addAction(name, fn);
714
- return this;
715
- }
716
- /** Get actions (internal use). */
717
- getActions() {
718
- return this.store.getActions();
719
- }
720
- /** Start batching. */
721
- beginBatch() {
722
- this.store.beginBatch();
723
565
  }
724
- /** End batching. */
725
- endBatch() {
726
- this.store.endBatch();
727
- }
728
- /** Flush pending notifications. */
729
- flushNotifications() {
730
- this.store.flushNotifications();
731
- }
732
- };
566
+ });
567
+
568
+ // src/store.ts
569
+ var store_exports = {};
570
+ __export(store_exports, {
571
+ StoreError: () => exports.StoreError,
572
+ StoreErrorCode: () => exports.StoreErrorCode,
573
+ StoreImpl: () => StoreImpl,
574
+ batch: () => batch,
575
+ createStore: () => createStore
576
+ });
733
577
  function createStore(initialState, actions) {
734
578
  const kernel = createKernel({ name: "store" });
735
579
  const state = { ...initialState };
@@ -796,6 +640,270 @@ function createStore(initialState, actions) {
796
640
  function batch(fn) {
797
641
  return fn();
798
642
  }
643
+ var StoreImpl, StoreBuilderImpl;
644
+ var init_store = __esm({
645
+ "src/store.ts"() {
646
+ init_utils();
647
+ init_kernel();
648
+ init_batch_context();
649
+ init_types();
650
+ StoreImpl = class {
651
+ state;
652
+ initialState;
653
+ listeners = /* @__PURE__ */ new Set();
654
+ selectorSubscriptions = /* @__PURE__ */ new Map();
655
+ kernel;
656
+ destroyed = false;
657
+ batchDepth = 0;
658
+ pendingNotify = false;
659
+ queuedState = null;
660
+ queuedPrevState = null;
661
+ actions = {};
662
+ constructor(initialState, kernel) {
663
+ this.state = deepClone(initialState);
664
+ this.initialState = deepClone(initialState);
665
+ this.kernel = kernel;
666
+ this.kernel.onError((error) => {
667
+ console.error("Store error:", error);
668
+ });
669
+ }
670
+ /** Get current state snapshot. */
671
+ getState() {
672
+ this.checkNotDestroyed();
673
+ return this.state;
674
+ }
675
+ /** Update state with partial object or function. */
676
+ setState(partial) {
677
+ this.checkNotDestroyed();
678
+ const prevState = this.state;
679
+ const update = typeof partial === "function" ? partial(this.state) : partial;
680
+ this.state = { ...this.state, ...update };
681
+ this.notifyOrQueue(this.state, prevState);
682
+ }
683
+ /** Deep merge state. */
684
+ merge(partial) {
685
+ this.checkNotDestroyed();
686
+ const prevState = this.state;
687
+ this.state = deepMerge(this.state, partial);
688
+ this.notifyOrQueue(this.state, prevState);
689
+ }
690
+ /** Reset to initial state. */
691
+ reset() {
692
+ this.checkNotDestroyed();
693
+ const prevState = this.state;
694
+ this.state = deepClone(this.initialState);
695
+ this.notifyOrQueue(this.state, prevState);
696
+ }
697
+ subscribe(arg1, arg2, arg3) {
698
+ this.checkNotDestroyed();
699
+ if (arg2 === void 0 && typeof arg1 === "function") {
700
+ const listener2 = arg1;
701
+ this.listeners.add(listener2);
702
+ return () => {
703
+ this.listeners.delete(listener2);
704
+ };
705
+ }
706
+ const selector2 = arg1;
707
+ const listener = arg2;
708
+ const equalityFn = arg3 || shallowEqual;
709
+ let subscription = this.selectorSubscriptions.get(selector2);
710
+ if (!subscription) {
711
+ const initialValue = selector2(this.state);
712
+ subscription = {
713
+ value: initialValue,
714
+ listeners: /* @__PURE__ */ new Set(),
715
+ selector: selector2,
716
+ equalityFn
717
+ };
718
+ this.selectorSubscriptions.set(selector2, subscription);
719
+ }
720
+ subscription.listeners.add(listener);
721
+ return () => {
722
+ const sub = this.selectorSubscriptions.get(selector2);
723
+ if (sub) {
724
+ sub.listeners.delete(listener);
725
+ if (sub.listeners.size === 0) {
726
+ this.selectorSubscriptions.delete(selector2);
727
+ }
728
+ }
729
+ };
730
+ }
731
+ /** Register a plugin. */
732
+ use(plugin, options) {
733
+ this.checkNotDestroyed();
734
+ this.kernel.register(plugin, options, this);
735
+ return this;
736
+ }
737
+ /** Destroy store and cleanup. */
738
+ destroy() {
739
+ if (this.destroyed) {
740
+ return;
741
+ }
742
+ this.destroyed = true;
743
+ this.kernel.destroy();
744
+ this.listeners.clear();
745
+ this.selectorSubscriptions.clear();
746
+ this.actions = {};
747
+ }
748
+ /** Add an action (for fluent builder pattern). */
749
+ addAction(name, fn) {
750
+ this.actions[name] = fn;
751
+ return this;
752
+ }
753
+ /** Get all actions. */
754
+ getActions() {
755
+ return this.actions;
756
+ }
757
+ /** Check if store is destroyed. */
758
+ checkNotDestroyed() {
759
+ if (this.destroyed) {
760
+ throw new Error("Cannot use destroyed store");
761
+ }
762
+ }
763
+ /** Notify listeners or queue if batching. */
764
+ notifyOrQueue(state, prevState) {
765
+ const inGlobalBatch = sharedBatchContext.isBatching();
766
+ if (inGlobalBatch) {
767
+ const managedStores = sharedBatchContext.managedStores;
768
+ if (!managedStores.has(this)) {
769
+ managedStores.add(this);
770
+ }
771
+ }
772
+ if (this.batchDepth > 0 || inGlobalBatch) {
773
+ this.queuedState = state;
774
+ if (!this.pendingNotify) {
775
+ this.queuedPrevState = prevState;
776
+ }
777
+ this.pendingNotify = true;
778
+ } else {
779
+ this.notify(state, prevState);
780
+ }
781
+ }
782
+ /** Notify all listeners. */
783
+ notify(state, prevState) {
784
+ this.kernel.emitStateChange(state, prevState);
785
+ for (const listener of this.listeners) {
786
+ try {
787
+ listener(state, prevState);
788
+ } catch (error) {
789
+ this.kernel.emitError(error);
790
+ }
791
+ }
792
+ for (const subscription of this.selectorSubscriptions.values()) {
793
+ const newValue = subscription.selector(state);
794
+ if (!subscription.equalityFn(newValue, subscription.value)) {
795
+ const prevValue = subscription.value;
796
+ subscription.value = newValue;
797
+ for (const listener of subscription.listeners) {
798
+ try {
799
+ listener(newValue, prevValue);
800
+ } catch (error) {
801
+ this.kernel.emitError(error);
802
+ }
803
+ }
804
+ }
805
+ }
806
+ }
807
+ /** Flush pending notifications (end of batch). */
808
+ flushNotifications() {
809
+ if (this.pendingNotify) {
810
+ this.notify(this.queuedState, this.queuedPrevState);
811
+ this.pendingNotify = false;
812
+ this.queuedState = null;
813
+ this.queuedPrevState = null;
814
+ }
815
+ }
816
+ /** Start batching. */
817
+ beginBatch() {
818
+ this.batchDepth++;
819
+ }
820
+ /** End batching. */
821
+ endBatch() {
822
+ this.batchDepth--;
823
+ if (this.batchDepth === 0) {
824
+ this.flushNotifications();
825
+ }
826
+ }
827
+ };
828
+ StoreBuilderImpl = class {
829
+ store;
830
+ constructor(initialState, kernel) {
831
+ this.store = new StoreImpl(initialState, kernel);
832
+ }
833
+ getState() {
834
+ return this.store.getState();
835
+ }
836
+ setState(partial) {
837
+ this.store.setState(partial);
838
+ }
839
+ merge(partial) {
840
+ this.store.merge(partial);
841
+ }
842
+ reset() {
843
+ this.store.reset();
844
+ }
845
+ subscribe(arg1, arg2, arg3) {
846
+ if (arg2 === void 0) {
847
+ return this.store.subscribe(arg1);
848
+ } else {
849
+ return this.store.subscribe(arg1, arg2, arg3);
850
+ }
851
+ }
852
+ use(plugin, options) {
853
+ this.store.use(plugin, options);
854
+ return this;
855
+ }
856
+ destroy() {
857
+ this.store.destroy();
858
+ }
859
+ action(name, fn) {
860
+ this.store.addAction(name, fn);
861
+ this[name] = (...args) => {
862
+ const currentState = this.getState();
863
+ const result = fn(currentState, ...args);
864
+ if (result instanceof Promise) {
865
+ return result.then((partial) => {
866
+ this.setState(partial);
867
+ return partial;
868
+ });
869
+ }
870
+ this.setState(result);
871
+ return result;
872
+ };
873
+ return this;
874
+ }
875
+ /** Add action (internal use). */
876
+ addAction(name, fn) {
877
+ this.store.addAction(name, fn);
878
+ return this;
879
+ }
880
+ /** Get actions (internal use). */
881
+ getActions() {
882
+ return this.store.getActions();
883
+ }
884
+ /** Start batching. */
885
+ beginBatch() {
886
+ this.store.beginBatch();
887
+ }
888
+ /** End batching. */
889
+ endBatch() {
890
+ this.store.endBatch();
891
+ }
892
+ /** Flush pending notifications. */
893
+ flushNotifications() {
894
+ this.store.flushNotifications();
895
+ }
896
+ };
897
+ }
898
+ });
899
+
900
+ // src/index.ts
901
+ init_store();
902
+
903
+ // src/react.ts
904
+ init_identity();
905
+ init_shallow_equal();
906
+ init_store();
799
907
  function useStore(store, selector2 = identity, equalityFn = shallowEqual) {
800
908
  const selectorRef = react.useRef(selector2);
801
909
  const equalityFnRef = react.useRef(equalityFn);
@@ -857,12 +965,798 @@ function useAction(store, actionName) {
857
965
  }
858
966
  return actionRef.current;
859
967
  }
860
-
861
- // src/plugins/persist.ts
862
- var defaultStorage = {
863
- getItem: (key) => {
864
- if (typeof window === "undefined") return null;
865
- try {
968
+ function useShallow(selector2) {
969
+ const prev = react.useRef();
970
+ return (state) => {
971
+ const next = selector2(state);
972
+ if (prev.current === void 0) {
973
+ prev.current = next;
974
+ return next;
975
+ }
976
+ if (shallowCompareObjects(prev.current, next)) {
977
+ return prev.current;
978
+ }
979
+ prev.current = next;
980
+ return next;
981
+ };
982
+ }
983
+ function shallowCompareObjects(a, b) {
984
+ if (a === b) return true;
985
+ if (typeof a !== "object" || typeof b !== "object") return false;
986
+ if (a === null || b === null) return false;
987
+ const keysA = Object.keys(a);
988
+ const keysB = Object.keys(b);
989
+ if (keysA.length !== keysB.length) return false;
990
+ for (const key of keysA) {
991
+ if (a[key] !== b[key]) {
992
+ return false;
993
+ }
994
+ }
995
+ return true;
996
+ }
997
+ function useStoreActions(store, ...actionNames) {
998
+ const storeRef = react.useRef(store);
999
+ const actionsRef = react.useRef({});
1000
+ if (storeRef.current !== store) {
1001
+ storeRef.current = store;
1002
+ actionsRef.current = {};
1003
+ }
1004
+ const result = {};
1005
+ for (const name of actionNames) {
1006
+ if (!actionsRef.current[name]) {
1007
+ actionsRef.current[name] = storeRef.current[name];
1008
+ }
1009
+ result[name] = actionsRef.current[name];
1010
+ }
1011
+ return result;
1012
+ }
1013
+ function useStoreSelector(store, selectors) {
1014
+ const selectorsRef = react.useRef(selectors);
1015
+ const keysRef = react.useRef(Object.keys(selectors));
1016
+ const prevResultRef = react.useRef(null);
1017
+ if (selectorsRef.current !== selectors) {
1018
+ selectorsRef.current = selectors;
1019
+ keysRef.current = Object.keys(selectors);
1020
+ }
1021
+ const combinedSelector = react.useCallback((state) => {
1022
+ const keys = keysRef.current;
1023
+ const currentSelectors = selectorsRef.current;
1024
+ const result = {};
1025
+ for (const key of keys) {
1026
+ const selector2 = currentSelectors[key];
1027
+ if (selector2) {
1028
+ result[key] = selector2(state);
1029
+ }
1030
+ }
1031
+ if (prevResultRef.current !== null) {
1032
+ let isEqual = true;
1033
+ for (const key of keys) {
1034
+ if (!shallowEqual(prevResultRef.current[key], result[key])) {
1035
+ isEqual = false;
1036
+ break;
1037
+ }
1038
+ }
1039
+ if (isEqual) {
1040
+ return prevResultRef.current;
1041
+ }
1042
+ }
1043
+ prevResultRef.current = result;
1044
+ return result;
1045
+ }, []);
1046
+ return useStore(store, combinedSelector);
1047
+ }
1048
+ function useTransientSubscribe(store, selector2, callback, equalityFn = shallowEqual) {
1049
+ const callbackRef = react.useRef(callback);
1050
+ callbackRef.current = callback;
1051
+ react.useEffect(() => {
1052
+ const unsubscribe = store.subscribe(
1053
+ selector2,
1054
+ (value, prevValue) => callbackRef.current(value, prevValue),
1055
+ equalityFn
1056
+ );
1057
+ return unsubscribe;
1058
+ }, [store, selector2, equalityFn]);
1059
+ }
1060
+ function useSetState(store) {
1061
+ const storeRef = react.useRef(store);
1062
+ if (storeRef.current !== store) {
1063
+ storeRef.current = store;
1064
+ }
1065
+ const setStateRef = react.useRef((partial) => {
1066
+ storeRef.current.setState(partial);
1067
+ });
1068
+ return setStateRef.current;
1069
+ }
1070
+
1071
+ // src/subscribe.ts
1072
+ init_utils();
1073
+ function createDebounced(fn, delay2) {
1074
+ let timeoutId = null;
1075
+ const debounced = ((...args) => {
1076
+ if (timeoutId) {
1077
+ clearTimeout(timeoutId);
1078
+ }
1079
+ timeoutId = setTimeout(() => {
1080
+ fn(...args);
1081
+ timeoutId = null;
1082
+ }, delay2);
1083
+ });
1084
+ debounced.cancel = () => {
1085
+ if (timeoutId) {
1086
+ clearTimeout(timeoutId);
1087
+ timeoutId = null;
1088
+ }
1089
+ };
1090
+ return debounced;
1091
+ }
1092
+ function createThrottled(fn, delay2) {
1093
+ let lastCall = 0;
1094
+ let timeoutId = null;
1095
+ let lastArgs = null;
1096
+ const throttled = ((...args) => {
1097
+ const now = Date.now();
1098
+ const remaining = delay2 - (now - lastCall);
1099
+ lastArgs = args;
1100
+ if (remaining <= 0) {
1101
+ if (timeoutId) {
1102
+ clearTimeout(timeoutId);
1103
+ timeoutId = null;
1104
+ }
1105
+ lastCall = now;
1106
+ fn(...args);
1107
+ } else if (!timeoutId) {
1108
+ timeoutId = setTimeout(() => {
1109
+ lastCall = Date.now();
1110
+ timeoutId = null;
1111
+ if (lastArgs) {
1112
+ fn(...lastArgs);
1113
+ }
1114
+ }, remaining);
1115
+ }
1116
+ });
1117
+ throttled.cancel = () => {
1118
+ if (timeoutId) {
1119
+ clearTimeout(timeoutId);
1120
+ timeoutId = null;
1121
+ }
1122
+ lastArgs = null;
1123
+ };
1124
+ return throttled;
1125
+ }
1126
+ function subscribeWithOptions(store, selector2, listener, options = {}) {
1127
+ const {
1128
+ equalityFn = shallowEqual,
1129
+ fireImmediately = false,
1130
+ debounce,
1131
+ throttle,
1132
+ when
1133
+ } = options;
1134
+ if (debounce !== void 0 && throttle !== void 0) {
1135
+ throw new Error("Cannot use both debounce and throttle options");
1136
+ }
1137
+ let wrappedListener = listener;
1138
+ let cleanup = null;
1139
+ if (debounce !== void 0 && debounce > 0) {
1140
+ const debouncedListener = createDebounced(listener, debounce);
1141
+ wrappedListener = debouncedListener;
1142
+ cleanup = () => debouncedListener.cancel();
1143
+ } else if (throttle !== void 0 && throttle > 0) {
1144
+ const throttledListener = createThrottled(listener, throttle);
1145
+ wrappedListener = throttledListener;
1146
+ cleanup = () => throttledListener.cancel();
1147
+ }
1148
+ let finalListener;
1149
+ let prevState = store.getState();
1150
+ if (when) {
1151
+ finalListener = (value, prevValue) => {
1152
+ const currentState = store.getState();
1153
+ if (when(currentState, prevState)) {
1154
+ wrappedListener(value, prevValue);
1155
+ }
1156
+ prevState = currentState;
1157
+ };
1158
+ } else {
1159
+ finalListener = wrappedListener;
1160
+ }
1161
+ if (fireImmediately) {
1162
+ const currentValue = selector2(store.getState());
1163
+ finalListener(currentValue, currentValue);
1164
+ }
1165
+ const unsubscribe = store.subscribe(selector2, finalListener, equalityFn);
1166
+ return () => {
1167
+ unsubscribe();
1168
+ if (cleanup) {
1169
+ cleanup();
1170
+ }
1171
+ };
1172
+ }
1173
+ function createSubscriber(defaultOptions = {}) {
1174
+ return (store, selector2, listener, options = {}) => {
1175
+ return subscribeWithOptions(store, selector2, listener, {
1176
+ ...defaultOptions,
1177
+ ...options
1178
+ });
1179
+ };
1180
+ }
1181
+ function subscribeToMany(store, selectors, listener, options = {}) {
1182
+ const keys = Object.keys(selectors);
1183
+ const state = store.getState();
1184
+ for (const key of keys) {
1185
+ const selector2 = selectors[key];
1186
+ if (selector2) {
1187
+ selector2(state);
1188
+ }
1189
+ }
1190
+ const combinedSelector = (state2) => {
1191
+ const result = {};
1192
+ for (const key of keys) {
1193
+ const selector2 = selectors[key];
1194
+ if (selector2) {
1195
+ result[key] = selector2(state2);
1196
+ }
1197
+ }
1198
+ return result;
1199
+ };
1200
+ const combinedEqualityFn = (a, b) => {
1201
+ for (const key of keys) {
1202
+ if (!shallowEqual(a[key], b[key])) {
1203
+ return false;
1204
+ }
1205
+ }
1206
+ return true;
1207
+ };
1208
+ return subscribeWithOptions(
1209
+ store,
1210
+ combinedSelector,
1211
+ listener,
1212
+ { ...options, equalityFn: combinedEqualityFn }
1213
+ );
1214
+ }
1215
+ function subscribeOnce(store, selector2, listener, options = {}) {
1216
+ let unsubscribe = null;
1217
+ const onceListener = (value, prevValue) => {
1218
+ listener(value, prevValue);
1219
+ if (unsubscribe) {
1220
+ unsubscribe();
1221
+ }
1222
+ };
1223
+ unsubscribe = subscribeWithOptions(store, selector2, onceListener, options);
1224
+ return unsubscribe;
1225
+ }
1226
+
1227
+ // src/computed.ts
1228
+ init_utils();
1229
+ function computed(store, selector2, options = {}) {
1230
+ const { equals = shallowEqual, lazy = false, cacheSize = 1 } = options;
1231
+ const cache = [];
1232
+ let currentValue;
1233
+ let isInitialized = false;
1234
+ let isDestroyed = false;
1235
+ const listeners = /* @__PURE__ */ new Set();
1236
+ let unsubscribe = null;
1237
+ const compute = () => {
1238
+ const state = store.getState();
1239
+ for (const entry of cache) {
1240
+ if (entry.input === state || shallowEqual(entry.input, state)) {
1241
+ return entry.output;
1242
+ }
1243
+ }
1244
+ const newValue = selector2(state);
1245
+ cache.unshift({ input: state, output: newValue });
1246
+ while (cache.length > cacheSize) {
1247
+ cache.pop();
1248
+ }
1249
+ return newValue;
1250
+ };
1251
+ const initialize = () => {
1252
+ if (isInitialized || isDestroyed) return;
1253
+ isInitialized = true;
1254
+ currentValue = compute();
1255
+ unsubscribe = store.subscribe((state, prevState) => {
1256
+ const prevValue = currentValue;
1257
+ const newValue = compute();
1258
+ if (!equals(newValue, prevValue)) {
1259
+ currentValue = newValue;
1260
+ for (const listener of listeners) {
1261
+ try {
1262
+ listener(newValue, prevValue);
1263
+ } catch (error) {
1264
+ console.error("Computed listener error:", error);
1265
+ }
1266
+ }
1267
+ }
1268
+ });
1269
+ };
1270
+ if (!lazy) {
1271
+ initialize();
1272
+ }
1273
+ const get = () => {
1274
+ if (isDestroyed) {
1275
+ throw new Error("Cannot access destroyed computed value");
1276
+ }
1277
+ if (!isInitialized) {
1278
+ initialize();
1279
+ }
1280
+ return currentValue;
1281
+ };
1282
+ const invalidate = () => {
1283
+ if (isDestroyed) return;
1284
+ cache.length = 0;
1285
+ if (isInitialized) {
1286
+ const prevValue = currentValue;
1287
+ currentValue = compute();
1288
+ if (!equals(currentValue, prevValue)) {
1289
+ for (const listener of listeners) {
1290
+ try {
1291
+ listener(currentValue, prevValue);
1292
+ } catch (error) {
1293
+ console.error("Computed listener error:", error);
1294
+ }
1295
+ }
1296
+ }
1297
+ }
1298
+ };
1299
+ const subscribe = (listener) => {
1300
+ if (isDestroyed) {
1301
+ throw new Error("Cannot subscribe to destroyed computed value");
1302
+ }
1303
+ if (!isInitialized) {
1304
+ initialize();
1305
+ }
1306
+ listeners.add(listener);
1307
+ return () => {
1308
+ listeners.delete(listener);
1309
+ };
1310
+ };
1311
+ const getHistory = () => {
1312
+ return cache.map((entry) => entry.output);
1313
+ };
1314
+ const destroy = () => {
1315
+ if (isDestroyed) return;
1316
+ isDestroyed = true;
1317
+ if (unsubscribe) {
1318
+ unsubscribe();
1319
+ unsubscribe = null;
1320
+ }
1321
+ listeners.clear();
1322
+ cache.length = 0;
1323
+ currentValue = void 0;
1324
+ };
1325
+ const computedFn = get;
1326
+ computedFn.get = get;
1327
+ computedFn.invalidate = invalidate;
1328
+ computedFn.subscribe = subscribe;
1329
+ computedFn.getHistory = getHistory;
1330
+ computedFn.destroy = destroy;
1331
+ return computedFn;
1332
+ }
1333
+ function combineComputed(computeds, combiner, options = {}) {
1334
+ const { equals = shallowEqual, cacheSize = 1 } = options;
1335
+ let currentValue;
1336
+ let isDestroyed = false;
1337
+ const listeners = /* @__PURE__ */ new Set();
1338
+ const unsubscribes = [];
1339
+ const cache = [];
1340
+ const compute = () => {
1341
+ const values = computeds.map((c) => c());
1342
+ return combiner(values);
1343
+ };
1344
+ currentValue = compute();
1345
+ cache.push(currentValue);
1346
+ for (const computed2 of computeds) {
1347
+ const unsub = computed2.subscribe(() => {
1348
+ if (isDestroyed) return;
1349
+ const prevValue = currentValue;
1350
+ const newValue = compute();
1351
+ if (!equals(newValue, prevValue)) {
1352
+ currentValue = newValue;
1353
+ cache.unshift(newValue);
1354
+ while (cache.length > cacheSize) {
1355
+ cache.pop();
1356
+ }
1357
+ for (const listener of listeners) {
1358
+ try {
1359
+ listener(newValue, prevValue);
1360
+ } catch (error) {
1361
+ console.error("Combined computed listener error:", error);
1362
+ }
1363
+ }
1364
+ }
1365
+ });
1366
+ unsubscribes.push(unsub);
1367
+ }
1368
+ const get = () => {
1369
+ if (isDestroyed) {
1370
+ throw new Error("Cannot access destroyed computed value");
1371
+ }
1372
+ return currentValue;
1373
+ };
1374
+ const invalidate = () => {
1375
+ if (isDestroyed) return;
1376
+ for (const computed2 of computeds) {
1377
+ computed2.invalidate();
1378
+ }
1379
+ };
1380
+ const subscribe = (listener) => {
1381
+ if (isDestroyed) {
1382
+ throw new Error("Cannot subscribe to destroyed computed value");
1383
+ }
1384
+ listeners.add(listener);
1385
+ return () => listeners.delete(listener);
1386
+ };
1387
+ const getHistory = () => [...cache];
1388
+ const destroy = () => {
1389
+ if (isDestroyed) return;
1390
+ isDestroyed = true;
1391
+ for (const unsub of unsubscribes) {
1392
+ unsub();
1393
+ }
1394
+ listeners.clear();
1395
+ cache.length = 0;
1396
+ };
1397
+ const combinedFn = get;
1398
+ combinedFn.get = get;
1399
+ combinedFn.invalidate = invalidate;
1400
+ combinedFn.subscribe = subscribe;
1401
+ combinedFn.getHistory = getHistory;
1402
+ combinedFn.destroy = destroy;
1403
+ return combinedFn;
1404
+ }
1405
+ function memoizeSelector(selector2, equals = shallowEqual) {
1406
+ let lastState;
1407
+ let lastResult;
1408
+ let isInitialized = false;
1409
+ return (state) => {
1410
+ if (!isInitialized || lastState !== state) {
1411
+ const newResult = selector2(state);
1412
+ if (!isInitialized || !equals(newResult, lastResult)) {
1413
+ lastResult = newResult;
1414
+ }
1415
+ lastState = state;
1416
+ isInitialized = true;
1417
+ }
1418
+ return lastResult;
1419
+ };
1420
+ }
1421
+
1422
+ // src/slices.ts
1423
+ init_store();
1424
+ function createSlice(name, creator) {
1425
+ return { name, creator };
1426
+ }
1427
+ function combineSlices(...slices) {
1428
+ const initialState = {};
1429
+ const actions = {};
1430
+ let tempStore = null;
1431
+ const set = (partial) => {
1432
+ if (tempStore) {
1433
+ if (typeof partial === "function") {
1434
+ tempStore.setState(partial);
1435
+ } else {
1436
+ tempStore.setState(partial);
1437
+ }
1438
+ }
1439
+ };
1440
+ const get = () => {
1441
+ return tempStore ? tempStore.getState() : initialState;
1442
+ };
1443
+ const placeholderStore = {
1444
+ getState: () => initialState,
1445
+ setState: () => {
1446
+ },
1447
+ subscribe: () => () => {
1448
+ },
1449
+ merge: () => {
1450
+ },
1451
+ reset: () => {
1452
+ },
1453
+ use: () => placeholderStore,
1454
+ destroy: () => {
1455
+ }
1456
+ };
1457
+ for (const slice of slices) {
1458
+ const sliceResult = slice.creator(set, get, placeholderStore);
1459
+ for (const [key, value] of Object.entries(sliceResult)) {
1460
+ if (typeof value === "function") {
1461
+ actions[key] = value;
1462
+ } else {
1463
+ initialState[key] = value;
1464
+ }
1465
+ }
1466
+ }
1467
+ tempStore = createStore(initialState);
1468
+ for (const slice of slices) {
1469
+ const sliceResult = slice.creator(
1470
+ (partial) => {
1471
+ if (typeof partial === "function") {
1472
+ tempStore.setState(partial);
1473
+ } else {
1474
+ tempStore.setState(partial);
1475
+ }
1476
+ },
1477
+ () => tempStore.getState(),
1478
+ tempStore
1479
+ );
1480
+ for (const [key, value] of Object.entries(sliceResult)) {
1481
+ if (typeof value === "function") {
1482
+ actions[key] = value;
1483
+ }
1484
+ }
1485
+ }
1486
+ const store = tempStore;
1487
+ for (const [name, action] of Object.entries(actions)) {
1488
+ store[name] = action;
1489
+ }
1490
+ return store;
1491
+ }
1492
+ function createNamespacedSlice(namespace, creator) {
1493
+ return createSlice(namespace, (set, get, store) => {
1494
+ const namespacedSet = (partial) => {
1495
+ const current = get()[namespace] || {};
1496
+ const update = typeof partial === "function" ? partial(current) : partial;
1497
+ set({ [namespace]: { ...current, ...update } });
1498
+ };
1499
+ const namespacedGet = () => {
1500
+ return get()[namespace] || {};
1501
+ };
1502
+ const sliceResult = creator(namespacedSet, namespacedGet);
1503
+ const state = {};
1504
+ const actions = {};
1505
+ for (const [key, value] of Object.entries(sliceResult)) {
1506
+ if (typeof value === "function") {
1507
+ actions[key] = value;
1508
+ } else {
1509
+ state[key] = value;
1510
+ }
1511
+ }
1512
+ return {
1513
+ [namespace]: state,
1514
+ ...actions
1515
+ };
1516
+ });
1517
+ }
1518
+ function extendStore(store, ...slices) {
1519
+ const actions = {};
1520
+ const set = (partial) => {
1521
+ if (typeof partial === "function") {
1522
+ store.setState(partial);
1523
+ } else {
1524
+ store.setState(partial);
1525
+ }
1526
+ };
1527
+ const get = () => store.getState();
1528
+ for (const slice of slices) {
1529
+ const sliceResult = slice.creator(set, get, store);
1530
+ for (const [key, value] of Object.entries(sliceResult)) {
1531
+ if (typeof value === "function") {
1532
+ actions[key] = value;
1533
+ } else {
1534
+ store.setState({ [key]: value });
1535
+ }
1536
+ }
1537
+ }
1538
+ const extendedStore = store;
1539
+ for (const [name, action] of Object.entries(actions)) {
1540
+ extendedStore[name] = action;
1541
+ }
1542
+ return extendedStore;
1543
+ }
1544
+ function resetSlices(store, ...sliceNames) {
1545
+ console.warn("resetSlices: Use store.reset() to reset all state");
1546
+ store.reset();
1547
+ }
1548
+
1549
+ // src/federation.ts
1550
+ function createFederation(stores, options = {}) {
1551
+ const { name = "federation", debug = false } = options;
1552
+ const listeners = /* @__PURE__ */ new Set();
1553
+ const unsubscribers = [];
1554
+ let isInTransaction = false;
1555
+ let transactionChanges = [];
1556
+ let previousStates = null;
1557
+ const getState = () => {
1558
+ const state = {};
1559
+ for (const key in stores) {
1560
+ const store = stores[key];
1561
+ if (store) {
1562
+ state[key] = store.getState();
1563
+ }
1564
+ }
1565
+ return state;
1566
+ };
1567
+ const notify = (changedStore) => {
1568
+ if (isInTransaction) {
1569
+ if (!transactionChanges.includes(changedStore)) {
1570
+ transactionChanges.push(changedStore);
1571
+ }
1572
+ return;
1573
+ }
1574
+ const state = getState();
1575
+ const prevState = previousStates || state;
1576
+ for (const listener of listeners) {
1577
+ try {
1578
+ listener(state, prevState, changedStore);
1579
+ } catch (error) {
1580
+ console.error(`Federation listener error:`, error);
1581
+ }
1582
+ }
1583
+ previousStates = state;
1584
+ };
1585
+ for (const key in stores) {
1586
+ const store = stores[key];
1587
+ if (store) {
1588
+ const unsubscribe = store.subscribe(() => {
1589
+ notify(key);
1590
+ });
1591
+ unsubscribers.push(unsubscribe);
1592
+ }
1593
+ }
1594
+ previousStates = getState();
1595
+ const log = (message, ...args) => {
1596
+ if (debug) {
1597
+ console.log(`[${name}] ${message}`, ...args);
1598
+ }
1599
+ };
1600
+ return {
1601
+ stores,
1602
+ getState,
1603
+ subscribe(listener) {
1604
+ listeners.add(listener);
1605
+ return () => {
1606
+ listeners.delete(listener);
1607
+ };
1608
+ },
1609
+ transaction(fn) {
1610
+ if (isInTransaction) {
1611
+ fn(stores);
1612
+ return;
1613
+ }
1614
+ isInTransaction = true;
1615
+ transactionChanges = [];
1616
+ const snapshotStates = getState();
1617
+ log("Transaction started");
1618
+ try {
1619
+ const result = fn(stores);
1620
+ if (result instanceof Promise) {
1621
+ throw new Error(
1622
+ "Async operations in transaction() are not supported. Use transactionAsync() instead."
1623
+ );
1624
+ }
1625
+ isInTransaction = false;
1626
+ if (transactionChanges.length > 0) {
1627
+ log("Transaction committed, changed stores:", transactionChanges);
1628
+ const state = getState();
1629
+ for (const listener of listeners) {
1630
+ try {
1631
+ listener(state, snapshotStates, transactionChanges[0]);
1632
+ } catch (error) {
1633
+ console.error(`Federation listener error:`, error);
1634
+ }
1635
+ }
1636
+ previousStates = state;
1637
+ }
1638
+ } catch (error) {
1639
+ isInTransaction = false;
1640
+ log("Transaction failed, rolling back");
1641
+ for (const key in stores) {
1642
+ const store = stores[key];
1643
+ if (store) {
1644
+ store.setState(snapshotStates[key]);
1645
+ }
1646
+ }
1647
+ throw error;
1648
+ }
1649
+ },
1650
+ async transactionAsync(fn) {
1651
+ if (isInTransaction) {
1652
+ await fn(stores);
1653
+ return;
1654
+ }
1655
+ isInTransaction = true;
1656
+ transactionChanges = [];
1657
+ const snapshotStates = getState();
1658
+ log("Async transaction started");
1659
+ try {
1660
+ await fn(stores);
1661
+ isInTransaction = false;
1662
+ if (transactionChanges.length > 0) {
1663
+ log("Async transaction committed, changed stores:", transactionChanges);
1664
+ const state = getState();
1665
+ for (const listener of listeners) {
1666
+ try {
1667
+ listener(state, snapshotStates, transactionChanges[0]);
1668
+ } catch (error) {
1669
+ console.error(`Federation listener error:`, error);
1670
+ }
1671
+ }
1672
+ previousStates = state;
1673
+ }
1674
+ } catch (error) {
1675
+ isInTransaction = false;
1676
+ log("Async transaction failed, rolling back");
1677
+ for (const key in stores) {
1678
+ const store = stores[key];
1679
+ if (store) {
1680
+ store.setState(snapshotStates[key]);
1681
+ }
1682
+ }
1683
+ throw error;
1684
+ }
1685
+ },
1686
+ getStore(storeName) {
1687
+ return stores[storeName];
1688
+ },
1689
+ destroy() {
1690
+ log("Destroying federation");
1691
+ for (const unsubscribe of unsubscribers) {
1692
+ unsubscribe();
1693
+ }
1694
+ listeners.clear();
1695
+ }
1696
+ };
1697
+ }
1698
+ function createFederatedSelector(federation, selector2) {
1699
+ return () => selector2(federation.getState());
1700
+ }
1701
+ function createFederatedComputed(federation, selector2, equalityFn = Object.is) {
1702
+ let cachedValue = selector2(federation.getState());
1703
+ const listeners = /* @__PURE__ */ new Set();
1704
+ federation.subscribe((state) => {
1705
+ const newValue = selector2(state);
1706
+ if (!equalityFn(newValue, cachedValue)) {
1707
+ const prevValue = cachedValue;
1708
+ cachedValue = newValue;
1709
+ for (const listener of listeners) {
1710
+ listener(newValue, prevValue);
1711
+ }
1712
+ }
1713
+ });
1714
+ return {
1715
+ get() {
1716
+ return cachedValue;
1717
+ },
1718
+ subscribe(listener) {
1719
+ listeners.add(listener);
1720
+ return () => {
1721
+ listeners.delete(listener);
1722
+ };
1723
+ }
1724
+ };
1725
+ }
1726
+ function waitForFederated(federation, predicate, timeout) {
1727
+ return new Promise((resolve, reject) => {
1728
+ const state = federation.getState();
1729
+ if (predicate(state)) {
1730
+ resolve(state);
1731
+ return;
1732
+ }
1733
+ let timeoutId;
1734
+ let unsubscribe;
1735
+ const cleanup = () => {
1736
+ if (timeoutId) clearTimeout(timeoutId);
1737
+ if (unsubscribe) unsubscribe();
1738
+ };
1739
+ if (timeout) {
1740
+ timeoutId = setTimeout(() => {
1741
+ cleanup();
1742
+ reject(new Error(`waitForFederated timed out after ${timeout}ms`));
1743
+ }, timeout);
1744
+ }
1745
+ unsubscribe = federation.subscribe((state2) => {
1746
+ if (predicate(state2)) {
1747
+ cleanup();
1748
+ resolve(state2);
1749
+ }
1750
+ });
1751
+ });
1752
+ }
1753
+
1754
+ // src/plugins/persist.ts
1755
+ init_utils();
1756
+ var defaultStorage = {
1757
+ getItem: (key) => {
1758
+ if (typeof window === "undefined") return null;
1759
+ try {
866
1760
  return window.localStorage.getItem(key);
867
1761
  } catch {
868
1762
  return null;
@@ -903,36 +1797,133 @@ var sessionStorage = {
903
1797
  }
904
1798
  }
905
1799
  };
1800
+ function createDebounced2(fn, delay2) {
1801
+ let timeoutId = null;
1802
+ const debounced = ((...args) => {
1803
+ if (timeoutId) {
1804
+ clearTimeout(timeoutId);
1805
+ }
1806
+ timeoutId = setTimeout(() => {
1807
+ fn(...args);
1808
+ timeoutId = null;
1809
+ }, delay2);
1810
+ });
1811
+ debounced.cancel = () => {
1812
+ if (timeoutId) {
1813
+ clearTimeout(timeoutId);
1814
+ timeoutId = null;
1815
+ }
1816
+ };
1817
+ return debounced;
1818
+ }
906
1819
  function persist(options) {
907
- const { key, storage = defaultStorage, whitelist, blacklist } = options;
1820
+ const {
1821
+ key,
1822
+ storage = defaultStorage,
1823
+ whitelist,
1824
+ blacklist,
1825
+ partialize,
1826
+ merge: customMerge,
1827
+ version = 0,
1828
+ migrate,
1829
+ serialize = JSON.stringify,
1830
+ deserialize = JSON.parse,
1831
+ encrypt,
1832
+ decrypt,
1833
+ writeDebounce,
1834
+ onRehydrateStorage,
1835
+ onHydrationComplete,
1836
+ onPersistError
1837
+ } = options;
1838
+ let cancelDebounce = null;
908
1839
  return {
909
1840
  name: "persist",
910
1841
  version: "1.0.0",
911
1842
  install(store) {
912
1843
  try {
913
- const saved = storage.getItem(key);
1844
+ let saved = storage.getItem(key);
1845
+ if (saved && decrypt) {
1846
+ try {
1847
+ saved = decrypt(saved);
1848
+ } catch {
1849
+ saved = null;
1850
+ }
1851
+ }
914
1852
  if (saved) {
915
- const parsed = JSON.parse(saved);
916
- store.merge(parsed);
1853
+ let parsed;
1854
+ let persistedVersion = 0;
1855
+ try {
1856
+ const data = deserialize(saved);
1857
+ if (data && typeof data === "object" && "state" in data && "version" in data) {
1858
+ parsed = data.state;
1859
+ persistedVersion = data.version;
1860
+ } else {
1861
+ parsed = data;
1862
+ }
1863
+ } catch {
1864
+ parsed = deserialize(saved);
1865
+ }
1866
+ if (onRehydrateStorage) {
1867
+ onRehydrateStorage(parsed);
1868
+ }
1869
+ if (migrate && persistedVersion < version) {
1870
+ parsed = migrate(parsed, persistedVersion);
1871
+ }
1872
+ if (customMerge) {
1873
+ const currentState = store.getState();
1874
+ const mergedState = customMerge(parsed, currentState);
1875
+ store.setState(mergedState);
1876
+ } else {
1877
+ store.merge(parsed);
1878
+ }
1879
+ if (onHydrationComplete) {
1880
+ onHydrationComplete(store.getState());
1881
+ }
917
1882
  }
918
1883
  } catch (error) {
919
- console.error(`Failed to hydrate state from '${key}':`, error);
1884
+ if (onPersistError) {
1885
+ onPersistError(error);
1886
+ } else {
1887
+ console.error(`Failed to hydrate state from '${key}':`, error);
1888
+ }
920
1889
  }
921
- store.subscribe((state) => {
1890
+ const persistState = (state) => {
922
1891
  try {
923
1892
  let toSave = state;
924
- if (whitelist) {
1893
+ if (partialize) {
1894
+ toSave = partialize(state);
1895
+ } else if (whitelist) {
925
1896
  toSave = pick(state, whitelist);
926
1897
  } else if (blacklist) {
927
1898
  toSave = omit(state, blacklist);
928
1899
  }
929
- storage.setItem(key, JSON.stringify(toSave));
1900
+ const dataToStore = {
1901
+ state: toSave,
1902
+ version
1903
+ };
1904
+ let serialized = serialize(dataToStore);
1905
+ if (encrypt) {
1906
+ serialized = encrypt(serialized);
1907
+ }
1908
+ storage.setItem(key, serialized);
930
1909
  } catch (error) {
931
- console.error(`Failed to persist state to '${key}':`, error);
1910
+ if (onPersistError) {
1911
+ onPersistError(error);
1912
+ } else {
1913
+ console.error(`Failed to persist state to '${key}':`, error);
1914
+ }
932
1915
  }
933
- });
1916
+ };
1917
+ const debouncedPersist = writeDebounce && writeDebounce > 0 ? createDebounced2(persistState, writeDebounce) : persistState;
1918
+ if (writeDebounce && writeDebounce > 0) {
1919
+ cancelDebounce = () => debouncedPersist.cancel?.();
1920
+ }
1921
+ store.subscribe(debouncedPersist);
934
1922
  },
935
1923
  onDestroy() {
1924
+ if (cancelDebounce) {
1925
+ cancelDebounce();
1926
+ }
936
1927
  }
937
1928
  };
938
1929
  }
@@ -1262,31 +2253,888 @@ function selector(options) {
1262
2253
  };
1263
2254
  }
1264
2255
 
1265
- exports.StoreError = StoreError;
1266
- exports.StoreErrorCode = StoreErrorCode;
2256
+ // src/plugins/logger.ts
2257
+ var LOG_LEVELS = {
2258
+ debug: 0,
2259
+ info: 1,
2260
+ warn: 2,
2261
+ error: 3
2262
+ };
2263
+ var COLORS = {
2264
+ title: "#9E9E9E",
2265
+ prevState: "#9E9E9E",
2266
+ action: "#03A9F4",
2267
+ nextState: "#4CAF50",
2268
+ diff: {
2269
+ changed: "#2196F3"
2270
+ }
2271
+ };
2272
+ function formatTime(date) {
2273
+ const hours = date.getHours().toString().padStart(2, "0");
2274
+ const minutes = date.getMinutes().toString().padStart(2, "0");
2275
+ const seconds = date.getSeconds().toString().padStart(2, "0");
2276
+ const ms = date.getMilliseconds().toString().padStart(3, "0");
2277
+ return `${hours}:${minutes}:${seconds}.${ms}`;
2278
+ }
2279
+ function calculateDiff(prevState, nextState) {
2280
+ const diff = {};
2281
+ if (typeof prevState !== "object" || typeof nextState !== "object") {
2282
+ if (prevState !== nextState) {
2283
+ diff["value"] = { prev: prevState, next: nextState };
2284
+ }
2285
+ return diff;
2286
+ }
2287
+ if (prevState === null || nextState === null) {
2288
+ if (prevState !== nextState) {
2289
+ diff["value"] = { prev: prevState, next: nextState };
2290
+ }
2291
+ return diff;
2292
+ }
2293
+ const allKeys = /* @__PURE__ */ new Set([
2294
+ ...Object.keys(prevState),
2295
+ ...Object.keys(nextState)
2296
+ ]);
2297
+ for (const key of allKeys) {
2298
+ const prev = prevState[key];
2299
+ const next = nextState[key];
2300
+ if (prev !== next) {
2301
+ diff[key] = { prev, next };
2302
+ }
2303
+ }
2304
+ return diff;
2305
+ }
2306
+ function isBrowser() {
2307
+ return typeof window !== "undefined" && typeof window.document !== "undefined";
2308
+ }
2309
+ function logger(options = {}) {
2310
+ const {
2311
+ level = "debug",
2312
+ logger: customLogger = console,
2313
+ collapsed = true,
2314
+ diff = true,
2315
+ colors = isBrowser(),
2316
+ timestamp = true,
2317
+ filter,
2318
+ stateTransformer,
2319
+ actionName = "STATE_CHANGE",
2320
+ name = "Store",
2321
+ enabled = true
2322
+ } = options;
2323
+ const minLevel = LOG_LEVELS[level];
2324
+ return {
2325
+ name: "logger",
2326
+ version: "1.0.0",
2327
+ install(store) {
2328
+ if (!enabled) return;
2329
+ store.subscribe((state, prevState) => {
2330
+ if (filter && !filter(state, prevState)) {
2331
+ return;
2332
+ }
2333
+ if (LOG_LEVELS.info < minLevel) {
2334
+ return;
2335
+ }
2336
+ const now = /* @__PURE__ */ new Date();
2337
+ const action = typeof actionName === "function" ? actionName(state, prevState) : actionName;
2338
+ const displayPrevState = stateTransformer ? stateTransformer(prevState) : prevState;
2339
+ const displayNextState = stateTransformer ? stateTransformer(state) : state;
2340
+ const timeStr = timestamp ? ` @ ${formatTime(now)}` : "";
2341
+ const title = `${name} ${action}${timeStr}`;
2342
+ if (colors && isBrowser()) {
2343
+ logWithColors(
2344
+ customLogger,
2345
+ title,
2346
+ displayPrevState,
2347
+ displayNextState,
2348
+ collapsed,
2349
+ diff ? calculateDiff(prevState, state) : void 0
2350
+ );
2351
+ } else {
2352
+ logPlain(
2353
+ customLogger,
2354
+ title,
2355
+ displayPrevState,
2356
+ displayNextState,
2357
+ collapsed,
2358
+ diff ? calculateDiff(prevState, state) : void 0
2359
+ );
2360
+ }
2361
+ });
2362
+ }
2363
+ };
2364
+ }
2365
+ function logWithColors(log, title, prevState, nextState, collapsed, diff) {
2366
+ const titleStyle = `color: ${COLORS.title}; font-weight: lighter;`;
2367
+ const groupMethod = collapsed ? "groupCollapsed" : "group";
2368
+ log[groupMethod](`%c${title}`, titleStyle);
2369
+ log.log("%cprev state", `color: ${COLORS.prevState}; font-weight: bold;`, prevState);
2370
+ log.log("%cnext state", `color: ${COLORS.nextState}; font-weight: bold;`, nextState);
2371
+ if (diff && Object.keys(diff).length > 0) {
2372
+ log.log("%cdiff", `color: ${COLORS.action}; font-weight: bold;`);
2373
+ for (const [key, { prev, next }] of Object.entries(diff)) {
2374
+ log.log(
2375
+ ` %c${key}:`,
2376
+ `color: ${COLORS.diff.changed};`,
2377
+ prev,
2378
+ "\u2192",
2379
+ next
2380
+ );
2381
+ }
2382
+ }
2383
+ log.groupEnd();
2384
+ }
2385
+ function logPlain(log, title, prevState, nextState, collapsed, diff) {
2386
+ const hasGroupCollapsed = typeof log.groupCollapsed === "function";
2387
+ const groupMethod = collapsed && hasGroupCollapsed ? "groupCollapsed" : "group";
2388
+ const hasGroup = typeof log[groupMethod] === "function";
2389
+ if (hasGroup) {
2390
+ log[groupMethod](title);
2391
+ } else {
2392
+ log.log(`=== ${title} ===`);
2393
+ }
2394
+ log.log("prev state:", prevState);
2395
+ log.log("next state:", nextState);
2396
+ if (diff && Object.keys(diff).length > 0) {
2397
+ log.log("diff:");
2398
+ for (const [key, { prev, next }] of Object.entries(diff)) {
2399
+ log.log(` ${key}:`, prev, "\u2192", next);
2400
+ }
2401
+ }
2402
+ if (hasGroup) {
2403
+ log.groupEnd();
2404
+ } else {
2405
+ log.log("===");
2406
+ }
2407
+ }
2408
+ function createLogger(defaultOptions = {}) {
2409
+ return (options = {}) => logger({ ...defaultOptions, ...options });
2410
+ }
2411
+
2412
+ // src/plugins/effects.ts
2413
+ init_utils();
2414
+ function createDebounced3(fn, delay2) {
2415
+ let timeoutId = null;
2416
+ const debounced = ((...args) => {
2417
+ if (timeoutId) {
2418
+ clearTimeout(timeoutId);
2419
+ }
2420
+ timeoutId = setTimeout(() => {
2421
+ fn(...args);
2422
+ timeoutId = null;
2423
+ }, delay2);
2424
+ });
2425
+ debounced.cancel = () => {
2426
+ if (timeoutId) {
2427
+ clearTimeout(timeoutId);
2428
+ timeoutId = null;
2429
+ }
2430
+ };
2431
+ return debounced;
2432
+ }
2433
+ function effects(options) {
2434
+ const { effects: effectDefs, onError } = options;
2435
+ return {
2436
+ name: "effects",
2437
+ version: "1.0.0",
2438
+ install(store) {
2439
+ const cleanups = [];
2440
+ const effectCleanups = /* @__PURE__ */ new Map();
2441
+ for (let i = 0; i < effectDefs.length; i++) {
2442
+ const def = effectDefs[i];
2443
+ if (!def) continue;
2444
+ const {
2445
+ selector: selector2,
2446
+ effect,
2447
+ equalityFn = shallowEqual,
2448
+ fireImmediately = false,
2449
+ debounce,
2450
+ name
2451
+ } = def;
2452
+ let isActive = true;
2453
+ let prevValue = selector2(store.getState());
2454
+ const createUtils = () => ({
2455
+ getState: () => store.getState(),
2456
+ setState: (partial) => store.setState(partial),
2457
+ isActive: () => isActive,
2458
+ cancel: () => {
2459
+ isActive = false;
2460
+ },
2461
+ onlyIfActive: (fn) => {
2462
+ if (isActive) {
2463
+ return fn();
2464
+ }
2465
+ return void 0;
2466
+ }
2467
+ });
2468
+ const runEffect = async (value, prev) => {
2469
+ const prevCleanup = effectCleanups.get(i);
2470
+ if (prevCleanup) {
2471
+ try {
2472
+ prevCleanup();
2473
+ } catch (e) {
2474
+ }
2475
+ effectCleanups.delete(i);
2476
+ }
2477
+ isActive = true;
2478
+ try {
2479
+ const result = effect(value, prev, createUtils());
2480
+ if (result instanceof Promise) {
2481
+ const cleanup = await result;
2482
+ if (cleanup && isActive) {
2483
+ effectCleanups.set(i, cleanup);
2484
+ }
2485
+ } else if (result) {
2486
+ effectCleanups.set(i, result);
2487
+ }
2488
+ } catch (error) {
2489
+ if (onError) {
2490
+ onError(error, name);
2491
+ } else {
2492
+ console.error(`Effect error${name ? ` in '${name}'` : ""}:`, error);
2493
+ }
2494
+ }
2495
+ };
2496
+ const effectFn = debounce && debounce > 0 ? createDebounced3(runEffect, debounce) : runEffect;
2497
+ if (fireImmediately) {
2498
+ effectFn(prevValue, prevValue);
2499
+ }
2500
+ const unsubscribe = store.subscribe(
2501
+ selector2,
2502
+ (value, prev) => {
2503
+ if (!equalityFn(value, prev)) {
2504
+ prevValue = value;
2505
+ effectFn(value, prev);
2506
+ }
2507
+ },
2508
+ equalityFn
2509
+ );
2510
+ cleanups.push(() => {
2511
+ unsubscribe();
2512
+ isActive = false;
2513
+ if ("cancel" in effectFn) {
2514
+ effectFn.cancel();
2515
+ }
2516
+ const cleanup = effectCleanups.get(i);
2517
+ if (cleanup) {
2518
+ try {
2519
+ cleanup();
2520
+ } catch {
2521
+ }
2522
+ }
2523
+ });
2524
+ }
2525
+ store.__effectsCleanup = () => {
2526
+ for (const cleanup of cleanups) {
2527
+ cleanup();
2528
+ }
2529
+ effectCleanups.clear();
2530
+ };
2531
+ }
2532
+ };
2533
+ }
2534
+ function createEffect(name, selector2, effect, options = {}) {
2535
+ return {
2536
+ name,
2537
+ selector: selector2,
2538
+ effect,
2539
+ ...options
2540
+ };
2541
+ }
2542
+ function createSimpleEffect(effect, options = {}) {
2543
+ return {
2544
+ selector: (s) => s,
2545
+ effect,
2546
+ equalityFn: () => false,
2547
+ // Always run
2548
+ ...options
2549
+ };
2550
+ }
2551
+ function combineEffects(...effectDefs) {
2552
+ return {
2553
+ effects: effectDefs
2554
+ };
2555
+ }
2556
+ function createDebouncedEffect(delay2, selector2, effect, options = {}) {
2557
+ return {
2558
+ selector: selector2,
2559
+ effect,
2560
+ debounce: delay2,
2561
+ ...options
2562
+ };
2563
+ }
2564
+
2565
+ // src/plugins/validate.ts
2566
+ function isZodLike(schema) {
2567
+ return typeof schema === "object" && schema !== null && "safeParse" in schema && typeof schema.safeParse === "function";
2568
+ }
2569
+ function isYupLike(schema) {
2570
+ return typeof schema === "object" && schema !== null && "validateSync" in schema && typeof schema.validateSync === "function";
2571
+ }
2572
+ function extractPaths(state, paths) {
2573
+ const result = {};
2574
+ for (const path of paths) {
2575
+ if (path in state) {
2576
+ result[path] = state[path];
2577
+ }
2578
+ }
2579
+ return result;
2580
+ }
2581
+ function validateState(state, schema, paths) {
2582
+ const stateToValidate = paths ? extractPaths(state, paths) : state;
2583
+ if (typeof schema === "function") {
2584
+ const result = schema(stateToValidate);
2585
+ if (typeof result === "boolean") {
2586
+ return {
2587
+ valid: result,
2588
+ errors: result ? [] : [{ path: [], message: "Validation failed" }]
2589
+ };
2590
+ }
2591
+ if ("valid" in result && "errors" in result) {
2592
+ return result;
2593
+ }
2594
+ if (Array.isArray(result)) {
2595
+ return {
2596
+ valid: result.length === 0,
2597
+ errors: result
2598
+ };
2599
+ }
2600
+ return { valid: true, errors: [] };
2601
+ }
2602
+ if (isZodLike(schema)) {
2603
+ const result = schema.safeParse(stateToValidate);
2604
+ if (result.success) {
2605
+ return { valid: true, errors: [] };
2606
+ }
2607
+ const errors = (result.error?.issues || []).map((issue) => ({
2608
+ path: issue.path.map(String),
2609
+ message: issue.message,
2610
+ rule: issue.code
2611
+ }));
2612
+ return { valid: false, errors };
2613
+ }
2614
+ if (isYupLike(schema)) {
2615
+ try {
2616
+ schema.validateSync(stateToValidate, { abortEarly: false });
2617
+ return { valid: true, errors: [] };
2618
+ } catch (error) {
2619
+ const errors = [];
2620
+ if (error.inner && Array.isArray(error.inner)) {
2621
+ for (const err of error.inner) {
2622
+ errors.push({
2623
+ path: err.path ? err.path.split(".") : [],
2624
+ message: err.message,
2625
+ rule: err.type,
2626
+ value: err.value
2627
+ });
2628
+ }
2629
+ } else {
2630
+ errors.push({
2631
+ path: error.path ? error.path.split(".") : [],
2632
+ message: error.message || "Validation failed",
2633
+ rule: error.type
2634
+ });
2635
+ }
2636
+ return { valid: false, errors };
2637
+ }
2638
+ }
2639
+ return { valid: true, errors: [] };
2640
+ }
2641
+ function validate(options) {
2642
+ const {
2643
+ schema,
2644
+ on = "change",
2645
+ onError,
2646
+ throwOnError = false,
2647
+ paths,
2648
+ name = "validate"
2649
+ } = options;
2650
+ return {
2651
+ name,
2652
+ version: "1.0.0",
2653
+ install(store) {
2654
+ let currentErrors = [];
2655
+ const doValidate = () => {
2656
+ const state = store.getState();
2657
+ const result = validateState(state, schema, paths);
2658
+ currentErrors = result.errors;
2659
+ if (!result.valid) {
2660
+ if (onError) {
2661
+ onError(result.errors);
2662
+ }
2663
+ if (throwOnError) {
2664
+ const errorMessages = result.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
2665
+ throw new Error(`Validation failed: ${errorMessages}`);
2666
+ }
2667
+ }
2668
+ return result;
2669
+ };
2670
+ if (on === "change") {
2671
+ store.subscribe(() => {
2672
+ doValidate();
2673
+ });
2674
+ }
2675
+ const validationAPI = {
2676
+ validate: doValidate,
2677
+ isValid: () => currentErrors.length === 0,
2678
+ getErrors: () => [...currentErrors],
2679
+ clearErrors: () => {
2680
+ currentErrors = [];
2681
+ }
2682
+ };
2683
+ Object.assign(store, validationAPI);
2684
+ }
2685
+ };
2686
+ }
2687
+ function createValidator(predicate, message) {
2688
+ return (state) => {
2689
+ const valid = predicate(state);
2690
+ return {
2691
+ valid,
2692
+ errors: valid ? [] : [{ path: [], message }]
2693
+ };
2694
+ };
2695
+ }
2696
+ function combineValidators(...validators) {
2697
+ return (state) => {
2698
+ const allErrors = [];
2699
+ for (const validator of validators) {
2700
+ const result = validator(state);
2701
+ if (typeof result === "boolean") {
2702
+ if (!result) {
2703
+ allErrors.push({ path: [], message: "Validation failed" });
2704
+ }
2705
+ } else if ("valid" in result && "errors" in result) {
2706
+ allErrors.push(...result.errors);
2707
+ } else if (Array.isArray(result)) {
2708
+ allErrors.push(...result);
2709
+ }
2710
+ }
2711
+ return {
2712
+ valid: allErrors.length === 0,
2713
+ errors: allErrors
2714
+ };
2715
+ };
2716
+ }
2717
+ function createFieldValidator(field, predicate, message) {
2718
+ return (state) => {
2719
+ const valid = predicate(state[field], state);
2720
+ return {
2721
+ valid,
2722
+ errors: valid ? [] : [{ path: [String(field)], message, value: state[field] }]
2723
+ };
2724
+ };
2725
+ }
2726
+ function createAsyncValidator(validator) {
2727
+ return async (state) => {
2728
+ const errors = await validator(state);
2729
+ return {
2730
+ valid: errors.length === 0,
2731
+ errors
2732
+ };
2733
+ };
2734
+ }
2735
+
2736
+ // src/index.ts
2737
+ init_utils();
2738
+
2739
+ // src/testing.ts
2740
+ init_store();
2741
+ init_utils();
2742
+ function createMockStorage() {
2743
+ const storage = /* @__PURE__ */ new Map();
2744
+ return {
2745
+ getItem(key) {
2746
+ return storage.get(key) ?? null;
2747
+ },
2748
+ setItem(key, value) {
2749
+ storage.set(key, value);
2750
+ },
2751
+ removeItem(key) {
2752
+ storage.delete(key);
2753
+ },
2754
+ clear() {
2755
+ storage.clear();
2756
+ },
2757
+ getAll() {
2758
+ const result = {};
2759
+ for (const [key, value] of storage) {
2760
+ result[key] = value;
2761
+ }
2762
+ return result;
2763
+ }
2764
+ };
2765
+ }
2766
+ function spyOnStore(store) {
2767
+ const changes = [];
2768
+ const waiters = [];
2769
+ const unsubscribe = store.subscribe((state, prevState) => {
2770
+ changes.push({
2771
+ state,
2772
+ prevState,
2773
+ timestamp: Date.now()
2774
+ });
2775
+ for (let i = waiters.length - 1; i >= 0; i--) {
2776
+ const waiter = waiters[i];
2777
+ if (waiter && waiter.predicate(state)) {
2778
+ waiter.resolve(state);
2779
+ waiters.splice(i, 1);
2780
+ }
2781
+ }
2782
+ });
2783
+ return {
2784
+ changes,
2785
+ lastChange: () => changes[changes.length - 1],
2786
+ lastState: () => changes[changes.length - 1]?.state,
2787
+ reset: () => {
2788
+ changes.length = 0;
2789
+ },
2790
+ unsubscribe,
2791
+ waitFor: (predicate, timeout = 5e3) => {
2792
+ return new Promise((resolve, reject) => {
2793
+ const current = store.getState();
2794
+ if (predicate(current)) {
2795
+ resolve(current);
2796
+ return;
2797
+ }
2798
+ const waiter = { resolve, predicate };
2799
+ waiters.push(waiter);
2800
+ const timeoutId = setTimeout(() => {
2801
+ const index = waiters.indexOf(waiter);
2802
+ if (index >= 0) {
2803
+ waiters.splice(index, 1);
2804
+ reject(new Error(`waitFor timeout after ${timeout}ms`));
2805
+ }
2806
+ }, timeout);
2807
+ const originalResolve = waiter.resolve;
2808
+ waiter.resolve = (state) => {
2809
+ clearTimeout(timeoutId);
2810
+ originalResolve(state);
2811
+ };
2812
+ });
2813
+ },
2814
+ waitForChanges: (count, timeout = 5e3) => {
2815
+ return new Promise((resolve, reject) => {
2816
+ const startCount = changes.length;
2817
+ const check = () => {
2818
+ if (changes.length >= startCount + count) {
2819
+ return changes.slice(startCount, startCount + count);
2820
+ }
2821
+ return null;
2822
+ };
2823
+ const immediate = check();
2824
+ if (immediate) {
2825
+ resolve(immediate);
2826
+ return;
2827
+ }
2828
+ const intervalId = setInterval(() => {
2829
+ const result = check();
2830
+ if (result) {
2831
+ clearInterval(intervalId);
2832
+ clearTimeout(timeoutId);
2833
+ resolve(result);
2834
+ }
2835
+ }, 10);
2836
+ const timeoutId = setTimeout(() => {
2837
+ clearInterval(intervalId);
2838
+ reject(new Error(`waitForChanges timeout after ${timeout}ms`));
2839
+ }, timeout);
2840
+ });
2841
+ }
2842
+ };
2843
+ }
2844
+ function assertState(store) {
2845
+ return {
2846
+ toEqual: (expected) => {
2847
+ const state = store.getState();
2848
+ for (const [key, value] of Object.entries(expected)) {
2849
+ if (state[key] !== value) {
2850
+ throw new Error(
2851
+ `Expected state.${key} to be ${JSON.stringify(value)}, but got ${JSON.stringify(state[key])}`
2852
+ );
2853
+ }
2854
+ }
2855
+ },
2856
+ toHaveSelected: (selector2, expected) => {
2857
+ const actual = selector2(store.getState());
2858
+ if (!shallowEqual(actual, expected)) {
2859
+ throw new Error(
2860
+ `Expected selector to return ${JSON.stringify(expected)}, but got ${JSON.stringify(actual)}`
2861
+ );
2862
+ }
2863
+ },
2864
+ toMatch: (predicate) => {
2865
+ const state = store.getState();
2866
+ if (!predicate(state)) {
2867
+ throw new Error(
2868
+ `State did not match predicate: ${JSON.stringify(state)}`
2869
+ );
2870
+ }
2871
+ }
2872
+ };
2873
+ }
2874
+ function createTestStore(options) {
2875
+ const { initialState, spy: enableSpy = true } = options;
2876
+ const store = createStore(initialState);
2877
+ const spy = enableSpy ? spyOnStore(store) : void 0;
2878
+ const assert = assertState(store);
2879
+ return {
2880
+ store,
2881
+ spy,
2882
+ assert,
2883
+ reset: () => {
2884
+ store.reset();
2885
+ spy?.reset();
2886
+ },
2887
+ destroy: () => {
2888
+ spy?.unsubscribe();
2889
+ store.destroy();
2890
+ }
2891
+ };
2892
+ }
2893
+ function delay(ms) {
2894
+ return new Promise((resolve) => setTimeout(resolve, ms));
2895
+ }
2896
+ async function flushMicrotasks(fn) {
2897
+ if (fn) {
2898
+ fn();
2899
+ }
2900
+ await Promise.resolve();
2901
+ }
2902
+ function mockAction(fn) {
2903
+ const calls = [];
2904
+ const mocked = ((...args) => {
2905
+ calls.push(args);
2906
+ return fn(...args);
2907
+ });
2908
+ Object.defineProperty(mocked, "callCount", {
2909
+ get: () => calls.length
2910
+ });
2911
+ mocked.calls = calls;
2912
+ mocked.reset = () => {
2913
+ calls.length = 0;
2914
+ };
2915
+ return mocked;
2916
+ }
2917
+ function snapshot(store) {
2918
+ return JSON.parse(JSON.stringify(store.getState()));
2919
+ }
2920
+ function stateDiff(before, after) {
2921
+ const diff = {};
2922
+ const allKeys = /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)]);
2923
+ for (const key of allKeys) {
2924
+ if (!shallowEqual(before[key], after[key])) {
2925
+ diff[key] = { before: before[key], after: after[key] };
2926
+ }
2927
+ }
2928
+ return diff;
2929
+ }
2930
+
2931
+ // src/compat/middleware.ts
2932
+ function toMiddlewareApi(store) {
2933
+ return {
2934
+ setState: (partial, replace) => {
2935
+ if (typeof partial === "function") {
2936
+ const currentState = store.getState();
2937
+ const newPartial = partial(currentState);
2938
+ if (replace) {
2939
+ store.setState(newPartial);
2940
+ } else {
2941
+ store.merge(newPartial);
2942
+ }
2943
+ } else {
2944
+ if (replace) {
2945
+ store.setState(partial);
2946
+ } else {
2947
+ store.merge(partial);
2948
+ }
2949
+ }
2950
+ },
2951
+ getState: () => store.getState(),
2952
+ subscribe: (listener) => store.subscribe(listener),
2953
+ destroy: () => store.destroy()
2954
+ };
2955
+ }
2956
+ function middlewareCompat(middleware, options) {
2957
+ return {
2958
+ name: "middleware-compat",
2959
+ version: "1.0.0",
2960
+ install(store) {
2961
+ const api = toMiddlewareApi(store);
2962
+ const stateCreator = (set, get) => {
2963
+ return get();
2964
+ };
2965
+ const enhancedCreator = middleware(stateCreator);
2966
+ const enhancedState = enhancedCreator(api.setState, api.getState, api);
2967
+ if (enhancedState && typeof enhancedState === "object") {
2968
+ const currentState = store.getState();
2969
+ const stateOnly = {};
2970
+ for (const key in enhancedState) {
2971
+ const value = enhancedState[key];
2972
+ if (typeof value !== "function") {
2973
+ stateOnly[key] = value;
2974
+ }
2975
+ }
2976
+ if (Object.keys(stateOnly).length > 0) {
2977
+ const hasChanges = Object.keys(stateOnly).some(
2978
+ (key) => currentState[key] !== stateOnly[key]
2979
+ );
2980
+ if (hasChanges) {
2981
+ store.merge(stateOnly);
2982
+ }
2983
+ }
2984
+ }
2985
+ }
2986
+ };
2987
+ }
2988
+ function createWithMiddleware(creator) {
2989
+ const { createStore: createStore2 } = (init_store(), __toCommonJS(store_exports));
2990
+ let currentState = null;
2991
+ let storeRef = null;
2992
+ const set = (partial, replace) => {
2993
+ if (!storeRef) {
2994
+ throw new Error("Store not initialized");
2995
+ }
2996
+ if (typeof partial === "function") {
2997
+ const newPartial = partial(storeRef.getState());
2998
+ if (replace) {
2999
+ storeRef.setState(newPartial);
3000
+ } else {
3001
+ storeRef.merge(newPartial);
3002
+ }
3003
+ } else {
3004
+ if (replace) {
3005
+ storeRef.setState(partial);
3006
+ } else {
3007
+ storeRef.merge(partial);
3008
+ }
3009
+ }
3010
+ };
3011
+ const get = () => {
3012
+ if (storeRef) {
3013
+ return storeRef.getState();
3014
+ }
3015
+ if (currentState) {
3016
+ return currentState;
3017
+ }
3018
+ throw new Error("Store not initialized");
3019
+ };
3020
+ const placeholderApi = {
3021
+ setState: set,
3022
+ getState: get,
3023
+ subscribe: () => () => {
3024
+ }
3025
+ };
3026
+ currentState = creator(set, get, placeholderApi);
3027
+ storeRef = createStore2(currentState);
3028
+ const api = {
3029
+ setState: (partial, replace) => {
3030
+ if (typeof partial === "function") {
3031
+ const newPartial = partial(storeRef.getState());
3032
+ if (replace) {
3033
+ storeRef.setState(newPartial);
3034
+ } else {
3035
+ storeRef.merge(newPartial);
3036
+ }
3037
+ } else {
3038
+ if (replace) {
3039
+ storeRef.setState(partial);
3040
+ } else {
3041
+ storeRef.merge(partial);
3042
+ }
3043
+ }
3044
+ },
3045
+ getState: () => storeRef.getState(),
3046
+ subscribe: (listener) => storeRef.subscribe(listener),
3047
+ destroy: () => storeRef.destroy(),
3048
+ use: (plugin) => {
3049
+ storeRef.use(plugin);
3050
+ return api;
3051
+ }
3052
+ };
3053
+ return api;
3054
+ }
3055
+ function createSimpleMiddleware(name, enhancer) {
3056
+ const middleware = enhancer;
3057
+ Object.defineProperty(middleware, "name", { value: name });
3058
+ return middleware;
3059
+ }
3060
+ function compose(...middlewares) {
3061
+ return (creator) => {
3062
+ return middlewares.reduceRight((acc, middleware) => {
3063
+ return middleware(acc);
3064
+ }, creator);
3065
+ };
3066
+ }
3067
+
3068
+ exports.assertState = assertState;
1267
3069
  exports.batch = batch;
3070
+ exports.combineComputed = combineComputed;
3071
+ exports.combineEffects = combineEffects;
3072
+ exports.combineSlices = combineSlices;
3073
+ exports.combineValidators = combineValidators;
3074
+ exports.compose = compose;
3075
+ exports.computed = computed;
3076
+ exports.createAsyncValidator = createAsyncValidator;
3077
+ exports.createDebouncedEffect = createDebouncedEffect;
3078
+ exports.createEffect = createEffect;
3079
+ exports.createFederatedComputed = createFederatedComputed;
3080
+ exports.createFederatedSelector = createFederatedSelector;
3081
+ exports.createFederation = createFederation;
3082
+ exports.createFieldValidator = createFieldValidator;
3083
+ exports.createLogger = createLogger;
3084
+ exports.createMockStorage = createMockStorage;
3085
+ exports.createNamespacedSlice = createNamespacedSlice;
3086
+ exports.createSimpleEffect = createSimpleEffect;
3087
+ exports.createSimpleMiddleware = createSimpleMiddleware;
3088
+ exports.createSlice = createSlice;
1268
3089
  exports.createStorage = createStorage;
1269
3090
  exports.createStore = createStore;
3091
+ exports.createSubscriber = createSubscriber;
3092
+ exports.createTestStore = createTestStore;
3093
+ exports.createValidator = createValidator;
3094
+ exports.createWithMiddleware = createWithMiddleware;
1270
3095
  exports.deepClone = deepClone;
1271
3096
  exports.deepEqual = deepEqual;
1272
3097
  exports.deepMerge = deepMerge;
3098
+ exports.delay = delay;
1273
3099
  exports.devtools = devtools;
3100
+ exports.effects = effects;
3101
+ exports.extendStore = extendStore;
3102
+ exports.flushMicrotasks = flushMicrotasks;
1274
3103
  exports.hasHistory = hasHistory;
1275
3104
  exports.history = history;
1276
3105
  exports.identity = identity;
1277
3106
  exports.immer = immer;
1278
3107
  exports.isFunction = isFunction;
3108
+ exports.logger = logger;
3109
+ exports.memoizeSelector = memoizeSelector;
3110
+ exports.middlewareCompat = middlewareCompat;
3111
+ exports.mockAction = mockAction;
1279
3112
  exports.omit = omit;
1280
3113
  exports.persist = persist;
1281
3114
  exports.pick = pick;
1282
3115
  exports.produce = produce;
3116
+ exports.resetSlices = resetSlices;
1283
3117
  exports.selector = selector;
1284
3118
  exports.sessionStorage = sessionStorage;
1285
3119
  exports.shallowEqual = shallowEqual;
3120
+ exports.snapshot = snapshot;
3121
+ exports.spyOnStore = spyOnStore;
3122
+ exports.stateDiff = stateDiff;
3123
+ exports.subscribeOnce = subscribeOnce;
3124
+ exports.subscribeToMany = subscribeToMany;
3125
+ exports.subscribeWithOptions = subscribeWithOptions;
1286
3126
  exports.sync = sync;
3127
+ exports.toMiddlewareApi = toMiddlewareApi;
1287
3128
  exports.triggerSync = triggerSync;
1288
3129
  exports.useAction = useAction;
1289
3130
  exports.useCreateStore = useCreateStore;
3131
+ exports.useSetState = useSetState;
3132
+ exports.useShallow = useShallow;
1290
3133
  exports.useStore = useStore;
3134
+ exports.useStoreActions = useStoreActions;
3135
+ exports.useStoreSelector = useStoreSelector;
3136
+ exports.useTransientSubscribe = useTransientSubscribe;
3137
+ exports.validate = validate;
3138
+ exports.waitForFederated = waitForFederated;
1291
3139
  //# sourceMappingURL=index.cjs.map
1292
3140
  //# sourceMappingURL=index.cjs.map