@but212/atom-effect 0.8.4 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,17 +1,10 @@
1
- # atom-effect
1
+ # @but212/atom-effect
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@but212/atom-effect.svg)](https://www.npmjs.com/package/@but212/atom-effect)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue.svg)](https://www.typescriptlang.org/)
6
6
 
7
- A lightweight, high-performance reactive state management library for TypeScript/JavaScript with zero dependencies.
8
-
9
- ## Features
10
-
11
- - **Core Primitives**: `atom`, `computed`, `effect`, `batch`, `untracked`
12
- - **Zero Dependencies** - Minimal footprint
13
- - **Full TypeScript Support** - Strict type checking
14
- - **Developer Friendly** - Circular dependency detection, infinite loop protection, auto debug IDs
7
+ Lightweight, high-performance reactive state management.
15
8
 
16
9
  ## Installation
17
10
 
@@ -19,143 +12,125 @@ A lightweight, high-performance reactive state management library for TypeScript
19
12
  npm i @but212/atom-effect
20
13
  ```
21
14
 
22
- ## Quick Start
15
+ ## Core API
23
16
 
24
- ```typescript
25
- import { atom, computed, effect, batch } from '@but212/atom-effect';
17
+ ### `atom(value)`
26
18
 
27
- // Create reactive state
19
+ Creates a mutable state container.
20
+
21
+ - **read**: `atom.value` (tracks dependency)
22
+ - **write**: `atom.value = newValue` (triggers effects)
23
+ - **peek**: `atom.peek()` (read without tracking)
24
+
25
+ ```typescript
28
26
  const count = atom(0);
29
- const name = atom('Alice');
27
+ count.value++;
28
+ console.log(count.value);
29
+ ```
30
30
 
31
- // Derived state
32
- const greeting = computed(() => `Hello, ${name.value}! Count: ${count.value}`);
31
+ ### `computed(fn)`
33
32
 
34
- // Side effects with automatic cleanup
35
- const effectObj = effect(() => {
36
- console.log(greeting.value);
37
- });
33
+ Creates a derived value that automatically updates when dependencies change.
38
34
 
39
- // Batch updates for performance
40
- batch(() => {
41
- count.value = 1;
42
- name.value = 'Bob';
43
- }); // Effect runs only once
35
+ - Lazy evaluation (only computes when read or needed by an effect).
36
+ - Caches result until dependencies change.
44
37
 
45
- effectObj.dispose();
38
+ ```typescript
39
+ const double = computed(() => count.value * 2);
46
40
  ```
47
41
 
48
- ## Core API
42
+ ### `effect(fn)`
49
43
 
50
- ### `atom(initialValue, options?)`
44
+ Runs a function immediately and re-runs it whenever its dependencies change.
51
45
 
52
- Creates reactive state with automatic dependency tracking.
46
+ - Returns a `dispose` function to stop the effect.
53
47
 
54
48
  ```typescript
55
- const count = atom(0);
56
-
57
- count.value = 1; // Write
58
- console.log(count.value); // Read (tracks dependencies)
59
- console.log(count.peek()); // Read without tracking
60
-
61
- const unsubscribe = count.subscribe((newVal, oldVal) => {
62
- console.log(`${oldVal} → ${newVal}`);
49
+ const stop = effect(() => {
50
+ console.log(count.value);
63
51
  });
52
+ stop();
64
53
  ```
65
54
 
66
- **Options:** `{ sync: boolean }` - Synchronous updates (default: `false`)
67
-
68
- ### `computed(fn, options?)`
55
+ ### `batch(fn)`
69
56
 
70
- Creates derived state that recomputes when dependencies change.
57
+ Delays effect execution until the function completes.
71
58
 
72
59
  ```typescript
73
- const count = atom(0);
74
- const doubled = computed(() => count.value * 2);
75
-
76
- // Async computed
77
- const userId = atom(1);
78
- const userData = computed(
79
- async () => {
80
- const res = await fetch(`/api/users/${userId.value}`);
81
- return res.json();
82
- },
83
- { defaultValue: null }
84
- );
60
+ batch(() => {
61
+ count.value = 1;
62
+ count.value = 2;
63
+ });
64
+ // Effects run once after the batch
85
65
  ```
86
66
 
87
- **Options:**
88
-
89
- - `equal` - Custom equality function (default: `Object.is`)
90
- - `defaultValue` - Required for async functions
91
- - `lazy` - Compute only when accessed (default: `true`)
92
- - `onError` - Error callback for computation failures
93
-
94
- ### `effect(fn)`
67
+ ### `untracked(fn)`
95
68
 
96
- Runs side effects with automatic dependency tracking and cleanup.
69
+ Runs a function without tracking any dependencies accessed within it.
97
70
 
98
71
  ```typescript
99
- const count = atom(0);
100
-
101
- const effectObj = effect(() => {
102
- console.log(`Count: ${count.value}`);
103
-
104
- // Optional cleanup
105
- return () => console.log('cleanup');
72
+ computed(() => {
73
+ // `count` is not tracked as a dependency here
74
+ return untracked(() => count.value * 2);
106
75
  });
107
-
108
- effectObj.dispose(); // Stop the effect
109
76
  ```
110
77
 
111
- **Options:**
78
+ ## API Reference
112
79
 
113
- - `sync` - Run synchronously (default: `false`)
114
- - `maxExecutionsPerFlush` - Maximum executions per flush cycle to prevent infinite loops (default: `SCHEDULER_CONFIG.MAX_EXECUTIONS_PER_FLUSH`)
80
+ ### Detailed Options
115
81
 
116
- ### `batch(fn)`
82
+ #### `atom(initialValue, options?)`
117
83
 
118
- Batches multiple updates to run effects only once.
84
+ - `name`: (string) Debug name.
119
85
 
120
- ```typescript
121
- const firstName = atom('John');
122
- const lastName = atom('Doe');
123
- const fullName = computed(() => `${firstName.value} ${lastName.value}`);
86
+ #### `computed(fn, options?)`
124
87
 
125
- effect(() => console.log(fullName.value));
88
+ - `equal`: (fn) Comparison function to skip re-computes.
89
+ - `defaultValue`: (any) Value to return when pending/error.
90
+ - `lazy`: (boolean) If true, defers evaluation until read.
126
91
 
127
- // Without batch - logs twice
128
- firstName.value = 'Jane';
129
- lastName.value = 'Smith';
92
+ #### `effect(fn, options?)`
130
93
 
131
- // With batch - logs once
132
- batch(() => {
133
- firstName.value = 'Alice';
134
- lastName.value = 'Johnson';
135
- });
94
+ - `sync`: (boolean) Runs synchronously on change.
95
+ - `onError`: (fn) Async error handler.
96
+ - `trackModifications`: (boolean) Warns on self-writes.
97
+
98
+ ### Advanced Usage
99
+
100
+ #### Async Computed
101
+
102
+ ```typescript
103
+ const userId = atom(1);
104
+ const user = computed(async () => {
105
+ const res = await fetch(`/api/users/${userId.value}`);
106
+ return res.json();
107
+ }, { defaultValue: { loading: true } });
136
108
  ```
137
109
 
138
- ### `untracked(fn)`
110
+ ## Utilities & Development
139
111
 
140
- Executes function without tracking dependencies.
112
+ ### Type Guards
141
113
 
142
114
  ```typescript
143
- const a = atom(1);
144
- const b = atom(2);
115
+ import { isAtom, isComputed, isReactive } from '@but212/atom-effect';
145
116
 
146
- const sum = computed(() => {
147
- const aValue = a.value; // Tracked
148
- const bValue = untracked(() => b.value); // NOT tracked
149
- return aValue + bValue;
150
- });
117
+ isAtom(count); // true
118
+ isReactive(double); // true
151
119
  ```
152
120
 
153
- ## Utilities
121
+ ### Development Commands
154
122
 
155
- Type guards (`isAtom`, `isComputed`, `isEffect`), configuration constants (`DEBUG_CONFIG`, `POOL_CONFIG`, `SCHEDULER_CONFIG`), and error classes (`AtomError`, `ComputedError`, `EffectError`) are available.
123
+ ```bash
124
+ pnpm test # Run unit tests
125
+ pnpm bench # Run benchmarks
126
+ pnpm lint # Run lint checks
127
+ pnpm build # Build production bundle
128
+ ```
156
129
 
157
130
  ## Performance
158
131
 
132
+ Verified benchmarks vs object pooling and lazy evaluation optimizations.
133
+
159
134
  | Operation | Performance |
160
135
  | --- | --- |
161
136
  | Atom creation | ~4.95M ops/sec |
@@ -163,24 +138,9 @@ Type guards (`isAtom`, `isComputed`, `isEffect`), configuration constants (`DEBU
163
138
  | Computed creation | ~1.75M ops/sec |
164
139
  | Computed recomputation | ~556K ops/sec |
165
140
  | Effect execution | ~4.57M ops/sec |
166
- | Batch update (2 atoms) | ~3.97M ops/sec |
167
- | Untracked read | ~6.01M ops/sec |
141
+ | Batched updates | ~3.97M ops/sec |
168
142
  | Deep chain (100 levels) | ~8.7K ops/sec |
169
143
 
170
- See [docs/BENCHMARKS.md](./docs/BENCHMARKS.md) for details.
171
-
172
- ## Development
173
-
174
- ```bash
175
- pnpm install # Install dependencies
176
- pnpm build # Build
177
- pnpm test # Run tests (299 test cases)
178
- pnpm test:coverage # With coverage
179
- pnpm bench # Run benchmarks
180
- pnpm typecheck # Type checking
181
- pnpm lint # Lint code
182
- ```
183
-
184
144
  ## Contributing
185
145
 
186
146
  Contributions are welcome! Feel free to open an issue or submit a pull request.
@@ -1,2 +1,2 @@
1
- (function(c,O){typeof exports=="object"&&typeof module<"u"?O(exports):typeof define=="function"&&define.amd?define(["exports"],O):(c=typeof globalThis<"u"?globalThis:c||self,O(c.AtomEffect={}))})(this,(function(c){"use strict";const O={ONE_SECOND_MS:1e3},U={IDLE:"idle",PENDING:"pending",RESOLVED:"resolved",REJECTED:"rejected"},x={DISPOSED:1,EXECUTING:2},u={DIRTY:1,IDLE:2,PENDING:4,RESOLVED:8,REJECTED:16,RECOMPUTING:32,HAS_ERROR:64},ie={MAX_SIZE:1e3,WARMUP_SIZE:100},g={MAX_EXECUTIONS_PER_SECOND:1e3,CLEANUP_THRESHOLD:1e3,MAX_EXECUTIONS_PER_EFFECT:100,MAX_EXECUTIONS_PER_FLUSH:1e4,MAX_FLUSH_ITERATIONS:1e3,MIN_FLUSH_ITERATIONS:10},w={MAX_DEPENDENCIES:1e3,WARN_INFINITE_LOOP:!0},I=1073741823,l=typeof process<"u"&&process.env&&process.env.NODE_ENV!=="production",ne=Object.freeze([]);class d extends Error{constructor(e,t=null,s=!0){super(e),this.name="AtomError",this.cause=t,this.recoverable=s,this.timestamp=new Date}}class m extends d{constructor(e,t=null){super(e,t,!0),this.name="ComputedError"}}class b extends d{constructor(e,t=null){super(e,t,!1),this.name="EffectError"}}class F extends d{constructor(e,t=null){super(e,t,!1),this.name="SchedulerError"}}const h={COMPUTED_MUST_BE_FUNCTION:"Computed function must be a function",COMPUTED_SUBSCRIBER_MUST_BE_FUNCTION:"Subscriber listener must be a function or Subscriber object",COMPUTED_ASYNC_PENDING_NO_DEFAULT:"Async computation is pending. No default value provided",COMPUTED_COMPUTATION_FAILED:"Computed computation failed",COMPUTED_ASYNC_COMPUTATION_FAILED:"Async computed computation failed",COMPUTED_DEPENDENCY_SUBSCRIPTION_FAILED:"Failed to subscribe to dependency",ATOM_SUBSCRIBER_MUST_BE_FUNCTION:"Subscription listener must be a function or Subscriber object",ATOM_SUBSCRIBER_EXECUTION_FAILED:"Error occurred while executing atom subscribers",ATOM_INDIVIDUAL_SUBSCRIBER_FAILED:"Error during individual atom subscriber execution",EFFECT_MUST_BE_FUNCTION:"Effect function must be a function",EFFECT_EXECUTION_FAILED:"Effect execution failed",EFFECT_CLEANUP_FAILED:"Effect cleanup function execution failed",LARGE_DEPENDENCY_GRAPH:i=>`Large dependency graph detected: ${i} dependencies`,UNSUBSCRIBE_NON_EXISTENT:"Attempted to unsubscribe a non-existent listener",CALLBACK_ERROR_IN_ERROR_HANDLER:"Error occurred during onError callback execution"},B=Symbol("debugName"),re=Symbol("id"),k=Symbol("type"),z=Symbol("noDefaultValue");function oe(i){return"dependencies"in i&&Array.isArray(i.dependencies)}let G=0;function X(i,e,t){if(i._visitedEpoch!==t){if(i._visitedEpoch=t,i===e)throw new m("Indirect circular dependency detected");if(oe(i)){const s=i.dependencies;for(let n=0;n<s.length;n++){const r=s[n];r&&X(r,e,t)}}}}const f={enabled:typeof process<"u"&&process.env?.NODE_ENV==="development",maxDependencies:w.MAX_DEPENDENCIES,warnInfiniteLoop:w.WARN_INFINITE_LOOP,warn(i,e){this.enabled&&i&&console.warn(`[Atom Effect] ${e}`)},checkCircular(i,e){if(i===e)throw new m("Direct circular dependency detected");this.enabled&&(G++,X(i,e,G))},attachDebugInfo(i,e,t){if(!this.enabled)return;const s=i;s[B]=`${e}_${t}`,s[re]=t,s[k]=e},getDebugName(i){if(i!=null&&B in i)return i[B]},getDebugType(i){if(i!=null&&k in i)return i[k]}};let ce=1;const ue=()=>ce++;class Y{constructor(){this.id=ue()&I,this.flags=0}}class H extends Y{constructor(){super(),this.version=0,this._lastSeenEpoch=-1}subscribe(e){if(typeof e=="object"&&e!==null&&"execute"in e)return this._objectSubscribers.add(e);if(typeof e!="function")throw new d(h.ATOM_SUBSCRIBER_MUST_BE_FUNCTION);return this._functionSubscribers.add(e)}subscriberCount(){return this._functionSubscribers.size+this._objectSubscribers.size}_notifySubscribers(e,t){this._functionSubscribers.forEachSafe(s=>s(e,t),s=>console.error(new d(h.ATOM_INDIVIDUAL_SUBSCRIBER_FAILED,s))),this._objectSubscribers.forEachSafe(s=>s.execute(),s=>console.error(new d(h.ATOM_INDIVIDUAL_SUBSCRIBER_FAILED,s)))}}let P=0;function $(){return P=(P+1|0)&I,P}function he(){return P}let v=0,q=0,L=!1;function J(){return L?(l&&console.warn("Warning: startFlush() called during flush - ignored to prevent infinite loop detection bypass"),!1):(L=!0,v=v+1&I,q=0,!0)}function Q(){L=!1}function _e(){return L?++q:0}class ae{constructor(){this.queueA=[],this.queueB=[],this.queue=this.queueA,this.queueSize=0,this._epoch=0,this.isProcessing=!1,this.isBatching=!1,this.batchDepth=0,this.batchQueue=[],this.batchQueueSize=0,this.isFlushingSync=!1,this.maxFlushIterations=g.MAX_FLUSH_ITERATIONS}get phase(){return this.isProcessing||this.isFlushingSync?2:this.isBatching?1:0}schedule(e){if(typeof e!="function")throw new F("Scheduler callback must be a function");e._nextEpoch!==this._epoch&&(e._nextEpoch=this._epoch,this.isBatching||this.isFlushingSync?this.batchQueue[this.batchQueueSize++]=e:(this.queue[this.queueSize++]=e,this.isProcessing||this.flush()))}flush(){if(this.isProcessing||this.queueSize===0)return;this.isProcessing=!0;const e=this.queue,t=this.queueSize;this.queue=this.queue===this.queueA?this.queueB:this.queueA,this.queueSize=0,this._epoch++,queueMicrotask(()=>{const s=J();this._processJobs(e,t),this.isProcessing=!1,s&&Q(),this.queueSize>0&&!this.isBatching&&this.flush()})}flushSync(){this.isFlushingSync=!0;const e=J();try{this._mergeBatchQueue(),this._drainQueue()}finally{this.isFlushingSync=!1,e&&Q()}}_mergeBatchQueue(){if(this._epoch++,this.batchQueueSize>0){for(let e=0;e<this.batchQueueSize;e++){const t=this.batchQueue[e];t&&t._nextEpoch!==this._epoch&&(t._nextEpoch=this._epoch,this.queue[this.queueSize++]=t)}this.batchQueueSize=0}}_drainQueue(){let e=0;for(;this.queueSize>0;){if(++e>this.maxFlushIterations){this._handleFlushOverflow();break}this._processCurrentQueue(),this._mergeBatchQueue()}}_processCurrentQueue(){const e=this.queue,t=this.queueSize;this.queue=this.queue===this.queueA?this.queueB:this.queueA,this.queueSize=0,this._epoch++,this._processJobs(e,t)}_handleFlushOverflow(){console.error(new F(`Maximum flush iterations (${this.maxFlushIterations}) exceeded. Possible infinite loop.`)),this.queueSize=0,this.queue.length=0,this.batchQueueSize=0}_processJobs(e,t){for(let s=0;s<t;s++)try{e[s]?.()}catch(n){console.error(new F("Error occurred during scheduler execution",n))}e.length=0}startBatch(){this.batchDepth++,this.isBatching=!0}endBatch(){this.batchDepth=Math.max(0,this.batchDepth-1),this.batchDepth===0&&(this.flushSync(),this.isBatching=!1)}setMaxFlushIterations(e){if(e<g.MIN_FLUSH_ITERATIONS)throw new F(`Max flush iterations must be at least ${g.MIN_FLUSH_ITERATIONS}`);this.maxFlushIterations=e}}const N=new ae;function le(i){if(typeof i!="function")throw new d("Batch callback must be a function");N.startBatch();try{return i()}finally{N.endBatch()}}const y={current:null,run(i,e){const t=this.current;this.current=i;try{return e()}finally{this.current=t}},getCurrent(){return this.current}};function W(i){if(typeof i!="function")throw new d("Untracked callback must be a function");const e=y.current;y.current=null;try{return i()}finally{y.current=e}}class M{constructor(){this.subscribers=null}add(e){if(this.subscribers||(this.subscribers=[]),this.subscribers.indexOf(e)!==-1)return()=>{};this.subscribers.push(e);let t=!1;return()=>{t||(t=!0,this.remove(e))}}remove(e){if(!this.subscribers)return!1;const t=this.subscribers.indexOf(e);if(t===-1)return!1;const s=this.subscribers.length-1;return t!==s&&(this.subscribers[t]=this.subscribers[s]),this.subscribers.pop(),!0}has(e){return this.subscribers?this.subscribers.indexOf(e)!==-1:!1}forEach(e){if(this.subscribers)for(let t=0;t<this.subscribers.length;t++)e(this.subscribers[t],t)}forEachSafe(e,t){if(this.subscribers)for(let s=0;s<this.subscribers.length;s++)try{e(this.subscribers[s],s)}catch(n){t?t(n):console.error("[SubscriberManager] Error in subscriber callback:",n)}}get size(){return this.subscribers?.length??0}get hasSubscribers(){return this.subscribers!==null&&this.subscribers.length>0}clear(){this.subscribers=null}toArray(){return this.subscribers?[...this.subscribers]:[]}}class j{constructor(){this.pool=[],this.maxPoolSize=50,this.maxReusableCapacity=256,this.stats=l?{acquired:0,released:0,rejected:{frozen:0,tooLarge:0,poolFull:0}}:null}acquire(){return l&&this.stats&&this.stats.acquired++,this.pool.pop()??[]}release(e,t){if(!(t&&e===t)){if(Object.isFrozen(e)){l&&this.stats&&this.stats.rejected.frozen++;return}if(e.length>this.maxReusableCapacity){l&&this.stats&&this.stats.rejected.tooLarge++;return}if(this.pool.length>=this.maxPoolSize){l&&this.stats&&this.stats.rejected.poolFull++;return}e.length=0,this.pool.push(e),l&&this.stats&&this.stats.released++}}getStats(){if(!l||!this.stats)return null;const{acquired:e,released:t,rejected:s}=this.stats,n=s.frozen+s.tooLarge+s.poolFull;return{acquired:e,released:t,rejected:s,leaked:e-t-n,poolSize:this.pool.length}}reset(){this.pool.length=0,l&&this.stats&&(this.stats.acquired=0,this.stats.released=0,this.stats.rejected={frozen:0,tooLarge:0,poolFull:0})}}const _=Object.freeze([]),E=Object.freeze([]),a=Object.freeze([]),D=new j,C=new j,p=new j;function K(i){return i!==null&&typeof i=="object"&&"value"in i&&"subscribe"in i&&typeof i.subscribe=="function"}function fe(i){if(f.enabled&&(i==null||typeof i=="object")){const e=f.getDebugType(i);if(e)return e==="computed"}return K(i)&&"invalidate"in i&&typeof i.invalidate=="function"}function de(i){return i!==null&&typeof i=="object"&&"dispose"in i&&"run"in i&&typeof i.dispose=="function"&&typeof i.run=="function"}function Z(i){return i!=null&&typeof i.then=="function"}function Ee(i){return typeof i=="object"&&i!==null}function pe(i){return(typeof i=="object"||typeof i=="function")&&i!==null&&typeof i.addDependency=="function"}function be(i){return typeof i=="function"&&typeof i.addDependency!="function"}function Se(i){return Ee(i)&&typeof i.execute=="function"}function ee(i,e,t,s){if(e){if(pe(e)){e.addDependency(i);return}if(be(e)){t.add(e);return}Se(e)&&s.add(e)}}function ge(i,e,t,s){if(e!==_&&t!==E)for(let r=0;r<e.length;r++){const o=e[r];o&&(o._tempUnsub=t[r])}const n=C.acquire();n.length=i.length;for(let r=0;r<i.length;r++){const o=i[r];o&&(o._tempUnsub?(n[r]=o._tempUnsub,o._tempUnsub=void 0):(f.checkCircular(o,s),n[r]=o.subscribe(s)))}if(e!==_)for(let r=0;r<e.length;r++){const o=e[r];o?._tempUnsub&&(o._tempUnsub(),o._tempUnsub=void 0)}return t!==E&&C.release(t),n}class De extends H{constructor(e,t){super(),this._isNotificationScheduled=!1,this._value=e,this._functionSubscribersStore=new M,this._objectSubscribersStore=new M,this._sync=t,this._notifyTask=this._flushNotifications.bind(this),f.attachDebugInfo(this,"atom",this.id)}get _functionSubscribers(){return this._functionSubscribersStore}get _objectSubscribers(){return this._objectSubscribersStore}get value(){const e=y.getCurrent();return e&&this._track(e),this._value}set value(e){if(Object.is(this._value,e))return;const t=this._value;this.version=this.version+1&I,this._value=e,!(!this._functionSubscribersStore.hasSubscribers&&!this._objectSubscribersStore.hasSubscribers)&&this._scheduleNotification(t)}_track(e){ee(this,e,this._functionSubscribersStore,this._objectSubscribersStore)}_scheduleNotification(e){this._isNotificationScheduled||(this._pendingOldValue=e,this._isNotificationScheduled=!0),this._sync&&!N.isBatching?this._flushNotifications():N.schedule(this._notifyTask)}_flushNotifications(){if(!this._isNotificationScheduled)return;const e=this._pendingOldValue,t=this._value;this._pendingOldValue=void 0,this._isNotificationScheduled=!1,this._notifySubscribers(t,e)}peek(){return this._value}dispose(){this._functionSubscribersStore.clear(),this._objectSubscribersStore.clear(),this._value=void 0}}function Ie(i,e={}){return new De(i,e.sync??!1)}function R(i,e,t){if(i instanceof TypeError)return new e(`Type error (${t}): ${i.message}`,i);if(i instanceof ReferenceError)return new e(`Reference error (${t}): ${i.message}`,i);if(i instanceof d)return i;const s=i instanceof Error?i.message:String(i),n=i instanceof Error?i:null;return new e(`Unexpected error (${t}): ${s}`,n)}const te=u.RESOLVED|u.PENDING|u.REJECTED,V=Array(te+1).fill(U.IDLE);V[u.RESOLVED]=U.RESOLVED,V[u.PENDING]=U.PENDING,V[u.REJECTED]=U.REJECTED;class se extends H{constructor(e,t={}){if(typeof e!="function")throw new m(h.COMPUTED_MUST_BE_FUNCTION);if(super(),this._cachedErrors=null,this._errorCacheEpoch=-1,this._value=void 0,this.flags=u.DIRTY|u.IDLE,this._error=null,this._promiseId=0,this._equal=t.equal??Object.is,this._fn=e,this._defaultValue="defaultValue"in t?t.defaultValue:z,this._hasDefaultValue=this._defaultValue!==z,this._onError=t.onError??null,this.MAX_PROMISE_ID=Number.MAX_SAFE_INTEGER-1,this._functionSubscribersStore=new M,this._objectSubscribersStore=new M,this._dependencies=_,this._dependencyVersions=a,this._unsubscribes=E,this._notifyJob=()=>{this._functionSubscribersStore.forEachSafe(s=>s(),s=>console.error(s)),this._objectSubscribersStore.forEachSafe(s=>s.execute(),s=>console.error(s))},this._trackable=Object.assign(()=>this._markDirty(),{addDependency:s=>{}}),f.attachDebugInfo(this,"computed",this.id),f.enabled){const s=this;s.subscriberCount=()=>this._functionSubscribersStore.size+this._objectSubscribersStore.size,s.isDirty=()=>this._isDirty(),s.dependencies=this._dependencies,s.stateFlags=this._getFlagsAsString()}if(t.lazy===!1)try{this._recompute()}catch{}}get _functionSubscribers(){return this._functionSubscribersStore}get _objectSubscribers(){return this._objectSubscribersStore}get value(){return this._registerTracking(),this._computeValue()}peek(){return this._value}get state(){return this._registerTracking(),this._getAsyncState()}get hasError(){if(this._registerTracking(),this._isRejected())return!0;for(let e=0;e<this._dependencies.length;e++){const t=this._dependencies[e];if(t&&"hasError"in t&&t.hasError)return!0}return!1}get isValid(){return!this.hasError}get errors(){if(this._registerTracking(),!this.hasError)return ne;const e=he();if(this._errorCacheEpoch===e&&this._cachedErrors!==null)return this._cachedErrors;const t=new Set;this._error&&t.add(this._error);for(let s=0;s<this._dependencies.length;s++){const n=this._dependencies[s];if(n&&"errors"in n){const r=n.errors;for(let o=0;o<r.length;o++){const T=r[o];T&&t.add(T)}}}return this._cachedErrors=Object.freeze([...t]),this._errorCacheEpoch=e,this._cachedErrors}get lastError(){return this._registerTracking(),this._error}get isPending(){return this._registerTracking(),this._isPending()}get isResolved(){return this._registerTracking(),this._isResolved()}invalidate(){this._markDirty(),this._dependencyVersions!==a&&(p.release(this._dependencyVersions),this._dependencyVersions=a),this._errorCacheEpoch=-1,this._cachedErrors=null}dispose(){if(this._unsubscribes!==E){for(let e=0;e<this._unsubscribes.length;e++){const t=this._unsubscribes[e];t&&t()}C.release(this._unsubscribes),this._unsubscribes=E}this._dependencies!==_&&(D.release(this._dependencies),this._dependencies=_),this._dependencyVersions!==a&&(p.release(this._dependencyVersions),this._dependencyVersions=a),this._functionSubscribersStore.clear(),this._objectSubscribersStore.clear(),this.flags=u.DIRTY|u.IDLE,this._error=null,this._value=void 0,this._promiseId=(this._promiseId+1)%this.MAX_PROMISE_ID,this._cachedErrors=null,this._errorCacheEpoch=-1}_isDirty(){return(this.flags&u.DIRTY)!==0}_setDirty(){this.flags|=u.DIRTY}_clearDirty(){this.flags&=-2}_isIdle(){return(this.flags&u.IDLE)!==0}_setIdle(){this.flags|=u.IDLE,this.flags&=-29}_isPending(){return(this.flags&u.PENDING)!==0}_setPending(){this.flags|=u.PENDING,this.flags&=-27}_isResolved(){return(this.flags&u.RESOLVED)!==0}_setResolved(){this.flags|=u.RESOLVED,this.flags&=-87}_isRejected(){return(this.flags&u.REJECTED)!==0}_setRejected(){this.flags|=u.REJECTED|u.HAS_ERROR,this.flags&=-15}_isRecomputing(){return(this.flags&u.RECOMPUTING)!==0}_setRecomputing(e){const t=u.RECOMPUTING;this.flags=this.flags&~t|-Number(e)&t}_getAsyncState(){return V[this.flags&te]}_getFlagsAsString(){const e=[];return this._isDirty()&&e.push("DIRTY"),this._isIdle()&&e.push("IDLE"),this._isPending()&&e.push("PENDING"),this._isResolved()&&e.push("RESOLVED"),this._isRejected()&&e.push("REJECTED"),this._isRecomputing()&&e.push("RECOMPUTING"),e.join(" | ")}_computeValue(){return this._isRecomputing()?this._value:((this._isDirty()||this._isIdle())&&this._recompute(),this._isPending()?this._handlePending():this._isRejected()?this._handleRejected():this._value)}_recompute(){if(this._isRecomputing())return;this._setRecomputing(!0);const e=this._prepareComputationContext();let t=!1;try{const s=y.run(this._trackable,this._fn);this._commitDependencies(e),t=!0,Z(s)?this._handleAsyncComputation(s):this._handleSyncResult(s)}catch(s){if(!t)try{this._commitDependencies(e),t=!0}catch(n){this._handleComputationError(n)}this._handleComputationError(s)}finally{this._cleanupContext(e,t),this._setRecomputing(!1)}}_prepareComputationContext(){const e=this._dependencies,t=this._dependencyVersions,s=D.acquire(),n=p.acquire(),r=$(),o={depCount:0},T=S=>{S._lastSeenEpoch!==r&&(S._lastSeenEpoch=r,o.depCount<s.length?(s[o.depCount]=S,n[o.depCount]=S.version):(s.push(S),n.push(S.version)),o.depCount++)},A=this._trackable.addDependency;return this._trackable.addDependency=T,{prevDeps:e,prevVersions:t,nextDeps:s,nextVersions:n,originalAdd:A,state:o}}_commitDependencies(e){const{nextDeps:t,nextVersions:s,state:n,prevDeps:r}=e;t.length=n.depCount,s.length=n.depCount,this._unsubscribes=ge(t,r,this._unsubscribes,this),this._dependencies=t,this._dependencyVersions=s}_cleanupContext(e,t){this._trackable.addDependency=e.originalAdd,t?(e.prevDeps!==_&&D.release(e.prevDeps),e.prevVersions!==a&&p.release(e.prevVersions)):(D.release(e.nextDeps),p.release(e.nextVersions))}_handleSyncResult(e){const t=!this._isResolved()||!this._equal(this._value,e);this.version=this.version+Number(t)&I,this._value=e,this._clearDirty(),this._setResolved(),this._error=null,this._setRecomputing(!1),this._cachedErrors=null,this._errorCacheEpoch=-1}_handleAsyncComputation(e){this._setPending(),this._clearDirty(),this._notifyJob(),this._promiseId=this._promiseId>=this.MAX_PROMISE_ID?1:this._promiseId+1;const t=this._promiseId;e.then(s=>{t===this._promiseId&&this._handleAsyncResolution(s)}).catch(s=>{t===this._promiseId&&this._handleAsyncRejection(s)})}_handleAsyncResolution(e){const t=!this._isResolved()||!this._equal(this._value,e);this.version=this.version+Number(t)&I,this._value=e,this._clearDirty(),this._setResolved(),this._error=null,this._setRecomputing(!1),this._cachedErrors=null,this._errorCacheEpoch=-1,this._notifyJob()}_handleAsyncRejection(e){const t=R(e,m,h.COMPUTED_ASYNC_COMPUTATION_FAILED),s=!this._isRejected();if(this.version=this.version+Number(s)&I,this._error=t,this._setRejected(),this._clearDirty(),this._setRecomputing(!1),this._onError)try{this._onError(t)}catch(n){console.error(h.CALLBACK_ERROR_IN_ERROR_HANDLER,n)}this._notifyJob()}_handleComputationError(e){const t=R(e,m,h.COMPUTED_COMPUTATION_FAILED);if(this._error=t,this._setRejected(),this._clearDirty(),this._setRecomputing(!1),this._onError)try{this._onError(t)}catch(s){console.error(h.CALLBACK_ERROR_IN_ERROR_HANDLER,s)}throw t}_handlePending(){if(this._hasDefaultValue)return this._defaultValue;throw new m(h.COMPUTED_ASYNC_PENDING_NO_DEFAULT)}_handleRejected(){if(this._error?.recoverable&&this._hasDefaultValue)return this._defaultValue;throw this._error}execute(){this._markDirty()}_markDirty(){this._isRecomputing()||this._isDirty()||(this._setDirty(),this._notifyJob())}_registerTracking(){ee(this,y.getCurrent(),this._functionSubscribersStore,this._objectSubscribersStore)}}Object.freeze(se.prototype);function me(i,e={}){return new se(i,e)}class ye extends Y{constructor(e,t={}){super(),this.run=()=>{if(this.isDisposed)throw new b(h.EFFECT_MUST_BE_FUNCTION);this._dependencyVersions!==a&&(p.release(this._dependencyVersions),this._dependencyVersions=a),this.execute()},this.dispose=()=>{if(!this.isDisposed){if(this._setDisposed(),this._safeCleanup(),this._unsubscribes!==E){for(let s=0;s<this._unsubscribes.length;s++){const n=this._unsubscribes[s];n&&n()}C.release(this._unsubscribes),this._unsubscribes=E}this._dependencies!==_&&(D.release(this._dependencies),this._dependencies=_),this._dependencyVersions!==a&&(p.release(this._dependencyVersions),this._dependencyVersions=a)}},this.addDependency=s=>{if(this.isExecuting&&this._nextDeps&&this._nextUnsubs&&this._nextVersions){const n=this._currentEpoch;if(s._lastSeenEpoch===n)return;s._lastSeenEpoch=n,this._nextDeps.push(s),this._nextVersions.push(s.version),s._tempUnsub?(this._nextUnsubs.push(s._tempUnsub),s._tempUnsub=void 0):this._subscribeTo(s)}},this.execute=()=>{if(this.isDisposed||this.isExecuting||!this._shouldExecute())return;this._checkInfiniteLoop(),this._setExecuting(!0),this._safeCleanup();const s=this._prepareEffectContext();let n=!1;try{const r=y.run(this,this._fn);this._commitEffect(s),n=!0,this._checkLoopWarnings(),Z(r)?r.then(o=>{!this.isDisposed&&typeof o=="function"&&(this._cleanup=o)}).catch(o=>{console.error(R(o,b,h.EFFECT_EXECUTION_FAILED))}):this._cleanup=typeof r=="function"?r:null}catch(r){n=!0,console.error(R(r,b,h.EFFECT_EXECUTION_FAILED)),this._cleanup=null}finally{this._cleanupEffect(s,n),this._setExecuting(!1)}},this._currentEpoch=-1,this._lastFlushEpoch=-1,this._executionsInEpoch=0,this._fn=e,this._sync=t.sync??!1,this._maxExecutions=t.maxExecutionsPerSecond??g.MAX_EXECUTIONS_PER_SECOND,this._maxExecutionsPerFlush=t.maxExecutionsPerFlush??g.MAX_EXECUTIONS_PER_EFFECT,this._trackModifications=t.trackModifications??!1,this._cleanup=null,this._dependencies=_,this._dependencyVersions=a,this._unsubscribes=E,this._nextDeps=null,this._nextVersions=null,this._nextUnsubs=null,this._history=l?[]:null,this._executionCount=0,f.attachDebugInfo(this,"effect",this.id)}_prepareEffectContext(){const e=this._dependencies,t=this._dependencyVersions,s=this._unsubscribes,n=D.acquire(),r=p.acquire(),o=C.acquire(),T=$();if(e!==_&&s!==E)for(let A=0;A<e.length;A++){const S=e[A];S&&(S._tempUnsub=s[A])}return this._nextDeps=n,this._nextVersions=r,this._nextUnsubs=o,this._currentEpoch=T,{prevDeps:e,prevVersions:t,prevUnsubs:s,nextDeps:n,nextVersions:r,nextUnsubs:o}}_commitEffect(e){const t=e.nextDeps.length;e.nextDeps.length=t,e.nextVersions.length=t,this._dependencies=e.nextDeps,this._dependencyVersions=e.nextVersions,this._unsubscribes=e.nextUnsubs}_cleanupEffect(e,t){if(this._nextDeps=null,this._nextVersions=null,this._nextUnsubs=null,t){if(e.prevDeps!==_){for(let s=0;s<e.prevDeps.length;s++){const n=e.prevDeps[s];n?._tempUnsub&&(n._tempUnsub(),n._tempUnsub=void 0)}D.release(e.prevDeps)}e.prevUnsubs!==E&&C.release(e.prevUnsubs),e.prevVersions!==a&&p.release(e.prevVersions)}else{D.release(e.nextDeps),p.release(e.nextVersions);for(let s=0;s<e.nextUnsubs.length;s++)e.nextUnsubs[s]?.();if(C.release(e.nextUnsubs),e.prevDeps!==_)for(let s=0;s<e.prevDeps.length;s++){const n=e.prevDeps[s];n&&(n._tempUnsub=void 0)}}}_subscribeTo(e){try{const t=e.subscribe(()=>{this._trackModifications&&this.isExecuting&&(e._modifiedAtEpoch=this._currentEpoch),this._sync?this.execute():N.schedule(this.execute)});this._nextUnsubs&&this._nextUnsubs.push(t)}catch(t){console.error(R(t,b,h.EFFECT_EXECUTION_FAILED)),this._nextUnsubs&&this._nextUnsubs.push(()=>{})}}get isDisposed(){return(this.flags&x.DISPOSED)!==0}get executionCount(){return this._executionCount}get isExecuting(){return(this.flags&x.EXECUTING)!==0}_setDisposed(){this.flags|=x.DISPOSED}_setExecuting(e){const t=x.EXECUTING;this.flags=this.flags&~t|-Number(e)&t}_safeCleanup(){if(this._cleanup){try{this._cleanup()}catch(e){console.error(R(e,b,h.EFFECT_CLEANUP_FAILED))}this._cleanup=null}}_checkInfiniteLoop(){if(this._lastFlushEpoch!==v&&(this._lastFlushEpoch=v,this._executionsInEpoch=0),this._executionsInEpoch++,this._executionsInEpoch>this._maxExecutionsPerFlush&&this._throwInfiniteLoopError("per-effect"),_e()>g.MAX_EXECUTIONS_PER_FLUSH&&this._throwInfiniteLoopError("global"),this._executionCount++,this._history){const e=Date.now();this._history.push(e),this._history.length>g.MAX_EXECUTIONS_PER_SECOND+10&&this._history.shift(),this._checkTimestampLoop(e)}}_checkTimestampLoop(e){const t=this._history;if(!t||this._maxExecutions<=0)return;const s=e-O.ONE_SECOND_MS;let n=0;for(let r=t.length-1;r>=0&&!(t[r]<s);r--)n++;if(n>this._maxExecutions){const r=new b(`Effect executed ${n} times within 1 second. Infinite loop suspected`);if(this.dispose(),console.error(r),l)throw r}}_throwInfiniteLoopError(e){const t=new b(`Infinite loop detected (${e}): effect executed ${this._executionsInEpoch} times in current flush. Total executions in flush: ${q}`);throw this.dispose(),console.error(t),t}_shouldExecute(){if(this._dependencies===_||this._dependencyVersions===a)return!0;for(let e=0;e<this._dependencies.length;e++){const t=this._dependencies[e];if(t){if("value"in t)try{W(()=>t.value)}catch{return!0}if(t.version!==this._dependencyVersions[e])return!0}}return!1}_checkLoopWarnings(){if(this._trackModifications&&f.enabled){const e=this._dependencies;for(let t=0;t<e.length;t++){const s=e[t];s&&s._modifiedAtEpoch===this._currentEpoch&&f.warn(!0,`Effect is reading a dependency (${f.getDebugName(s)||"unknown"}) that it just modified. Infinite loop may occur`)}}}}function Ce(i,e={}){if(typeof i!="function")throw new b(h.EFFECT_MUST_BE_FUNCTION);const t=new ye(i,e);return t.execute(),t}c.AsyncState=U,c.AtomError=d,c.ComputedError=m,c.DEBUG_CONFIG=w,c.DEBUG_RUNTIME=f,c.EffectError=b,c.POOL_CONFIG=ie,c.SCHEDULER_CONFIG=g,c.SchedulerError=F,c.atom=Ie,c.batch=le,c.computed=me,c.effect=Ce,c.isAtom=K,c.isComputed=fe,c.isEffect=de,c.scheduler=N,c.untracked=W,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(c,A){typeof exports=="object"&&typeof module<"u"?A(exports):typeof define=="function"&&define.amd?define(["exports"],A):(c=typeof globalThis<"u"?globalThis:c||self,A(c.AtomEffect={}))})(this,(function(c){"use strict";const A={ONE_SECOND_MS:1e3},O={IDLE:"idle",PENDING:"pending",RESOLVED:"resolved",REJECTED:"rejected"},F={DISPOSED:1,EXECUTING:2},h={DIRTY:1,IDLE:2,PENDING:4,RESOLVED:8,REJECTED:16,RECOMPUTING:32,HAS_ERROR:64},ie={MAX_SIZE:1e3,WARMUP_SIZE:100},g={MAX_EXECUTIONS_PER_SECOND:1e3,CLEANUP_THRESHOLD:1e3,MAX_EXECUTIONS_PER_EFFECT:100,MAX_EXECUTIONS_PER_FLUSH:1e4,MAX_FLUSH_ITERATIONS:1e3,MIN_FLUSH_ITERATIONS:10},w={MAX_DEPENDENCIES:1e3,WARN_INFINITE_LOOP:!0},I=1073741823,l=typeof process<"u"&&process.env&&process.env.NODE_ENV!=="production",ne=Object.freeze([]);class E extends Error{constructor(e,t=null,i=!0){super(e),this.name="AtomError",this.cause=t,this.recoverable=i,this.timestamp=new Date}}class m extends E{constructor(e,t=null){super(e,t,!0),this.name="ComputedError"}}class D extends E{constructor(e,t=null){super(e,t,!1),this.name="EffectError"}}class U extends E{constructor(e,t=null){super(e,t,!1),this.name="SchedulerError"}}const u={COMPUTED_MUST_BE_FUNCTION:"Computed function must be a function",COMPUTED_ASYNC_PENDING_NO_DEFAULT:"Async computation is pending. No default value provided",COMPUTED_COMPUTATION_FAILED:"Computed computation failed",COMPUTED_ASYNC_COMPUTATION_FAILED:"Async computed computation failed",ATOM_SUBSCRIBER_MUST_BE_FUNCTION:"Subscription listener must be a function or Subscriber object",ATOM_INDIVIDUAL_SUBSCRIBER_FAILED:"Error during individual atom subscriber execution",EFFECT_MUST_BE_FUNCTION:"Effect function must be a function",EFFECT_EXECUTION_FAILED:"Effect execution failed",EFFECT_CLEANUP_FAILED:"Effect cleanup function execution failed",CALLBACK_ERROR_IN_ERROR_HANDLER:"Error occurred during onError callback execution"},k=Symbol("debugName"),re=Symbol("id"),q=Symbol("type"),z=Symbol("noDefaultValue");function oe(s){return"dependencies"in s&&Array.isArray(s.dependencies)}let G=0;function X(s,e,t){if(s._visitedEpoch!==t){if(s._visitedEpoch=t,s===e)throw new m("Indirect circular dependency detected");if(oe(s)){const i=s.dependencies;for(let n=0;n<i.length;n++){const r=i[n];r&&X(r,e,t)}}}}const f={enabled:typeof process<"u"&&process.env?.NODE_ENV==="development",maxDependencies:w.MAX_DEPENDENCIES,warnInfiniteLoop:w.WARN_INFINITE_LOOP,warn(s,e){this.enabled&&s&&console.warn(`[Atom Effect] ${e}`)},checkCircular(s,e){if(s===e)throw new m("Direct circular dependency detected");this.enabled&&(G++,X(s,e,G))},attachDebugInfo(s,e,t){if(!this.enabled)return;const i=s;i[k]=`${e}_${t}`,i[re]=t,i[q]=e},getDebugName(s){if(s!=null&&k in s)return s[k]},getDebugType(s){if(s!=null&&q in s)return s[q]}};let ce=1;const he=()=>ce++;class Y{constructor(){this.id=he()&I,this.flags=0}}class H extends Y{constructor(){super(),this.version=0,this._lastSeenEpoch=-1}subscribe(e){if(typeof e=="object"&&e!==null&&"execute"in e)return this._objectSubscribers.add(e);if(typeof e!="function")throw new E(u.ATOM_SUBSCRIBER_MUST_BE_FUNCTION);return this._functionSubscribers.add(e)}subscriberCount(){return this._functionSubscribers.size+this._objectSubscribers.size}_notifySubscribers(e,t){this._functionSubscribers.forEachSafe(i=>i(e,t),i=>console.error(new E(u.ATOM_INDIVIDUAL_SUBSCRIBER_FAILED,i))),this._objectSubscribers.forEachSafe(i=>i.execute(),i=>console.error(new E(u.ATOM_INDIVIDUAL_SUBSCRIBER_FAILED,i)))}}let v=0;function J(){return v=v+1&I||1,v}function ue(){return v}let P=0,B=0,M=!1;function Q(){return M?(l&&console.warn("Warning: startFlush() called during flush - ignored to prevent infinite loop detection bypass"),!1):(M=!0,P=P+1&I,B=0,!0)}function $(){M=!1}function _e(){return M?++B:0}class ae{constructor(){this.queueA=[],this.queueB=[],this.queue=this.queueA,this.queueSize=0,this._epoch=0,this.isProcessing=!1,this.isBatching=!1,this.batchDepth=0,this.batchQueue=[],this.batchQueueSize=0,this.isFlushingSync=!1,this.maxFlushIterations=g.MAX_FLUSH_ITERATIONS}get phase(){return this.isProcessing||this.isFlushingSync?2:this.isBatching?1:0}schedule(e){if(typeof e!="function")throw new U("Scheduler callback must be a function");e._nextEpoch!==this._epoch&&(e._nextEpoch=this._epoch,this.isBatching||this.isFlushingSync?this.batchQueue[this.batchQueueSize++]=e:(this.queue[this.queueSize++]=e,this.isProcessing||this.flush()))}flush(){if(this.isProcessing||this.queueSize===0)return;this.isProcessing=!0;const e=this.queue,t=this.queueSize;this.queue=this.queue===this.queueA?this.queueB:this.queueA,this.queueSize=0,this._epoch++,queueMicrotask(()=>{const i=Q();this._processJobs(e,t),this.isProcessing=!1,i&&$(),this.queueSize>0&&!this.isBatching&&this.flush()})}flushSync(){this.isFlushingSync=!0;const e=Q();try{this._mergeBatchQueue(),this._drainQueue()}finally{this.isFlushingSync=!1,e&&$()}}_mergeBatchQueue(){if(this._epoch++,this.batchQueueSize>0){for(let e=0;e<this.batchQueueSize;e++){const t=this.batchQueue[e];t&&t._nextEpoch!==this._epoch&&(t._nextEpoch=this._epoch,this.queue[this.queueSize++]=t)}this.batchQueueSize=0}}_drainQueue(){let e=0;for(;this.queueSize>0;){if(++e>this.maxFlushIterations){this._handleFlushOverflow();break}this._processCurrentQueue(),this._mergeBatchQueue()}}_processCurrentQueue(){const e=this.queue,t=this.queueSize;this.queue=this.queue===this.queueA?this.queueB:this.queueA,this.queueSize=0,this._epoch++,this._processJobs(e,t)}_handleFlushOverflow(){console.error(new U(`Maximum flush iterations (${this.maxFlushIterations}) exceeded. Possible infinite loop.`)),this.queueSize=0,this.queue.length=0,this.batchQueueSize=0}_processJobs(e,t){for(let i=0;i<t;i++)try{e[i]?.()}catch(n){console.error(new U("Error occurred during scheduler execution",n))}e.length=0}startBatch(){this.batchDepth++,this.isBatching=!0}endBatch(){this.batchDepth=Math.max(0,this.batchDepth-1),this.batchDepth===0&&(this.flushSync(),this.isBatching=!1)}setMaxFlushIterations(e){if(e<g.MIN_FLUSH_ITERATIONS)throw new U(`Max flush iterations must be at least ${g.MIN_FLUSH_ITERATIONS}`);this.maxFlushIterations=e}}const R=new ae;function le(s){if(typeof s!="function")throw new E("Batch callback must be a function");R.startBatch();try{return s()}finally{R.endBatch()}}const C={current:null,run(s,e){const t=this.current;this.current=s;try{return e()}finally{this.current=t}},getCurrent(){return this.current}};function W(s){if(typeof s!="function")throw new E("Untracked callback must be a function");const e=C.current;C.current=null;try{return s()}finally{C.current=e}}class L{constructor(){this.subscribers=null}add(e){if(this.subscribers||(this.subscribers=[]),this.subscribers.indexOf(e)!==-1)return()=>{};this.subscribers.push(e);let t=!1;return()=>{t||(t=!0,this.remove(e))}}remove(e){if(!this.subscribers)return!1;const t=this.subscribers.indexOf(e);if(t===-1)return!1;const i=this.subscribers.length-1;return t!==i&&(this.subscribers[t]=this.subscribers[i]),this.subscribers.pop(),!0}has(e){return this.subscribers?this.subscribers.indexOf(e)!==-1:!1}forEach(e){if(this.subscribers)for(let t=0;t<this.subscribers.length;t++)e(this.subscribers[t],t)}forEachSafe(e,t){if(this.subscribers)for(let i=0;i<this.subscribers.length;i++)try{e(this.subscribers[i],i)}catch(n){t?t(n):console.error("[SubscriberManager] Error in subscriber callback:",n)}}get size(){return this.subscribers?.length??0}get hasSubscribers(){return this.subscribers!==null&&this.subscribers.length>0}clear(){this.subscribers=null}toArray(){return this.subscribers?[...this.subscribers]:[]}}class j{constructor(){this.pool=[],this.maxPoolSize=50,this.maxReusableCapacity=256,this.stats=l?{acquired:0,released:0,rejected:{frozen:0,tooLarge:0,poolFull:0}}:null}acquire(){return l&&this.stats&&this.stats.acquired++,this.pool.pop()??[]}release(e,t){if(!(t&&e===t)){if(Object.isFrozen(e)){l&&this.stats&&this.stats.rejected.frozen++;return}if(e.length>this.maxReusableCapacity){l&&this.stats&&this.stats.rejected.tooLarge++;return}if(this.pool.length>=this.maxPoolSize){l&&this.stats&&this.stats.rejected.poolFull++;return}e.length=0,this.pool.push(e),l&&this.stats&&this.stats.released++}}getStats(){if(!l||!this.stats)return null;const{acquired:e,released:t,rejected:i}=this.stats,n=i.frozen+i.tooLarge+i.poolFull;return{acquired:e,released:t,rejected:i,leaked:e-t-n,poolSize:this.pool.length}}reset(){this.pool.length=0,l&&this.stats&&(this.stats.acquired=0,this.stats.released=0,this.stats.rejected={frozen:0,tooLarge:0,poolFull:0})}}const _=Object.freeze([]),p=Object.freeze([]),a=Object.freeze([]),y=new j,N=new j,b=new j;function K(s){return s!==null&&typeof s=="object"&&"value"in s&&"subscribe"in s&&typeof s.subscribe=="function"}function fe(s){if(f.enabled&&(s==null||typeof s=="object")){const e=f.getDebugType(s);if(e)return e==="computed"}return K(s)&&"invalidate"in s&&typeof s.invalidate=="function"}function de(s){return s!==null&&typeof s=="object"&&"dispose"in s&&"run"in s&&typeof s.dispose=="function"&&typeof s.run=="function"}function Z(s){return s!=null&&typeof s.then=="function"}function Ee(s){return typeof s=="object"&&s!==null}function pe(s){return(typeof s=="object"||typeof s=="function")&&s!==null&&typeof s.addDependency=="function"}function be(s){return typeof s=="function"&&typeof s.addDependency!="function"}function Se(s){return Ee(s)&&typeof s.execute=="function"}function ee(s,e,t,i){if(e){if(pe(e)){e.addDependency(s);return}if(be(e)){t.add(e);return}Se(e)&&i.add(e)}}function ge(s,e,t,i){if(e!==_&&t!==p)for(let r=0;r<e.length;r++){const o=e[r];o&&(o._tempUnsub=t[r])}const n=N.acquire();n.length=s.length;for(let r=0;r<s.length;r++){const o=s[r];o&&(o._tempUnsub?(n[r]=o._tempUnsub,o._tempUnsub=void 0):(f.checkCircular(o,i),n[r]=o.subscribe(i)))}if(e!==_)for(let r=0;r<e.length;r++){const o=e[r];o?._tempUnsub&&(o._tempUnsub(),o._tempUnsub=void 0)}return t!==p&&N.release(t),n}class De extends H{constructor(e,t){super(),this._isNotificationScheduled=!1,this._value=e,this._functionSubscribersStore=new L,this._objectSubscribersStore=new L,this._sync=t,this._notifyTask=this._flushNotifications.bind(this),f.attachDebugInfo(this,"atom",this.id)}get _functionSubscribers(){return this._functionSubscribersStore}get _objectSubscribers(){return this._objectSubscribersStore}get value(){const e=C.getCurrent();return e&&this._track(e),this._value}set value(e){if(Object.is(this._value,e))return;const t=this._value;this.version=this.version+1&I,this._value=e,!(!this._functionSubscribersStore.hasSubscribers&&!this._objectSubscribersStore.hasSubscribers)&&this._scheduleNotification(t)}_track(e){ee(this,e,this._functionSubscribersStore,this._objectSubscribersStore)}_scheduleNotification(e){this._isNotificationScheduled||(this._pendingOldValue=e,this._isNotificationScheduled=!0),this._sync&&!R.isBatching?this._flushNotifications():R.schedule(this._notifyTask)}_flushNotifications(){if(!this._isNotificationScheduled)return;const e=this._pendingOldValue,t=this._value;this._pendingOldValue=void 0,this._isNotificationScheduled=!1,this._notifySubscribers(t,e)}peek(){return this._value}dispose(){this._functionSubscribersStore.clear(),this._objectSubscribersStore.clear(),this._value=void 0}}function ye(s,e={}){return new De(s,e.sync??!1)}function x(s,e,t){if(s instanceof TypeError)return new e(`Type error (${t}): ${s.message}`,s);if(s instanceof ReferenceError)return new e(`Reference error (${t}): ${s.message}`,s);if(s instanceof E)return s;const i=s instanceof Error?s.message:String(s),n=s instanceof Error?s:null;return new e(`Unexpected error (${t}): ${i}`,n)}const te=h.RESOLVED|h.PENDING|h.REJECTED,V=Array(te+1).fill(O.IDLE);V[h.RESOLVED]=O.RESOLVED,V[h.PENDING]=O.PENDING,V[h.REJECTED]=O.REJECTED;class se extends H{constructor(e,t={}){if(typeof e!="function")throw new m(u.COMPUTED_MUST_BE_FUNCTION);if(super(),this._cachedErrors=null,this._errorCacheEpoch=-1,this._value=void 0,this.flags=h.DIRTY|h.IDLE,this._error=null,this._promiseId=0,this._equal=t.equal??Object.is,this._fn=e,this._defaultValue="defaultValue"in t?t.defaultValue:z,this._hasDefaultValue=this._defaultValue!==z,this._onError=t.onError??null,this.MAX_PROMISE_ID=Number.MAX_SAFE_INTEGER-1,this._functionSubscribersStore=new L,this._objectSubscribersStore=new L,this._dependencies=_,this._dependencyVersions=a,this._unsubscribes=p,this._notifyJob=()=>{this._functionSubscribersStore.forEachSafe(i=>i(),i=>console.error(i)),this._objectSubscribersStore.forEachSafe(i=>i.execute(),i=>console.error(i))},this._trackable=Object.assign(()=>this._markDirty(),{addDependency:i=>{}}),f.attachDebugInfo(this,"computed",this.id),f.enabled){const i=this;i.subscriberCount=()=>this._functionSubscribersStore.size+this._objectSubscribersStore.size,i.isDirty=()=>this._isDirty(),i.dependencies=this._dependencies,i.stateFlags=this._getFlagsAsString()}if(t.lazy===!1)try{this._recompute()}catch{}}get _functionSubscribers(){return this._functionSubscribersStore}get _objectSubscribers(){return this._objectSubscribersStore}get value(){return this._registerTracking(),this._computeValue()}peek(){return this._value}get state(){return this._registerTracking(),this._getAsyncState()}get hasError(){if(this._registerTracking(),this._isRejected())return!0;for(let e=0;e<this._dependencies.length;e++){const t=this._dependencies[e];if(t&&"hasError"in t&&t.hasError)return!0}return!1}get isValid(){return!this.hasError}get errors(){if(this._registerTracking(),!this.hasError)return ne;const e=ue();if(this._errorCacheEpoch===e&&this._cachedErrors!==null)return this._cachedErrors;const t=new Set;this._error&&t.add(this._error);for(let i=0;i<this._dependencies.length;i++){const n=this._dependencies[i];if(n&&"errors"in n){const r=n.errors;for(let o=0;o<r.length;o++){const d=r[o];d&&t.add(d)}}}return this._cachedErrors=Object.freeze([...t]),this._errorCacheEpoch=e,this._cachedErrors}get lastError(){return this._registerTracking(),this._error}get isPending(){return this._registerTracking(),this._isPending()}get isResolved(){return this._registerTracking(),this._isResolved()}invalidate(){this._markDirty(),this._dependencyVersions!==a&&(b.release(this._dependencyVersions),this._dependencyVersions=a),this._errorCacheEpoch=-1,this._cachedErrors=null}dispose(){if(this._unsubscribes!==p){for(let e=0;e<this._unsubscribes.length;e++){const t=this._unsubscribes[e];t&&t()}N.release(this._unsubscribes),this._unsubscribes=p}this._dependencies!==_&&(y.release(this._dependencies),this._dependencies=_),this._dependencyVersions!==a&&(b.release(this._dependencyVersions),this._dependencyVersions=a),this._functionSubscribersStore.clear(),this._objectSubscribersStore.clear(),this.flags=h.DIRTY|h.IDLE,this._error=null,this._value=void 0,this._promiseId=(this._promiseId+1)%this.MAX_PROMISE_ID,this._cachedErrors=null,this._errorCacheEpoch=-1}_isDirty(){return(this.flags&h.DIRTY)!==0}_setDirty(){this.flags|=h.DIRTY}_clearDirty(){this.flags&=-2}_isIdle(){return(this.flags&h.IDLE)!==0}_setIdle(){this.flags|=h.IDLE,this.flags&=-29}_isPending(){return(this.flags&h.PENDING)!==0}_setPending(){this.flags|=h.PENDING,this.flags&=-27}_isResolved(){return(this.flags&h.RESOLVED)!==0}_setResolved(){this.flags|=h.RESOLVED,this.flags&=-87}_isRejected(){return(this.flags&h.REJECTED)!==0}_setRejected(){this.flags|=h.REJECTED|h.HAS_ERROR,this.flags&=-15}_isRecomputing(){return(this.flags&h.RECOMPUTING)!==0}_setRecomputing(e){const t=h.RECOMPUTING;this.flags=this.flags&~t|-Number(e)&t}_getAsyncState(){return V[this.flags&te]}_getFlagsAsString(){const e=[];return this._isDirty()&&e.push("DIRTY"),this._isIdle()&&e.push("IDLE"),this._isPending()&&e.push("PENDING"),this._isResolved()&&e.push("RESOLVED"),this._isRejected()&&e.push("REJECTED"),this._isRecomputing()&&e.push("RECOMPUTING"),e.join(" | ")}_computeValue(){return this._isRecomputing()?this._value:((this._isDirty()||this._isIdle())&&this._recompute(),this._isPending()?this._handlePending():this._isRejected()?this._handleRejected():this._value)}_recompute(){if(this._isRecomputing())return;this._setRecomputing(!0);const e=this._prepareComputationContext();let t=!1;try{const i=C.run(this._trackable,this._fn);this._commitDependencies(e),t=!0,Z(i)?this._handleAsyncComputation(i):this._handleSyncResult(i)}catch(i){if(!t)try{this._commitDependencies(e),t=!0}catch(n){this._handleComputationError(n)}this._handleComputationError(i)}finally{this._cleanupContext(e,t),this._setRecomputing(!1)}}_prepareComputationContext(){const e=this._dependencies,t=this._dependencyVersions,i=y.acquire(),n=b.acquire(),r=J(),o={depCount:0},d=S=>{S._lastSeenEpoch!==r&&(S._lastSeenEpoch=r,o.depCount<i.length?(i[o.depCount]=S,n[o.depCount]=S.version):(i.push(S),n.push(S.version)),o.depCount++)},T=this._trackable.addDependency;return this._trackable.addDependency=d,{prevDeps:e,prevVersions:t,nextDeps:i,nextVersions:n,originalAdd:T,state:o}}_commitDependencies(e){const{nextDeps:t,nextVersions:i,state:n,prevDeps:r}=e;t.length=n.depCount,i.length=n.depCount,this._unsubscribes=ge(t,r,this._unsubscribes,this),this._dependencies=t,this._dependencyVersions=i}_cleanupContext(e,t){this._trackable.addDependency=e.originalAdd,t?(e.prevDeps!==_&&y.release(e.prevDeps),e.prevVersions!==a&&b.release(e.prevVersions)):(y.release(e.nextDeps),b.release(e.nextVersions))}_handleSyncResult(e){const t=!this._isResolved()||!this._equal(this._value,e);this.version=this.version+Number(t)&I,this._value=e,this._clearDirty(),this._setResolved(),this._error=null,this._setRecomputing(!1),this._cachedErrors=null,this._errorCacheEpoch=-1}_handleAsyncComputation(e){this._setPending(),this._clearDirty(),this._notifyJob(),this._promiseId=this._promiseId>=this.MAX_PROMISE_ID?1:this._promiseId+1;const t=this._promiseId;e.then(i=>{t===this._promiseId&&this._handleAsyncResolution(i)}).catch(i=>{t===this._promiseId&&this._handleAsyncRejection(i)})}_handleAsyncResolution(e){const t=!this._isResolved()||!this._equal(this._value,e);this.version=this.version+Number(t)&I,this._value=e,this._clearDirty(),this._setResolved(),this._error=null,this._setRecomputing(!1),this._cachedErrors=null,this._errorCacheEpoch=-1,this._notifyJob()}_handleAsyncRejection(e){const t=x(e,m,u.COMPUTED_ASYNC_COMPUTATION_FAILED),i=!this._isRejected();if(this.version=this.version+Number(i)&I,this._error=t,this._setRejected(),this._clearDirty(),this._setRecomputing(!1),this._onError)try{this._onError(t)}catch(n){console.error(u.CALLBACK_ERROR_IN_ERROR_HANDLER,n)}this._notifyJob()}_handleComputationError(e){const t=x(e,m,u.COMPUTED_COMPUTATION_FAILED);if(this._error=t,this._setRejected(),this._clearDirty(),this._setRecomputing(!1),this._onError)try{this._onError(t)}catch(i){console.error(u.CALLBACK_ERROR_IN_ERROR_HANDLER,i)}throw t}_handlePending(){if(this._hasDefaultValue)return this._defaultValue;throw new m(u.COMPUTED_ASYNC_PENDING_NO_DEFAULT)}_handleRejected(){if(this._error?.recoverable&&this._hasDefaultValue)return this._defaultValue;throw this._error}execute(){this._markDirty()}_markDirty(){this._isRecomputing()||this._isDirty()||(this._setDirty(),this._notifyJob())}_registerTracking(){ee(this,C.getCurrent(),this._functionSubscribersStore,this._objectSubscribersStore)}}Object.freeze(se.prototype);function Ie(s,e={}){return new se(s,e)}class me extends Y{constructor(e,t={}){super(),this.run=()=>{if(this.isDisposed)throw new D(u.EFFECT_MUST_BE_FUNCTION);this._dependencyVersions!==a&&(b.release(this._dependencyVersions),this._dependencyVersions=a),this.execute()},this.dispose=()=>{if(!this.isDisposed){if(this._setDisposed(),this._safeCleanup(),this._unsubscribes!==p){for(let n=0;n<this._unsubscribes.length;n++){const r=this._unsubscribes[n];r&&r()}N.release(this._unsubscribes),this._unsubscribes=p}this._dependencies!==_&&(y.release(this._dependencies),this._dependencies=_),this._dependencyVersions!==a&&(b.release(this._dependencyVersions),this._dependencyVersions=a)}},this.addDependency=n=>{if(this.isExecuting&&this._nextDeps&&this._nextUnsubs&&this._nextVersions){const r=this._currentEpoch;if(n._lastSeenEpoch===r)return;n._lastSeenEpoch=r,this._nextDeps.push(n),this._nextVersions.push(n.version),n._tempUnsub?(this._nextUnsubs.push(n._tempUnsub),n._tempUnsub=void 0):this._subscribeTo(n)}},this.execute=()=>{if(this.isDisposed||this.isExecuting||!this._shouldExecute())return;this._checkInfiniteLoop(),this._setExecuting(!0),this._safeCleanup();const n=this._prepareEffectContext();let r=!1;try{const o=C.run(this,this._fn);this._commitEffect(n),r=!0,this._checkLoopWarnings(),Z(o)?o.then(d=>{!this.isDisposed&&typeof d=="function"&&(this._cleanup=d)}).catch(d=>{this._handleExecutionError(d)}):this._cleanup=typeof o=="function"?o:null}catch(o){r=!0,this._handleExecutionError(o),this._cleanup=null}finally{this._cleanupEffect(n,r),this._setExecuting(!1)}},this._currentEpoch=-1,this._lastFlushEpoch=-1,this._executionsInEpoch=0,this._fn=e,this._sync=t.sync??!1,this._maxExecutions=t.maxExecutionsPerSecond??g.MAX_EXECUTIONS_PER_SECOND,this._maxExecutionsPerFlush=t.maxExecutionsPerFlush??g.MAX_EXECUTIONS_PER_EFFECT,this._trackModifications=t.trackModifications??!1,this._cleanup=null,this._dependencies=_,this._dependencyVersions=a,this._unsubscribes=p,this._nextDeps=null,this._nextVersions=null,this._nextUnsubs=null,this._onError=t.onError??null,this._historyPtr=0;const i=Number.isFinite(this._maxExecutions);this._historyCapacity=i?Math.min(this._maxExecutions+1,g.MAX_EXECUTIONS_PER_SECOND+1):0,this._history=l&&i&&this._historyCapacity>0?new Array(this._historyCapacity).fill(0):null,this._executionCount=0,f.attachDebugInfo(this,"effect",this.id)}_prepareEffectContext(){const e=this._dependencies,t=this._dependencyVersions,i=this._unsubscribes,n=y.acquire(),r=b.acquire(),o=N.acquire(),d=J();if(e!==_&&i!==p)for(let T=0;T<e.length;T++){const S=e[T];S&&(S._tempUnsub=i[T])}return this._nextDeps=n,this._nextVersions=r,this._nextUnsubs=o,this._currentEpoch=d,{prevDeps:e,prevVersions:t,prevUnsubs:i,nextDeps:n,nextVersions:r,nextUnsubs:o}}_commitEffect(e){const t=e.nextDeps.length;e.nextDeps.length=t,e.nextVersions.length=t,this._dependencies=e.nextDeps,this._dependencyVersions=e.nextVersions,this._unsubscribes=e.nextUnsubs}_cleanupEffect(e,t){if(this._nextDeps=null,this._nextVersions=null,this._nextUnsubs=null,t){if(e.prevDeps!==_){for(let i=0;i<e.prevDeps.length;i++){const n=e.prevDeps[i];n?._tempUnsub&&(n._tempUnsub(),n._tempUnsub=void 0)}y.release(e.prevDeps)}e.prevUnsubs!==p&&N.release(e.prevUnsubs),e.prevVersions!==a&&b.release(e.prevVersions)}else{y.release(e.nextDeps),b.release(e.nextVersions);for(let i=0;i<e.nextUnsubs.length;i++)e.nextUnsubs[i]?.();if(N.release(e.nextUnsubs),e.prevDeps!==_)for(let i=0;i<e.prevDeps.length;i++){const n=e.prevDeps[i];n&&(n._tempUnsub=void 0)}}}_subscribeTo(e){try{const t=e.subscribe(()=>{this._trackModifications&&this.isExecuting&&(e._modifiedAtEpoch=this._currentEpoch),this._sync?this.execute():R.schedule(this.execute)});this._nextUnsubs&&this._nextUnsubs.push(t)}catch(t){console.error(x(t,D,u.EFFECT_EXECUTION_FAILED)),this._nextUnsubs&&this._nextUnsubs.push(()=>{})}}get isDisposed(){return(this.flags&F.DISPOSED)!==0}get executionCount(){return this._executionCount}get isExecuting(){return(this.flags&F.EXECUTING)!==0}_setDisposed(){this.flags|=F.DISPOSED}_setExecuting(e){const t=F.EXECUTING;this.flags=this.flags&~t|-Number(e)&t}_safeCleanup(){if(this._cleanup){try{this._cleanup()}catch(e){console.error(x(e,D,u.EFFECT_CLEANUP_FAILED))}this._cleanup=null}}_checkInfiniteLoop(){if(this._lastFlushEpoch!==P&&(this._lastFlushEpoch=P,this._executionsInEpoch=0),this._executionsInEpoch++,this._executionsInEpoch>this._maxExecutionsPerFlush&&this._throwInfiniteLoopError("per-effect"),_e()>g.MAX_EXECUTIONS_PER_FLUSH&&this._throwInfiniteLoopError("global"),this._executionCount++,this._history&&this._maxExecutions>0){const e=Date.now(),t=this._historyPtr,i=this._historyCapacity;this._history[t]=e;const n=(t+1)%i,r=this._history[n]??0;if(this._historyPtr=n,r>0&&e-r<A.ONE_SECOND_MS){const o=new D(`Effect executed ${i} times within 1 second. Infinite loop suspected`);if(this.dispose(),console.error(o),this._onError&&this._onError(o),l)throw o}}}_throwInfiniteLoopError(e){const t=new D(`Infinite loop detected (${e}): effect executed ${this._executionsInEpoch} times in current flush. Total executions in flush: ${B}`);throw this.dispose(),console.error(t),t}_shouldExecute(){if(this._dependencies===_||this._dependencyVersions===a)return!0;for(let e=0;e<this._dependencies.length;e++){const t=this._dependencies[e];if(t){if("value"in t)try{W(()=>t.value)}catch{return!0}if(t.version!==this._dependencyVersions[e])return!0}}return!1}_handleExecutionError(e){const t=x(e,D,u.EFFECT_EXECUTION_FAILED);console.error(t),this._onError&&this._onError(t)}_checkLoopWarnings(){if(this._trackModifications&&f.enabled){const e=this._dependencies;for(let t=0;t<e.length;t++){const i=e[t];i&&i._modifiedAtEpoch===this._currentEpoch&&f.warn(!0,`Effect is reading a dependency (${f.getDebugName(i)||"unknown"}) that it just modified. Infinite loop may occur`)}}}}function Ce(s,e={}){if(typeof s!="function")throw new D(u.EFFECT_MUST_BE_FUNCTION);const t=new me(s,e);return t.execute(),t}c.AsyncState=O,c.AtomError=E,c.ComputedError=m,c.DEBUG_CONFIG=w,c.DEBUG_RUNTIME=f,c.EffectError=D,c.POOL_CONFIG=ie,c.SCHEDULER_CONFIG=g,c.SchedulerError=U,c.atom=ye,c.batch=le,c.computed=Ie,c.effect=Ce,c.isAtom=K,c.isComputed=fe,c.isEffect=de,c.scheduler=R,c.untracked=W,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})}));
2
2
  //# sourceMappingURL=atom-effect.min.js.map