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