@but212/atom-effect 0.8.4 → 0.9.1

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,167 +12,144 @@ 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
+ ### CDN
23
16
 
24
- ```typescript
25
- import { atom, computed, effect, batch } from '@but212/atom-effect';
17
+ ```html
18
+ <script src="https://cdn.jsdelivr.net/npm/@but212/atom-effect@latest"></script>
19
+ <!-- or -->
20
+ <script src="https://unpkg.com/@but212/atom-effect@latest"></script>
21
+ ```
26
22
 
27
- // Create reactive state
28
- const count = atom(0);
29
- const name = atom('Alice');
23
+ ## Core API
30
24
 
31
- // Derived state
32
- const greeting = computed(() => `Hello, ${name.value}! Count: ${count.value}`);
25
+ ### `atom(value)`
33
26
 
34
- // Side effects with automatic cleanup
35
- const effectObj = effect(() => {
36
- console.log(greeting.value);
37
- });
27
+ Creates a mutable state container.
38
28
 
39
- // Batch updates for performance
40
- batch(() => {
41
- count.value = 1;
42
- name.value = 'Bob';
43
- }); // Effect runs only once
29
+ - **read**: `atom.value` (tracks dependency)
30
+ - **write**: `atom.value = newValue` (triggers effects)
31
+ - **peek**: `atom.peek()` (read without tracking)
44
32
 
45
- effectObj.dispose();
33
+ ```typescript
34
+ const count = atom(0);
35
+ count.value++;
36
+ console.log(count.value);
46
37
  ```
47
38
 
48
- ## Core API
39
+ ### `computed(fn)`
49
40
 
50
- ### `atom(initialValue, options?)`
41
+ Creates a derived value that automatically updates when dependencies change.
51
42
 
52
- Creates reactive state with automatic dependency tracking.
43
+ - Lazy evaluation (only computes when read or needed by an effect).
44
+ - Caches result until dependencies change.
53
45
 
54
46
  ```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}`);
63
- });
47
+ const double = computed(() => count.value * 2);
64
48
  ```
65
49
 
66
- **Options:** `{ sync: boolean }` - Synchronous updates (default: `false`)
50
+ ### `effect(fn)`
67
51
 
68
- ### `computed(fn, options?)`
52
+ Runs a function immediately and re-runs it whenever its dependencies change.
69
53
 
70
- Creates derived state that recomputes when dependencies change.
54
+ - Returns a `dispose` function to stop the effect.
71
55
 
72
56
  ```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
- );
57
+ const stop = effect(() => {
58
+ console.log(count.value);
59
+ });
60
+ stop();
85
61
  ```
86
62
 
87
- **Options:**
63
+ ### `batch(fn)`
88
64
 
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
65
+ Delays effect execution until the function completes.
93
66
 
94
- ### `effect(fn)`
67
+ ```typescript
68
+ batch(() => {
69
+ count.value = 1;
70
+ count.value = 2;
71
+ });
72
+ // Effects run once after the batch
73
+ ```
95
74
 
96
- Runs side effects with automatic dependency tracking and cleanup.
75
+ ### `untracked(fn)`
97
76
 
98
- ```typescript
99
- const count = atom(0);
77
+ Runs a function without tracking any dependencies accessed within it.
100
78
 
101
- const effectObj = effect(() => {
102
- console.log(`Count: ${count.value}`);
103
-
104
- // Optional cleanup
105
- return () => console.log('cleanup');
79
+ ```typescript
80
+ computed(() => {
81
+ // `count` is not tracked as a dependency here
82
+ return untracked(() => count.value * 2);
106
83
  });
107
-
108
- effectObj.dispose(); // Stop the effect
109
84
  ```
110
85
 
111
- **Options:**
86
+ ## API Reference
112
87
 
113
- - `sync` - Run synchronously (default: `false`)
114
- - `maxExecutionsPerFlush` - Maximum executions per flush cycle to prevent infinite loops (default: `SCHEDULER_CONFIG.MAX_EXECUTIONS_PER_FLUSH`)
88
+ ### Detailed Options
115
89
 
116
- ### `batch(fn)`
90
+ #### `atom(initialValue, options?)`
117
91
 
118
- Batches multiple updates to run effects only once.
92
+ - `name`: (string) Debug name.
119
93
 
120
- ```typescript
121
- const firstName = atom('John');
122
- const lastName = atom('Doe');
123
- const fullName = computed(() => `${firstName.value} ${lastName.value}`);
94
+ #### `computed(fn, options?)`
124
95
 
125
- effect(() => console.log(fullName.value));
96
+ - `equal`: (fn) Comparison function to skip re-computes.
97
+ - `defaultValue`: (any) Value to return when pending/error.
98
+ - `lazy`: (boolean) If true, defers evaluation until read.
126
99
 
127
- // Without batch - logs twice
128
- firstName.value = 'Jane';
129
- lastName.value = 'Smith';
100
+ #### `effect(fn, options?)`
130
101
 
131
- // With batch - logs once
132
- batch(() => {
133
- firstName.value = 'Alice';
134
- lastName.value = 'Johnson';
135
- });
102
+ - `sync`: (boolean) Runs synchronously on change.
103
+ - `onError`: (fn) Async error handler.
104
+ - `trackModifications`: (boolean) Warns on self-writes.
105
+
106
+ ### Advanced Usage
107
+
108
+ #### Async Computed
109
+
110
+ ```typescript
111
+ const userId = atom(1);
112
+ const user = computed(async () => {
113
+ const res = await fetch(`/api/users/${userId.value}`);
114
+ return res.json();
115
+ }, { defaultValue: { loading: true } });
136
116
  ```
137
117
 
138
- ### `untracked(fn)`
118
+ ## Utilities & Development
139
119
 
140
- Executes function without tracking dependencies.
120
+ ### Type Guards
141
121
 
142
122
  ```typescript
143
- const a = atom(1);
144
- const b = atom(2);
123
+ import { isAtom, isComputed, isReactive } from '@but212/atom-effect';
145
124
 
146
- const sum = computed(() => {
147
- const aValue = a.value; // Tracked
148
- const bValue = untracked(() => b.value); // NOT tracked
149
- return aValue + bValue;
150
- });
125
+ isAtom(count); // true
126
+ isReactive(double); // true
151
127
  ```
152
128
 
153
- ## Utilities
129
+ ### Development Commands
154
130
 
155
- Type guards (`isAtom`, `isComputed`, `isEffect`), configuration constants (`DEBUG_CONFIG`, `POOL_CONFIG`, `SCHEDULER_CONFIG`), and error classes (`AtomError`, `ComputedError`, `EffectError`) are available.
131
+ ```bash
132
+ pnpm test # Run unit tests
133
+ pnpm bench # Run benchmarks
134
+ pnpm lint # Run lint checks
135
+ pnpm build # Build production bundle
136
+ ```
156
137
 
157
138
  ## Performance
158
139
 
159
- | Operation | Performance |
160
- | --- | --- |
161
- | Atom creation | ~4.95M ops/sec |
162
- | Atom read/write | ~9.32M ops/sec |
163
- | Computed creation | ~1.75M ops/sec |
164
- | Computed recomputation | ~556K ops/sec |
165
- | Effect execution | ~4.57M ops/sec |
166
- | Batch update (2 atoms) | ~3.97M ops/sec |
167
- | Untracked read | ~6.01M ops/sec |
168
- | Deep chain (100 levels) | ~8.7K ops/sec |
169
-
170
- See [docs/BENCHMARKS.md](./docs/BENCHMARKS.md) for details.
140
+ Verified benchmarks vs object pooling and lazy evaluation optimizations.
171
141
 
172
- ## Development
142
+ > *Note: These numbers represent pure engine throughput in isolation. Actual app performance often depends on external factors like DOM updates and layout.*
173
143
 
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
- ```
144
+ | Operation | Performance |
145
+ | --- | --- |
146
+ | Atom creation | ~4.69M ops/sec |
147
+ | Atom read/write | ~9.52M ops/sec |
148
+ | Computed creation | ~1.80M ops/sec |
149
+ | Computed recomputation | ~583K ops/sec |
150
+ | Effect execution | ~2.96M ops/sec |
151
+ | Batched updates | ~3.82M ops/sec |
152
+ | Deep chain (100 levels) | ~8.2K ops/sec |
183
153
 
184
154
  ## Contributing
185
155
 
@@ -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"),B=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[B]=e},getDebugName(s){if(s!=null&&k in s)return s[k]},getDebugType(s){if(s!=null&&B in s)return s[B]}};let ce=1;const he=()=>ce++;class Y{constructor(){this.id=he()&I,this.flags=0}}class Q 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 H(){return v=v+1&I||1,v}function ue(){return v}let P=0,j=0,M=!1;function $(){return M?(l&&console.warn("Warning: startFlush() called during flush - ignored to prevent infinite loop detection bypass"),!1):(M=!0,P=P+1&I,j=0,!0)}function J(){M=!1}function ae(){return M?++j:0}class _e{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(){this.isProcessing||this.queueSize===0||(this.isProcessing=!0,queueMicrotask(()=>{try{if(this.queueSize===0)return;const e=$();this._drainQueue(),e&&J()}finally{this.isProcessing=!1,this.queueSize>0&&!this.isBatching&&this.flush()}}))}flushSync(){this.isFlushingSync=!0;const e=$();try{this._mergeBatchQueue(),this._drainQueue()}finally{this.isFlushingSync=!1,e&&J()}}_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 _e;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 q{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 a=Object.freeze([]),p=Object.freeze([]),_=Object.freeze([]),y=new q,N=new q,b=new q;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!==a&&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!==a)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 Q{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 Q{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=a,this._dependencyVersions=_,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!==_&&(b.release(this._dependencyVersions),this._dependencyVersions=_),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!==a&&(y.release(this._dependencies),this._dependencies=a),this._dependencyVersions!==_&&(b.release(this._dependencyVersions),this._dependencyVersions=_),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=H(),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!==a&&y.release(e.prevDeps),e.prevVersions!==_&&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!==_&&(b.release(this._dependencyVersions),this._dependencyVersions=_),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!==a&&(y.release(this._dependencies),this._dependencies=a),this._dependencyVersions!==_&&(b.release(this._dependencyVersions),this._dependencyVersions=_)}},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=a,this._dependencyVersions=_,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=H();if(e!==a&&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!==a){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!==_&&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!==a)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"),ae()>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: ${j}`);throw this.dispose(),console.error(t),t}_shouldExecute(){if(this._dependencies===a||this._dependencyVersions===_)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