@vielzeug/stateit 2.1.0 → 3.0.3

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
@@ -33,7 +33,7 @@ doubled.dispose();
33
33
 
34
34
  ## Store As Small Recipe
35
35
 
36
- `store()` is a thin object helper over `signal()` with immutable-style updates.
36
+ `store()` is a thin object helper over `signal()` with immutable-style updates. Stores expose the readable signal contract (`value`, `peek`, `subscribe`) plus object-focused mutation helpers.
37
37
 
38
38
  ```ts
39
39
  import { store } from '@vielzeug/stateit';
@@ -45,52 +45,63 @@ user.update((state) => ({ ...state, count: state.count + 1 }));
45
45
  user.reset();
46
46
  ```
47
47
 
48
- ## Watch Selector Overload
48
+ ## Watching Derived Values
49
49
 
50
- No intermediate selector signal is required.
50
+ Use `watch` with a getter function to watch any derived value directly:
51
51
 
52
52
  ```ts
53
53
  import { store, watch } from '@vielzeug/stateit';
54
54
 
55
55
  const cart = store({ count: 0, label: 'x' });
56
56
 
57
- const stop = watch(
58
- cart,
59
- (state) => state.count,
60
- (next, prev) => {
61
- console.log(prev, '->', next);
62
- },
63
- );
57
+ const stop = watch(() => cart.value.count, (next, prev) => {
58
+ console.log(prev, '->', next);
59
+ });
64
60
 
65
61
  stop();
66
62
  ```
67
63
 
64
+ ## Interop Helpers
65
+
66
+ Stateit stays framework-agnostic, but the core exports are designed to plug directly into common reactive contracts.
67
+
68
+ ```ts
69
+ import { computed, readonly, signal, toObservable, toStore } from '@vielzeug/stateit';
70
+
71
+ const count = signal(0);
72
+ const doubled = computed(() => count.value * 2);
73
+
74
+ const publicCount = readonly(count);
75
+ const svelteStore = toStore(doubled);
76
+ const observable = toObservable(publicCount);
77
+ ```
78
+
68
79
  ## Strict Runtime Rules
69
80
 
70
81
  - `onCleanup()` throws when called outside an active effect.
71
82
  - Reading a disposed computed signal throws.
72
- - Store misuse (non-object values) throws.
83
+ - Store constructor/patch misuse (non-object values) throws.
73
84
 
74
85
  ## API
75
86
 
76
87
  ```ts
88
+ type ObservableObserver<T> = { next(value: T): void };
89
+ type ObservableLike<T> = {
90
+ subscribe(observer: ObservableObserver<T> | ((value: T) => void)): { unsubscribe(): void };
91
+ };
92
+
77
93
  signal<T>(initial: T, options?: { equals?: (a: T, b: T) => boolean }): Signal<T>;
78
94
  computed<T>(compute: () => T, options?: { equals?: (a: T, b: T) => boolean }): ComputedSignal<T>;
79
- effect(fn: () => void | (() => void), options?: { maxIterations?: number }): Subscription;
95
+ effect(fn: () => void | (() => void)): Subscription;
80
96
  watch<T>(source: ReadonlySignal<T>, cb: (value: T, prev: T) => void, options?: WatchOptions<T>): Subscription;
81
- watch<S, T>(
82
- source: ReadonlySignal<S>,
83
- selector: (value: S) => T,
84
- cb: (value: T, prev: T) => void,
85
- options?: WatchOptions<T>,
86
- ): Subscription;
97
+ watch<T>(source: () => T, cb: (value: T, prev: T) => void, options?: WatchOptions<T>): Subscription;
87
98
  batch<T>(fn: () => T): T;
88
99
  untrack<T>(fn: () => T): T;
100
+ readonly<T>(source: ReadonlySignal<T>): ReadonlySignal<T>;
101
+ toStore<T>(source: ReadonlySignal<T>): { subscribe(run: (value: T) => void): Subscription };
102
+ toObservable<T>(source: ReadonlySignal<T>): ObservableLike<T>;
89
103
  onCleanup(fn: () => void): void;
90
- store<T extends object>(initial: T, options?: { equals?: (a: T, b: T) => boolean }): Store<T>;
91
- readonly<T>(input: ReadonlySignal<T>): ReadonlySignal<T>;
92
- writable<T>(input: Signal<T>): Signal<T>;
104
+ scope(setup?: () => void): Scope;
105
+ store<T extends object>(initial: T): Store<T>;
93
106
  isSignal<T>(value: unknown): value is ReadonlySignal<T>;
94
- peekValue<T>(input: T | ReadonlySignal<T>): T;
95
- toValue<T>(input: T | ReadonlySignal<T> | (() => T)): T;
96
107
  ```
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./stateit.cjs`);exports.batch=e.batch,exports.computed=e.computed,exports.effect=e.effect,exports.isSignal=e.isSignal,exports.onCleanup=e.onCleanup,exports.peekValue=e.peekValue,exports.readonly=e.readonly,exports.signal=e.signal,exports.store=e.store,exports.toValue=e.toValue,exports.untrack=e.untrack,exports.watch=e.watch,exports.writable=e.writable;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./stateit.cjs`);exports.batch=e.batch,exports.computed=e.computed,exports.effect=e.effect,exports.isSignal=e.isSignal,exports.observableSymbol=e.observableSymbol,exports.onCleanup=e.onCleanup,exports.readonly=e.readonly,exports.scope=e.scope,exports.signal=e.signal,exports.store=e.store,exports.toObservable=e.toObservable,exports.toStore=e.toStore,exports.toSubscription=e.toSubscription,exports.untrack=e.untrack,exports.watch=e.watch;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
- export { batch, computed, effect, isSignal, onCleanup, peekValue, readonly, signal, store, toValue, untrack, watch, writable, } from './stateit';
2
- export * from './types';
1
+ export * from './stateit';
3
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,SAAS,EACT,SAAS,EACT,QAAQ,EACR,MAAM,EACN,KAAK,EACL,OAAO,EACP,OAAO,EACP,KAAK,EACL,QAAQ,GACT,MAAM,WAAW,CAAC;AAEnB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { batch as e, computed as t, effect as n, isSignal as r, onCleanup as i, peekValue as a, readonly as o, signal as s, store as c, toValue as l, untrack as u, watch as d, writable as f } from "./stateit.js";
2
- export { e as batch, t as computed, n as effect, r as isSignal, i as onCleanup, a as peekValue, o as readonly, s as signal, c as store, l as toValue, u as untrack, d as watch, f as writable };
1
+ import { batch as e, computed as t, effect as n, isSignal as r, observableSymbol as i, onCleanup as a, readonly as o, scope as s, signal as c, store as l, toObservable as u, toStore as d, toSubscription as f, untrack as p, watch as m } from "./stateit.js";
2
+ export { e as batch, t as computed, n as effect, r as isSignal, i as observableSymbol, a as onCleanup, o as readonly, s as scope, c as signal, l as store, u as toObservable, d as toStore, f as toSubscription, p as untrack, m as watch };
package/dist/stateit.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Symbol(`stateit.uninitialized`),t=100,n=e=>Object.assign(e,{dispose:e,[Symbol.dispose]:e}),r=(e,t)=>{if(typeof e!=`object`||!e||Array.isArray(e))throw TypeError(t)},i=e=>structuredClone(e),a=(e,t)=>{let n=[];for(let t of e)try{t()}catch(e){n.push(e)}if(n.length===1)throw n[0];if(n.length>1)throw AggregateError(n,`[stateit] ${t}`)},o=e=>{let t=[];for(let n of[...e])try{n()}catch(e){t.push(e)}if(t.length===1)throw t[0];if(t.length>1)throw AggregateError(t,`[stateit] subscriber errors`)},s={cleanups:null,deps:null,effect:null},c=(e,t,n,r)=>{let i=s;s={cleanups:n,deps:t,effect:e};try{return r()}finally{s=i}},l=0,u=new Set,d=()=>{for(;u.size>0;){let e=[...u];u.clear(),o(new Set(e))}},f=class{subscribers=new Set;track(){!s.effect||!s.deps||(this.subscribers.add(s.effect),s.deps.add(()=>this.subscribers.delete(s.effect)))}hasSubscribers(){return this.subscribers.size>0}notify(){if(this.subscribers.size!==0){if(l>0){for(let e of this.subscribers)u.add(e);return}o(this.subscribers)}}},p=class extends f{value_;equals_;constructor(e,t){super(),this.value_=e,this.equals_=t??Object.is}get value(){return this.track(),this.value_}set value(e){this.equals_(this.value_,e)||(this.value_=e,this.notify())}update(e){this.value=e(this.value_)}},m=class extends f{value_=e;dirty_=!0;disposed_=!1;deps_=new Set;compute_;equals_;onDepChange=()=>{if(!this.disposed_){if(this.subscribers.size===0){this.dirty_=!0;return}this.recompute()&&this.notify()}};constructor(e,t){super(),this.compute_=e,this.equals_=t??Object.is,this.recompute()}recompute(){for(let e of this.deps_)e();this.deps_.clear();let t=c(this.onDepChange,this.deps_,null,this.compute_);return this.dirty_=!1,this.value_===e||!this.equals_(this.value_,t)?(this.value_=t,!0):!1}get value(){if(this.disposed_)throw Error(`[stateit] Cannot read disposed computed signal`);return this.dirty_&&this.recompute(),this.track(),this.value_}get stale(){return this.dirty_}dispose(){if(!this.disposed_){this.disposed_=!0,this.dirty_=!0;for(let e of this.deps_)e();this.deps_.clear()}}[Symbol.dispose](){this.dispose()}},h=(e,t)=>new p(e,t?.equals),g=(e,t)=>{let n=new m(e,t?.equals);return s.effect!==null&&s.cleanups!==null&&b(()=>n.dispose()),n},_=e=>{l++;try{let t=e();return--l===0&&d(),t}catch(e){throw--l===0&&d(),e}},v=(e,r)=>{let i,o=new Set,s=!1,l=!1,u=!1,d=r?.maxIterations??t,f=()=>{let e=[];i&&e.push(i),i=void 0;for(let t of o)e.push(t);o.clear(),a(e,`effect teardown errors`)},p=()=>{if(!u){if(s){l=!0;return}s=!0;try{let t=0;do{if(++t>d)throw Error(`[stateit] infinite effect loop (> ${d} iterations)`);l=!1,f();let n=[],r=c(p,o,n,e);r&&n.push(r),n.length>0&&(i=()=>{a(n,`effect cleanup errors`)})}while(l&&!u)}finally{s=!1}}};return p(),n(()=>{u||(u=!0,f())})},y=e=>c(null,null,null,e),b=e=>{if(s.cleanups===null)throw Error(`[stateit] onCleanup() must be called from inside an active effect.`);s.cleanups.push(e)},x=(e,t,n)=>{let r=n?.equals??Object.is,i=y(()=>e.value);n?.immediate&&t(i,i);let a=v(()=>{let o=e.value;if(r(i,o))return;let s=i;i=o,t(o,s),n?.once&&a()});return a};function S(e,t,r,i){if(typeof r==`function`){let a=t,o=r,s=g(()=>a(e.value)),c=x(s,o,i);return n(()=>{c(),s.dispose()})}return x(e,t,r)}var C=(e,t)=>{r(e,`[stateit] store() requires a plain object initial state.`);let n=i(e),a=h(i(e),t);return{patch(e){if(typeof e!=`object`||!e||Array.isArray(e))throw TypeError(`[stateit] store.patch() requires a plain object partial.`);a.value={...a.value,...e}},reset(){a.value=i(n)},update(e){let t=e(a.value);r(t,`[stateit] store.update() must return a plain object.`),a.value=t},get value(){return a.value},set value(e){r(e,`[stateit] Store value must always be a plain object.`),a.value=e}}},w=e=>e,T=e=>e,E=e=>typeof e!=`object`||!e?!1:`value`in e,D=e=>E(e)?e.value:e,O=e=>E(e)?e.value:typeof e==`function`?e():e;exports.batch=_,exports.computed=g,exports.effect=v,exports.isSignal=E,exports.onCleanup=b,exports.peekValue=D,exports.readonly=w,exports.signal=h,exports.store=C,exports.toValue=O,exports.untrack=y,exports.watch=S,exports.writable=T;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=100,t=Symbol(`stateit.is-signal`),n=Symbol.observable??Symbol.for(`observable`),r=n,i=e=>Object.assign(e,{dispose:e,[Symbol.dispose]:e}),a=new WeakMap,o=e=>e instanceof Error?e:Error(String(e)),s=(e,t)=>{if(typeof e!=`object`||!e||Array.isArray(e))throw TypeError(t)},c=(e,t)=>{let n=[];for(let t of e)try{t()}catch(e){n.push(e)}if(n.length===1)throw n[0];if(n.length>1)throw AggregateError(n,`[stateit] ${t}`)},l=(e,t,n)=>{let r=o(e);throw t.length===0?r:AggregateError([r,...t.map(o)],`[stateit] ${n}`,{cause:r})},u=e=>{try{return c(e,`cleanup errors`),[]}catch(e){return e instanceof AggregateError?e.errors:[e]}},d=null,f=null,p=null,m=null,h=(e,t,n,r,i)=>{let a=d,o=f,s=p,c=m;d=e,f=t,p=n,m=r;try{return i()}finally{d=a,f=o,p=s,m=c}},g=0,_=new Set,v=new Set,y=e=>{let t=new Set(e),n=new Map;for(let t of e)n.set(t,0);for(let r of e)for(let e of r.computedSubscribers())t.has(e)&&n.set(e,(n.get(e)??0)+1);let r=[];for(let t of e)(n.get(t)??0)===0&&r.push(t);let i=[];for(;r.length>0;){let e=r.shift();i.push(e);for(let i of e.computedSubscribers()){if(!t.has(i))continue;let e=(n.get(i)??0)-1;n.set(i,e),e===0&&r.push(i)}}if(i.length<e.length)for(let t of e)i.includes(t)||i.push(t);return i},b=e=>{let t=[...e.computedSubscribers()],n=new Set;for(let t of e.subscribers())_.add(t);for(;t.length>0;){let e=t.pop();if(!n.has(e)&&(n.add(e),e.markDirty())){v.add(e);for(let n of e.computedSubscribers())t.push(n)}}},x=()=>{for(;v.size>0;){let e=y([...v]);v.clear();for(let t of e)if(t.hasAnySubscribers()&&t.refreshIfDirty()){for(let e of t.subscribers())_.add(e);for(let e of t.computedSubscribers())e.markDirty()&&v.add(e)}}},S=()=>{let t=0;for(;_.size>0||v.size>0;){if(++t>e)throw Error(`[stateit] infinite flush loop (> ${e} iterations)`);if(v.size>0&&x(),_.size===0)continue;let n=[..._];_.clear(),c(n,`subscriber errors`)}},C=e=>{e.hasAnySubscribers()&&(b(e),g===0&&S())},w=class{computedSubs_=new Set;subscribers_=new Set;track(){if(p){if(f!==null){let e=f;this.computedSubs_.add(e),p.add(()=>this.computedSubs_.delete(e));return}if(d!==null){let e=d;this.subscribers_.add(e),p.add(()=>this.subscribers_.delete(e))}}}notify(){C(this)}hasAnySubscribers(){return this.computedSubs_.size>0||this.subscribers_.size>0}computedSubscribers(){return this.computedSubs_}subscribers(){return this.subscribers_}subscribe(e){return this.subscribers_.add(e),i(()=>{this.subscribers_.delete(e)})}},T=class extends w{value_;equals_;[t]=!0;constructor(e,t){super(),this.value_=e,this.equals_=t??Object.is}get value(){return this.track(),this.value_}peek(){return this.value_}subscribe=e=>super.subscribe(e);update(e){this.value=e(this.value_)}set value(e){this.equals_(this.value_,e)||(this.value_=e,this.notify())}},E=class extends w{hasValue_=!1;value_;dirty_=!0;computing_=!1;disposed_=!1;deps_=new Set;compute_;equals_;[t]=!0;constructor(e,t){super(),this.compute_=e,this.equals_=t??Object.is}markDirty(){return this.disposed_||this.dirty_?!1:(this.dirty_=!0,!0)}refreshIfDirty(){return this.dirty_?this.recompute():!1}recompute(){if(this.computing_)throw Error(`[stateit] computed cycle detected`);for(let e of this.deps_)e();this.deps_.clear(),this.computing_=!0;try{let e=h(null,this,this.deps_,null,this.compute_);return this.dirty_=!1,!this.hasValue_||!this.equals_(this.value_,e)?(this.hasValue_=!0,this.value_=e,!0):!1}catch(e){let t=u(this.deps_);return this.deps_.clear(),l(e,t,`computed failed dependency cleanup errors`)}finally{this.computing_=!1}}get value(){if(this.disposed_)throw Error(`[stateit] Cannot read disposed computed signal`);return this.refreshIfDirty(),this.track(),this.value_}peek(){if(this.disposed_)throw Error(`[stateit] Cannot read disposed computed signal`);return this.refreshIfDirty(),this.value_}subscribe=e=>{if(this.disposed_)throw Error(`[stateit] Cannot subscribe to a disposed computed signal`);return this.refreshIfDirty(),super.subscribe(e)};dispose(){if(!this.disposed_){this.disposed_=!0;for(let e of this.deps_)e();this.deps_.clear()}}[Symbol.dispose](){this.dispose()}},D=(e,t)=>new T(e,t?.equals),O=(e,t)=>{let n=new E(e,t?.equals);return m!==null&&F(()=>n.dispose()),n},k=e=>{g++;let t,n;try{t=e()}catch(e){n=e}if(g--,g===0)try{S()}catch(e){throw n===void 0?o(e):AggregateError([n,e],`[stateit] batch error with flush errors`,{cause:e})}if(n!==void 0)throw o(n);return t},A=t=>{let n,r=new Set,a=!1,o=!1,s=!1,d=()=>{if(!n&&r.size===0)return;let e=n?[n,...r]:[...r];n=void 0,r.clear(),c(e,`effect teardown errors`)},f=()=>{if(!s){if(a){o=!0;return}a=!0;try{let i=0;do{if(++i>e)throw Error(`[stateit] infinite effect loop (> ${e} iterations)`);o=!1,d();let a=[],s;try{s=h(f,null,r,a,t)}catch(e){let t=[...u(r),...u(a)];r.clear(),l(e,t,`effect failure with cleanup errors`)}typeof s==`function`&&a.push(s),n=a.length>0?()=>{c(a,`effect cleanup errors`)}:void 0}while(o&&!s)}finally{a=!1}}};return f(),i(()=>{s||(s=!0,d())})},j=e=>h(null,null,null,null,e),M=e=>{let t=e,n=a.get(t);if(n)return n;let r={peek(){return e.peek()},subscribe(t){return e.subscribe(t)},get value(){return e.value}};return a.set(t,r),r},N=e=>({subscribe(t){return t(e.value),e.subscribe(()=>t(e.value))}}),P=e=>{let t=t=>{let n=typeof t==`function`?{next:t}:t;n.next?.(e.value);let r=e.subscribe(()=>n.next?.(e.value));return{unsubscribe(){r()}}},r={[n](){return r},subscribe:t};return r},F=e=>{if(m===null)throw Error(`[stateit] onCleanup() must be called from within an active effect or scope.`);m.push(e)},I=e=>{let t=[],n=!1,r=e=>{if(n)throw Error(`[stateit] Cannot run inside a disposed scope.`);return h(null,null,null,t,e)},i=()=>{n||(n=!0,c([...t].reverse(),`scope cleanup errors`),t.length=0)},a={dispose:i,run:r,[Symbol.dispose]:i};return e&&r(e),a};function L(e,t,n){let r=typeof e==`function`?e:()=>e.value,i=n?.equals??Object.is,a=!1,o;return n?.immediate&&(o=j(r),a=!0,t(o,o)),A(()=>{let e=r();if(!a){a=!0,o=e;return}if(i(o,e))return;let n=o;o=e,t(e,n)})}var R=e=>{s(e,`[stateit] store() requires a plain object initial state.`);let n=structuredClone(e),r=D(structuredClone(e));return{[t]:!0,patch(e){s(e,`[stateit] store.patch() requires a plain object partial.`);let t=j(()=>r.value);Object.keys(e).some(n=>!Object.is(t[n],e[n]))&&(r.value={...t,...e})},peek(){return r.peek()},reset(){r.value=structuredClone(n)},subscribe(e){return r.subscribe(e)},update(e){r.update(e)},get value(){return r.value}}},z=e=>typeof e==`object`&&!!e&&!!e[t];exports.batch=k,exports.computed=O,exports.effect=A,exports.isSignal=z,exports.observableSymbol=r,exports.onCleanup=F,exports.readonly=M,exports.scope=I,exports.signal=D,exports.store=R,exports.toObservable=P,exports.toStore=N,exports.toSubscription=i,exports.untrack=j,exports.watch=L;
2
2
  //# sourceMappingURL=stateit.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"stateit.cjs","names":[],"sources":["../src/stateit.ts"],"sourcesContent":["import type {\n CleanupFn,\n ComputedSignal,\n EffectCallback,\n EffectOptions,\n EqualityFn,\n ReactiveOptions,\n ReadonlySignal,\n Signal,\n Store,\n Subscription,\n WatchOptions,\n} from './types';\n\n// === CONSTANTS ===\nconst UNINITIALIZED = Symbol('stateit.uninitialized');\nconst DEFAULT_MAX_ITERATIONS = 100;\n\n// === HELPERS ===\nconst toSubscription = (dispose: () => void): Subscription =>\n Object.assign(dispose, { dispose, [Symbol.dispose]: dispose }) as Subscription;\n\nconst ensureObject = (value: unknown, message: string): void => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new TypeError(message);\n }\n};\n\nconst clone = <T>(value: T): T => structuredClone(value);\n\n// === UNIFIED ERROR HANDLING ===\nconst runCallbacks = (callbacks: CleanupFn[], context: string): void => {\n const errors: unknown[] = [];\n\n for (const callback of callbacks) {\n try {\n callback();\n } catch (e) {\n errors.push(e);\n }\n }\n\n if (errors.length === 1) throw errors[0];\n\n if (errors.length > 1) {\n throw new AggregateError(errors, `[stateit] ${context}`);\n }\n};\n\nconst runSubscribers = (subscribers: Set<EffectCallback>): void => {\n const errors: unknown[] = [];\n\n for (const fn of [...subscribers]) {\n try {\n fn();\n } catch (e) {\n errors.push(e);\n }\n }\n\n if (errors.length === 1) throw errors[0];\n\n if (errors.length > 1) {\n throw new AggregateError(errors, '[stateit] subscriber errors');\n }\n};\n\n// === GLOBAL REACTIVE GRAPH ===\ninterface EffectScope {\n effect: EffectCallback | null;\n deps: Set<CleanupFn> | null;\n cleanups: CleanupFn[] | null;\n}\n\nlet currentScope: EffectScope = {\n cleanups: null,\n deps: null,\n effect: null,\n};\n\nconst withScope = <T>(\n effect: EffectCallback | null,\n deps: Set<CleanupFn> | null,\n cleanups: CleanupFn[] | null,\n fn: () => T,\n): T => {\n const prev = currentScope;\n\n currentScope = { cleanups, deps, effect };\n\n try {\n return fn();\n } finally {\n currentScope = prev;\n }\n};\n\n// === BATCH QUEUE ===\nlet batchDepth = 0;\nconst batchQueue = new Set<EffectCallback>();\n\nconst flushBatch = (): void => {\n while (batchQueue.size > 0) {\n const pending = [...batchQueue];\n\n batchQueue.clear();\n\n runSubscribers(new Set(pending));\n }\n};\n\n// === BASE REACTIVE NODE ===\nclass ReactiveNode {\n protected subscribers = new Set<EffectCallback>();\n\n protected track(): void {\n if (!currentScope.effect || !currentScope.deps) return;\n\n this.subscribers.add(currentScope.effect);\n currentScope.deps.add(() => this.subscribers.delete(currentScope.effect!));\n }\n\n protected hasSubscribers(): boolean {\n return this.subscribers.size > 0;\n }\n\n protected notify(): void {\n if (this.subscribers.size === 0) return;\n\n if (batchDepth > 0) {\n for (const fn of this.subscribers) batchQueue.add(fn);\n\n return;\n }\n\n runSubscribers(this.subscribers);\n }\n}\n\n// === SIGNAL IMPLEMENTATION ===\nclass SignalImpl<T> extends ReactiveNode implements Signal<T> {\n private value_: T;\n private equals_: EqualityFn<T>;\n\n constructor(initial: T, equals?: EqualityFn<T>) {\n super();\n this.value_ = initial;\n this.equals_ = equals ?? Object.is;\n }\n\n get value(): T {\n this.track();\n\n return this.value_;\n }\n\n set value(next: T) {\n if (this.equals_(this.value_, next)) return;\n\n this.value_ = next;\n this.notify();\n }\n\n update(fn: (current: T) => T): void {\n this.value = fn(this.value_);\n }\n}\n\n// === COMPUTED IMPLEMENTATION ===\nclass ComputedImpl<T> extends ReactiveNode implements ComputedSignal<T> {\n private value_: T | typeof UNINITIALIZED = UNINITIALIZED;\n private dirty_ = true;\n private disposed_ = false;\n private deps_ = new Set<CleanupFn>();\n private compute_: () => T;\n private equals_: EqualityFn<T>;\n\n private readonly onDepChange: EffectCallback = () => {\n if (this.disposed_) return;\n\n if (this.subscribers.size === 0) {\n this.dirty_ = true;\n\n return;\n }\n\n if (this.recompute()) this.notify();\n };\n\n constructor(compute: () => T, equals?: EqualityFn<T>) {\n super();\n this.compute_ = compute;\n this.equals_ = equals ?? Object.is;\n this.recompute();\n }\n\n private recompute(): boolean {\n for (const unsub of this.deps_) unsub();\n this.deps_.clear();\n\n const next = withScope(this.onDepChange, this.deps_, null, this.compute_);\n\n this.dirty_ = false;\n\n if (this.value_ === UNINITIALIZED || !this.equals_(this.value_ as T, next)) {\n this.value_ = next;\n\n return true;\n }\n\n return false;\n }\n\n get value(): T {\n if (this.disposed_) {\n throw new Error('[stateit] Cannot read disposed computed signal');\n }\n\n if (this.dirty_) this.recompute();\n\n this.track();\n\n return this.value_ as T;\n }\n\n get stale(): boolean {\n return this.dirty_;\n }\n\n dispose(): void {\n if (this.disposed_) return;\n\n this.disposed_ = true;\n this.dirty_ = true;\n for (const unsub of this.deps_) unsub();\n this.deps_.clear();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\n// === CORE API ===\n\nexport const signal = <T>(initial: T, options?: ReactiveOptions<T>): Signal<T> =>\n new SignalImpl(initial, options?.equals);\n\nexport const computed = <T>(compute: () => T, options?: ReactiveOptions<T>): ComputedSignal<T> => {\n const comp = new ComputedImpl(compute, options?.equals);\n\n // Auto-dispose when created inside effect\n if (currentScope.effect !== null && currentScope.cleanups !== null) {\n onCleanup(() => comp.dispose());\n }\n\n return comp;\n};\n\nexport const batch = <T>(fn: () => T): T => {\n batchDepth++;\n\n try {\n const result = fn();\n\n if (--batchDepth === 0) flushBatch();\n\n return result;\n } catch (e) {\n if (--batchDepth === 0) flushBatch();\n\n throw e;\n }\n};\n\nexport const effect = (fn: EffectCallback, options?: EffectOptions): Subscription => {\n let cleanup: CleanupFn | undefined;\n const deps = new Set<CleanupFn>();\n let isRunning = false;\n let isDirty = false;\n let isDisposed = false;\n const maxIterations = options?.maxIterations ?? DEFAULT_MAX_ITERATIONS;\n\n const teardown = (): void => {\n const callbacks: CleanupFn[] = [];\n\n if (cleanup) callbacks.push(cleanup);\n\n cleanup = undefined;\n\n for (const unsub of deps) callbacks.push(unsub);\n deps.clear();\n\n runCallbacks(callbacks, 'effect teardown errors');\n };\n\n const run = (): void => {\n if (isDisposed) return;\n\n if (isRunning) {\n isDirty = true;\n\n return;\n }\n\n isRunning = true;\n\n try {\n let iterations = 0;\n\n do {\n if (++iterations > maxIterations) {\n throw new Error(`[stateit] infinite effect loop (> ${maxIterations} iterations)`);\n }\n\n isDirty = false;\n teardown();\n\n const localCleanups: CleanupFn[] = [];\n const returnedCleanup = withScope(run, deps, localCleanups, fn);\n\n if (returnedCleanup) localCleanups.push(returnedCleanup);\n\n if (localCleanups.length > 0) {\n cleanup = () => {\n runCallbacks(localCleanups, 'effect cleanup errors');\n };\n }\n } while (isDirty && !isDisposed);\n } finally {\n isRunning = false;\n }\n };\n\n run();\n\n return toSubscription(() => {\n if (isDisposed) return;\n\n isDisposed = true;\n teardown();\n });\n};\n\nexport const untrack = <T>(fn: () => T): T => {\n return withScope(null, null, null, fn);\n};\n\nexport const onCleanup = (fn: CleanupFn): void => {\n if (currentScope.cleanups === null) {\n throw new Error('[stateit] onCleanup() must be called from inside an active effect.');\n }\n\n currentScope.cleanups.push(fn);\n};\n\nconst watchBase = <T>(\n source: ReadonlySignal<T>,\n cb: (value: T, prev: T) => void,\n watchOptions?: WatchOptions<T>,\n): Subscription => {\n const equals = watchOptions?.equals ?? Object.is;\n let prev = untrack(() => source.value);\n\n if (watchOptions?.immediate) cb(prev, prev);\n\n const stop = effect(() => {\n const next = source.value;\n\n if (equals(prev, next)) return;\n\n const old = prev;\n\n prev = next;\n cb(next, old);\n\n if (watchOptions?.once) stop();\n });\n\n return stop;\n};\n\nfunction watch<T>(\n source: ReadonlySignal<T>,\n cb: (value: T, prev: T) => void,\n watchOptions?: WatchOptions<T>,\n): Subscription;\nfunction watch<S, T>(\n source: ReadonlySignal<S>,\n selector: (value: S) => T,\n cb: (value: T, prev: T) => void,\n watchOptions?: WatchOptions<T>,\n): Subscription;\nfunction watch<S, T>(\n source: ReadonlySignal<S>,\n selectorOrCb: ((value: S) => T) | ((value: S, prev: S) => void),\n maybeCb?: ((value: T, prev: T) => void) | WatchOptions<S>,\n maybeOptions?: WatchOptions<T>,\n): Subscription {\n if (typeof maybeCb === 'function') {\n const selector = selectorOrCb as (value: S) => T;\n const cb = maybeCb as (value: T, prev: T) => void;\n const selected = computed(() => selector(source.value));\n const stop = watchBase(selected, cb, maybeOptions);\n\n return toSubscription(() => {\n stop();\n selected.dispose();\n });\n }\n\n const cb = selectorOrCb as (value: S, prev: S) => void;\n\n return watchBase(source, cb, maybeCb as WatchOptions<S> | undefined);\n}\n\nexport { watch };\n\nexport const store = <T extends object>(initial: T, storeOptions?: ReactiveOptions<T>): Store<T> => {\n ensureObject(initial, '[stateit] store() requires a plain object initial state.');\n\n const initialSnapshot = clone(initial);\n const state = signal(clone(initial), storeOptions);\n\n return {\n patch(partial: Partial<T>): void {\n if (typeof partial !== 'object' || partial === null || Array.isArray(partial)) {\n throw new TypeError('[stateit] store.patch() requires a plain object partial.');\n }\n\n state.value = { ...state.value, ...partial };\n },\n reset(): void {\n state.value = clone(initialSnapshot);\n },\n update(fn: (current: T) => T): void {\n const next = fn(state.value);\n\n ensureObject(next, '[stateit] store.update() must return a plain object.');\n state.value = next;\n },\n get value(): T {\n return state.value;\n },\n set value(next: T) {\n ensureObject(next, '[stateit] Store value must always be a plain object.');\n state.value = next;\n },\n };\n};\n\n// === TYPE HELPERS ===\n\nexport const readonly = <T>(input: ReadonlySignal<T>): ReadonlySignal<T> => input;\n\nexport const writable = <T>(input: Signal<T>): Signal<T> => input;\n\nexport const isSignal = <T = unknown>(value: unknown): value is ReadonlySignal<T> => {\n if (typeof value !== 'object' || value === null) return false;\n\n const candidate = value as Partial<ReadonlySignal<T>>;\n\n return 'value' in candidate;\n};\n\nexport const peekValue = <T>(input: T | ReadonlySignal<T>): T => (isSignal<T>(input) ? input.value : input);\n\nexport const toValue = <T>(input: T | ReadonlySignal<T> | (() => T)): T => {\n if (isSignal<T>(input)) return input.value;\n\n if (typeof input === 'function') return (input as () => T)();\n\n return input;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"stateit.cjs","names":[],"sources":["../src/stateit.ts"],"sourcesContent":["// === TYPES ===\nexport type CleanupFn = () => void;\nexport type EffectCallback = () => CleanupFn | void;\nexport type EqualityFn<T> = (a: T, b: T) => boolean;\nexport type ReactiveOptions<T> = { equals?: EqualityFn<T> };\n\nexport interface Subscription {\n (): void;\n dispose(): void;\n [Symbol.dispose](): void;\n}\n\nexport interface ReadonlySignal<T> {\n peek(): T;\n subscribe(onStoreChange: () => void): Subscription;\n readonly value: T;\n}\n\nexport interface Signal<T> extends ReadonlySignal<T> {\n update(fn: (current: T) => T): void;\n value: T;\n}\n\nexport interface ComputedSignal<T> extends ReadonlySignal<T> {\n dispose(): void;\n [Symbol.dispose](): void;\n}\n\nexport type WatchOptions<T> = {\n equals?: EqualityFn<T>;\n immediate?: boolean;\n};\n\nexport interface ObservableObserver<T> {\n complete?(): void;\n error?(error: unknown): void;\n next?(value: T): void;\n}\n\nexport interface Store<T extends object> extends ReadonlySignal<T> {\n patch(partial: Partial<T>): void;\n update(fn: (state: T) => T): void;\n reset(): void;\n}\n\nexport interface Scope {\n readonly run: <T>(fn: () => T) => T;\n readonly dispose: () => void;\n readonly [Symbol.dispose]: () => void;\n}\n\n// === CONSTANTS ===\nconst DEFAULT_MAX_ITERATIONS = 100;\nconst IS_SIGNAL = Symbol('stateit.is-signal');\nconst OBSERVABLE_SYMBOL: unique symbol = ((Symbol as typeof Symbol & { observable?: symbol }).observable ??\n Symbol.for('observable')) as never;\n\nexport const observableSymbol = OBSERVABLE_SYMBOL;\n\ntype EffectRunner = () => void;\ntype Subscriber = () => void;\n\nexport type ObservableLike<T> = {\n [observableSymbol](): ObservableLike<T>;\n subscribe(observer: ObservableObserver<T> | ((value: T) => void)): { unsubscribe(): void };\n};\n\n// === HELPERS ===\nexport const toSubscription = (dispose: () => void): Subscription =>\n Object.assign(dispose, { dispose, [Symbol.dispose]: dispose }) as Subscription;\n\nconst readonlyCache = new WeakMap<object, ReadonlySignal<unknown>>();\n\nconst ensureError = (error: unknown): Error => (error instanceof Error ? error : new Error(String(error)));\n\nconst ensureObject = (value: unknown, message: string): void => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new TypeError(message);\n }\n};\n\nconst runAll = (items: Iterable<() => void>, context: string): void => {\n const errors: unknown[] = [];\n\n for (const fn of items) {\n try {\n fn();\n } catch (e) {\n errors.push(e);\n }\n }\n\n if (errors.length === 1) throw errors[0];\n\n if (errors.length > 1) {\n throw new AggregateError(errors, `[stateit] ${context}`);\n }\n};\n\nconst rethrowWithCleanupErrors = (error: unknown, cleanupErrors: unknown[], context: string): never => {\n const rootCause = ensureError(error);\n\n if (cleanupErrors.length === 0) {\n throw rootCause;\n }\n\n throw new AggregateError([rootCause, ...cleanupErrors.map(ensureError)], `[stateit] ${context}`, {\n cause: rootCause,\n });\n};\n\nconst runCleanupAndCollectErrors = (items: Iterable<() => void>): unknown[] => {\n try {\n runAll(items, 'cleanup errors');\n\n return [];\n } catch (error) {\n return error instanceof AggregateError ? error.errors : [error];\n }\n};\n\n// === GLOBAL TRACKING STATE ===\nlet currentEffect: EffectRunner | null = null;\nlet currentComputed: ComputedImpl<any> | null = null;\nlet currentDeps: Set<CleanupFn> | null = null;\nlet currentCleanups: CleanupFn[] | null = null;\n\nconst withTracking = <T>(\n effect: EffectRunner | null,\n computed: ComputedImpl<any> | null,\n deps: Set<CleanupFn> | null,\n cleanups: CleanupFn[] | null,\n fn: () => T,\n): T => {\n const prevEffect = currentEffect;\n const prevComputed = currentComputed;\n const prevDeps = currentDeps;\n const prevCleanups = currentCleanups;\n\n currentEffect = effect;\n currentComputed = computed;\n currentDeps = deps;\n currentCleanups = cleanups;\n\n try {\n return fn();\n } finally {\n currentEffect = prevEffect;\n currentComputed = prevComputed;\n currentDeps = prevDeps;\n currentCleanups = prevCleanups;\n }\n};\n\n// === NOTIFICATION QUEUES ===\nlet batchDepth = 0;\nconst pendingSubscribers = new Set<Subscriber>();\nconst pendingDirtyComputeds = new Set<ComputedImpl<any>>();\n\nconst toTopologicalOrder = (dirtyComputeds: readonly ComputedImpl<any>[]): ComputedImpl<any>[] => {\n const pendingSet = new Set(dirtyComputeds);\n const indegree = new Map<ComputedImpl<any>, number>();\n\n for (const computed of dirtyComputeds) {\n indegree.set(computed, 0);\n }\n\n for (const computed of dirtyComputeds) {\n for (const downstream of computed.computedSubscribers()) {\n if (!pendingSet.has(downstream)) continue;\n\n indegree.set(downstream, (indegree.get(downstream) ?? 0) + 1);\n }\n }\n\n const queue: ComputedImpl<any>[] = [];\n\n for (const computed of dirtyComputeds) {\n if ((indegree.get(computed) ?? 0) === 0) {\n queue.push(computed);\n }\n }\n\n const ordered: ComputedImpl<any>[] = [];\n\n while (queue.length > 0) {\n const computed = queue.shift()!;\n\n ordered.push(computed);\n\n for (const downstream of computed.computedSubscribers()) {\n if (!pendingSet.has(downstream)) continue;\n\n const nextIndegree = (indegree.get(downstream) ?? 0) - 1;\n\n indegree.set(downstream, nextIndegree);\n\n if (nextIndegree === 0) {\n queue.push(downstream);\n }\n }\n }\n\n if (ordered.length < dirtyComputeds.length) {\n for (const computed of dirtyComputeds) {\n if (!ordered.includes(computed)) {\n ordered.push(computed);\n }\n }\n }\n\n return ordered;\n};\n\nconst queueEffectsFromNode = (node: ReactiveNode): void => {\n const dirtyComputeds: ComputedImpl<any>[] = [...node.computedSubscribers()];\n const seenComputeds = new Set<ComputedImpl<any>>();\n\n for (const subscriber of node.subscribers()) {\n pendingSubscribers.add(subscriber);\n }\n\n while (dirtyComputeds.length > 0) {\n const computed = dirtyComputeds.pop()!;\n\n if (seenComputeds.has(computed)) continue;\n\n seenComputeds.add(computed);\n\n if (!computed.markDirty()) continue;\n\n pendingDirtyComputeds.add(computed);\n\n for (const downstream of computed.computedSubscribers()) {\n dirtyComputeds.push(downstream);\n }\n }\n};\n\nconst flushDirtyComputeds = (): void => {\n while (pendingDirtyComputeds.size > 0) {\n const dirtyComputeds = toTopologicalOrder([...pendingDirtyComputeds]);\n\n pendingDirtyComputeds.clear();\n\n for (const computed of dirtyComputeds) {\n if (!computed.hasAnySubscribers()) continue;\n\n const changed = computed.refreshIfDirty();\n\n if (!changed) continue;\n\n for (const subscriber of computed.subscribers()) {\n pendingSubscribers.add(subscriber);\n }\n\n for (const downstream of computed.computedSubscribers()) {\n if (downstream.markDirty()) {\n pendingDirtyComputeds.add(downstream);\n }\n }\n }\n }\n};\n\nconst flushEffects = (): void => {\n let iterations = 0;\n\n while (pendingSubscribers.size > 0 || pendingDirtyComputeds.size > 0) {\n if (++iterations > DEFAULT_MAX_ITERATIONS) {\n throw new Error(`[stateit] infinite flush loop (> ${DEFAULT_MAX_ITERATIONS} iterations)`);\n }\n\n if (pendingDirtyComputeds.size > 0) {\n flushDirtyComputeds();\n }\n\n if (pendingSubscribers.size === 0) continue;\n\n const subscribersToRun = [...pendingSubscribers];\n\n pendingSubscribers.clear();\n runAll(subscribersToRun, 'subscriber errors');\n }\n};\n\nconst notifyNodeChange = (node: ReactiveNode): void => {\n if (!node.hasAnySubscribers()) return;\n\n queueEffectsFromNode(node);\n\n if (batchDepth === 0) {\n flushEffects();\n }\n};\n\n// === BASE REACTIVE NODE ===\nclass ReactiveNode {\n private computedSubs_ = new Set<ComputedImpl<any>>();\n private subscribers_ = new Set<Subscriber>();\n\n protected track(): void {\n if (!currentDeps) return;\n\n if (currentComputed !== null) {\n const owner = currentComputed;\n\n this.computedSubs_.add(owner);\n currentDeps.add(() => this.computedSubs_.delete(owner));\n\n return;\n }\n\n if (currentEffect !== null) {\n const owner = currentEffect;\n\n this.subscribers_.add(owner);\n currentDeps.add(() => this.subscribers_.delete(owner));\n }\n }\n\n protected notify(): void {\n notifyNodeChange(this);\n }\n\n hasAnySubscribers(): boolean {\n return this.computedSubs_.size > 0 || this.subscribers_.size > 0;\n }\n\n computedSubscribers(): ReadonlySet<ComputedImpl<any>> {\n return this.computedSubs_;\n }\n\n subscribers(): ReadonlySet<Subscriber> {\n return this.subscribers_;\n }\n\n subscribe(subscriber: Subscriber): Subscription {\n this.subscribers_.add(subscriber);\n\n return toSubscription(() => {\n this.subscribers_.delete(subscriber);\n });\n }\n}\n\n// === SIGNAL IMPLEMENTATION ===\nclass SignalImpl<T> extends ReactiveNode implements Signal<T> {\n private value_: T;\n private equals_: EqualityFn<T>;\n [IS_SIGNAL] = true;\n\n constructor(initial: T, equals?: EqualityFn<T>) {\n super();\n this.value_ = initial;\n this.equals_ = equals ?? Object.is;\n }\n\n get value(): T {\n this.track();\n\n return this.value_;\n }\n\n peek(): T {\n return this.value_;\n }\n\n readonly subscribe = (onStoreChange: () => void): Subscription => {\n return super.subscribe(onStoreChange);\n };\n\n update(fn: (current: T) => T): void {\n this.value = fn(this.value_);\n }\n\n set value(next: T) {\n if (this.equals_(this.value_, next)) return;\n\n this.value_ = next;\n this.notify();\n }\n}\n\n// === COMPUTED IMPLEMENTATION ===\nclass ComputedImpl<T> extends ReactiveNode implements ComputedSignal<T> {\n private hasValue_ = false;\n private value_!: T;\n private dirty_ = true;\n private computing_ = false;\n private disposed_ = false;\n private deps_ = new Set<CleanupFn>();\n private compute_: () => T;\n private equals_: EqualityFn<T>;\n [IS_SIGNAL] = true;\n\n constructor(compute: () => T, equals?: EqualityFn<T>) {\n super();\n this.compute_ = compute;\n this.equals_ = equals ?? Object.is;\n }\n\n markDirty(): boolean {\n if (this.disposed_ || this.dirty_) return false;\n\n this.dirty_ = true;\n\n return true;\n }\n\n refreshIfDirty(): boolean {\n return this.dirty_ ? this.recompute() : false;\n }\n\n private recompute(): boolean {\n if (this.computing_) {\n throw new Error('[stateit] computed cycle detected');\n }\n\n for (const unsub of this.deps_) unsub();\n this.deps_.clear();\n\n this.computing_ = true;\n\n try {\n const next = withTracking(null, this, this.deps_, null, this.compute_);\n\n this.dirty_ = false;\n\n if (!this.hasValue_ || !this.equals_(this.value_, next)) {\n this.hasValue_ = true;\n this.value_ = next;\n\n return true;\n }\n\n return false;\n } catch (error) {\n const cleanupErrors = runCleanupAndCollectErrors(this.deps_);\n\n this.deps_.clear();\n\n return rethrowWithCleanupErrors(error, cleanupErrors, 'computed failed dependency cleanup errors');\n } finally {\n this.computing_ = false;\n }\n }\n\n get value(): T {\n if (this.disposed_) {\n throw new Error('[stateit] Cannot read disposed computed signal');\n }\n\n this.refreshIfDirty();\n\n this.track();\n\n return this.value_;\n }\n\n peek(): T {\n if (this.disposed_) {\n throw new Error('[stateit] Cannot read disposed computed signal');\n }\n\n this.refreshIfDirty();\n\n return this.value_;\n }\n\n readonly subscribe = (onStoreChange: () => void): Subscription => {\n if (this.disposed_) {\n throw new Error('[stateit] Cannot subscribe to a disposed computed signal');\n }\n\n // Subscribing should be lazy in terms of callbacks, but computed dependencies\n // must be established so upstream writes can mark this node dirty.\n this.refreshIfDirty();\n\n return super.subscribe(onStoreChange);\n };\n\n dispose(): void {\n if (this.disposed_) return;\n\n this.disposed_ = true;\n\n for (const unsub of this.deps_) unsub();\n this.deps_.clear();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\n// === CORE API ===\n\nexport const signal = <T>(initial: T, options?: ReactiveOptions<T>): Signal<T> =>\n new SignalImpl(initial, options?.equals);\n\nexport const computed = <T>(compute: () => T, options?: ReactiveOptions<T>): ComputedSignal<T> => {\n const comp = new ComputedImpl(compute, options?.equals);\n\n if (currentCleanups !== null) {\n onCleanup(() => comp.dispose());\n }\n\n return comp;\n};\n\nexport const batch = <T>(fn: () => T): T => {\n // Batch coalesces notifications. Writes that happen before an error are not rolled back.\n // Pending subscribers still flush, and caller-visible errors are aggregated.\n batchDepth++;\n\n let result: T | undefined;\n let bodyError: unknown;\n\n try {\n result = fn();\n } catch (e) {\n bodyError = e;\n }\n\n batchDepth--;\n\n if (batchDepth === 0) {\n try {\n flushEffects();\n } catch (flushError) {\n if (bodyError !== undefined) {\n throw new AggregateError([bodyError, flushError], '[stateit] batch error with flush errors', {\n cause: flushError,\n });\n }\n\n throw ensureError(flushError);\n }\n }\n\n if (bodyError !== undefined) {\n throw ensureError(bodyError);\n }\n\n return result as T;\n};\n\nexport const effect = (fn: EffectCallback): Subscription => {\n let cleanup: CleanupFn | undefined;\n const deps = new Set<CleanupFn>();\n let isRunning = false;\n let isDirty = false;\n let isDisposed = false;\n\n const teardown = (): void => {\n if (!cleanup && deps.size === 0) return;\n\n const callbacks = cleanup ? [cleanup, ...deps] : [...deps];\n\n cleanup = undefined;\n deps.clear();\n\n runAll(callbacks, 'effect teardown errors');\n };\n\n const run: EffectRunner = (): void => {\n if (isDisposed) return;\n\n if (isRunning) {\n isDirty = true;\n\n return;\n }\n\n isRunning = true;\n\n try {\n let iterations = 0;\n\n do {\n if (++iterations > DEFAULT_MAX_ITERATIONS) {\n throw new Error(`[stateit] infinite effect loop (> ${DEFAULT_MAX_ITERATIONS} iterations)`);\n }\n\n isDirty = false;\n teardown();\n\n const localCleanups: CleanupFn[] = [];\n let returnedCleanup: CleanupFn | void = undefined;\n\n try {\n returnedCleanup = withTracking(run, null, deps, localCleanups, fn);\n } catch (error) {\n const cleanupErrors = [...runCleanupAndCollectErrors(deps), ...runCleanupAndCollectErrors(localCleanups)];\n\n deps.clear();\n rethrowWithCleanupErrors(error, cleanupErrors, 'effect failure with cleanup errors');\n }\n\n if (typeof returnedCleanup === 'function') {\n localCleanups.push(returnedCleanup);\n }\n\n cleanup =\n localCleanups.length > 0\n ? () => {\n runAll(localCleanups, 'effect cleanup errors');\n }\n : undefined;\n } while (isDirty && !isDisposed);\n } finally {\n isRunning = false;\n }\n };\n\n run();\n\n return toSubscription(() => {\n if (isDisposed) return;\n\n isDisposed = true;\n teardown();\n });\n};\n\nexport const untrack = <T>(fn: () => T): T => withTracking(null, null, null, null, fn);\n\nexport const readonly = <T>(source: ReadonlySignal<T>): ReadonlySignal<T> => {\n const sourceObject = source as object;\n const cached = readonlyCache.get(sourceObject);\n\n if (cached) {\n return cached as ReadonlySignal<T>;\n }\n\n const view: ReadonlySignal<T> = {\n peek(): T {\n return source.peek();\n },\n subscribe(onStoreChange: () => void): Subscription {\n return source.subscribe(onStoreChange);\n },\n get value(): T {\n return source.value;\n },\n };\n\n readonlyCache.set(sourceObject, view as ReadonlySignal<unknown>);\n\n return view;\n};\n\nexport const toStore = <T>(source: ReadonlySignal<T>): { subscribe(run: (value: T) => void): Subscription } => ({\n subscribe(run) {\n run(source.value);\n\n return source.subscribe(() => run(source.value));\n },\n});\n\nexport const toObservable = <T>(source: ReadonlySignal<T>): ObservableLike<T> => {\n const subscribe = (observerOrNext: ObservableObserver<T> | ((value: T) => void)): { unsubscribe(): void } => {\n const observer: ObservableObserver<T> =\n typeof observerOrNext === 'function' ? { next: observerOrNext } : observerOrNext;\n\n observer.next?.(source.value);\n\n const subscription = source.subscribe(() => observer.next?.(source.value));\n\n return {\n unsubscribe(): void {\n subscription();\n },\n };\n };\n\n const observable = {\n [OBSERVABLE_SYMBOL](): ObservableLike<T> {\n return observable;\n },\n subscribe,\n };\n\n return observable;\n};\n\nexport const onCleanup = (fn: CleanupFn): void => {\n if (currentCleanups === null) {\n throw new Error('[stateit] onCleanup() must be called from within an active effect or scope.');\n }\n\n currentCleanups.push(fn);\n};\n\nexport const scope = (setup?: () => void): Scope => {\n const cleanups: CleanupFn[] = [];\n let disposed = false;\n\n const run = <T>(fn: () => T): T => {\n if (disposed) throw new Error('[stateit] Cannot run inside a disposed scope.');\n\n return withTracking(null, null, null, cleanups, fn);\n };\n\n const dispose = (): void => {\n if (disposed) return;\n\n disposed = true;\n\n runAll([...cleanups].reverse(), 'scope cleanup errors');\n cleanups.length = 0;\n };\n\n const api: Scope = { dispose, run, [Symbol.dispose]: dispose };\n\n if (setup) {\n run(setup);\n }\n\n return api;\n};\n\nfunction watch<T>(\n source: ReadonlySignal<T>,\n cb: (value: T, prev: T) => void,\n watchOptions?: WatchOptions<T>,\n): Subscription;\nfunction watch<T>(source: () => T, cb: (value: T, prev: T) => void, watchOptions?: WatchOptions<T>): Subscription;\nfunction watch<T>(\n source: ReadonlySignal<T> | (() => T),\n cb: (value: T, prev: T) => void,\n watchOptions?: WatchOptions<T>,\n): Subscription {\n const get = typeof source === 'function' ? source : () => source.value;\n const equals = watchOptions?.equals ?? Object.is;\n let initialized = false;\n let prev!: T;\n\n if (watchOptions?.immediate) {\n prev = untrack(get);\n initialized = true;\n cb(prev, prev);\n }\n\n return effect(() => {\n const next = get();\n\n if (!initialized) {\n initialized = true;\n prev = next;\n\n return;\n }\n\n if (equals(prev, next)) return;\n\n const old = prev;\n\n prev = next;\n cb(next, old);\n });\n}\nexport { watch };\n\nexport const store = <T extends object>(initial: T): Store<T> => {\n ensureObject(initial, '[stateit] store() requires a plain object initial state.');\n\n const initialSnapshot = structuredClone(initial);\n const state = signal(structuredClone(initial));\n const api: Store<T> & { [IS_SIGNAL]: true } = {\n [IS_SIGNAL]: true,\n patch(partial: Partial<T>): void {\n ensureObject(partial, '[stateit] store.patch() requires a plain object partial.');\n\n const current = untrack(() => state.value);\n const hasChange = (Object.keys(partial) as Array<keyof T>).some((k) => !Object.is(current[k], partial[k]));\n\n if (hasChange) state.value = { ...current, ...partial };\n },\n peek(): T {\n return state.peek();\n },\n reset(): void {\n state.value = structuredClone(initialSnapshot);\n },\n subscribe(onStoreChange: () => void): Subscription {\n return state.subscribe(onStoreChange);\n },\n update(fn: (current: T) => T): void {\n state.update(fn);\n },\n get value(): T {\n return state.value;\n },\n };\n\n return api;\n};\n\n// === TYPE HELPERS ===\n\nexport const isSignal = <T = unknown>(value: unknown): value is ReadonlySignal<T> =>\n typeof value === 'object' && value !== null && !!(value as Record<typeof IS_SIGNAL, unknown>)[IS_SIGNAL];\n"],"mappings":"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"}
package/dist/stateit.d.ts CHANGED
@@ -1,17 +1,68 @@
1
- import type { CleanupFn, ComputedSignal, EffectCallback, EffectOptions, ReactiveOptions, ReadonlySignal, Signal, Store, Subscription, WatchOptions } from './types';
1
+ export type CleanupFn = () => void;
2
+ export type EffectCallback = () => CleanupFn | void;
3
+ export type EqualityFn<T> = (a: T, b: T) => boolean;
4
+ export type ReactiveOptions<T> = {
5
+ equals?: EqualityFn<T>;
6
+ };
7
+ export interface Subscription {
8
+ (): void;
9
+ dispose(): void;
10
+ [Symbol.dispose](): void;
11
+ }
12
+ export interface ReadonlySignal<T> {
13
+ peek(): T;
14
+ subscribe(onStoreChange: () => void): Subscription;
15
+ readonly value: T;
16
+ }
17
+ export interface Signal<T> extends ReadonlySignal<T> {
18
+ update(fn: (current: T) => T): void;
19
+ value: T;
20
+ }
21
+ export interface ComputedSignal<T> extends ReadonlySignal<T> {
22
+ dispose(): void;
23
+ [Symbol.dispose](): void;
24
+ }
25
+ export type WatchOptions<T> = {
26
+ equals?: EqualityFn<T>;
27
+ immediate?: boolean;
28
+ };
29
+ export interface ObservableObserver<T> {
30
+ complete?(): void;
31
+ error?(error: unknown): void;
32
+ next?(value: T): void;
33
+ }
34
+ export interface Store<T extends object> extends ReadonlySignal<T> {
35
+ patch(partial: Partial<T>): void;
36
+ update(fn: (state: T) => T): void;
37
+ reset(): void;
38
+ }
39
+ export interface Scope {
40
+ readonly run: <T>(fn: () => T) => T;
41
+ readonly dispose: () => void;
42
+ readonly [Symbol.dispose]: () => void;
43
+ }
44
+ export declare const observableSymbol: symbol;
45
+ export type ObservableLike<T> = {
46
+ subscribe(observer: ObservableObserver<T> | ((value: T) => void)): {
47
+ unsubscribe(): void;
48
+ };
49
+ };
50
+ export declare const toSubscription: (dispose: () => void) => Subscription;
2
51
  export declare const signal: <T>(initial: T, options?: ReactiveOptions<T>) => Signal<T>;
3
52
  export declare const computed: <T>(compute: () => T, options?: ReactiveOptions<T>) => ComputedSignal<T>;
4
53
  export declare const batch: <T>(fn: () => T) => T;
5
- export declare const effect: (fn: EffectCallback, options?: EffectOptions) => Subscription;
54
+ export declare const effect: (fn: EffectCallback) => Subscription;
6
55
  export declare const untrack: <T>(fn: () => T) => T;
56
+ export declare const readonly: <T>(source: ReadonlySignal<T>) => ReadonlySignal<T>;
57
+ export declare const toStore: <T>(source: ReadonlySignal<T>) => {
58
+ subscribe(run: (value: T) => void): Subscription;
59
+ };
60
+ export declare const toObservable: <T>(source: ReadonlySignal<T>) => ObservableLike<T>;
7
61
  export declare const onCleanup: (fn: CleanupFn) => void;
62
+ export declare const scope: (setup?: () => void) => Scope;
8
63
  declare function watch<T>(source: ReadonlySignal<T>, cb: (value: T, prev: T) => void, watchOptions?: WatchOptions<T>): Subscription;
9
- declare function watch<S, T>(source: ReadonlySignal<S>, selector: (value: S) => T, cb: (value: T, prev: T) => void, watchOptions?: WatchOptions<T>): Subscription;
64
+ declare function watch<T>(source: () => T, cb: (value: T, prev: T) => void, watchOptions?: WatchOptions<T>): Subscription;
10
65
  export { watch };
11
- export declare const store: <T extends object>(initial: T, storeOptions?: ReactiveOptions<T>) => Store<T>;
12
- export declare const readonly: <T>(input: ReadonlySignal<T>) => ReadonlySignal<T>;
13
- export declare const writable: <T>(input: Signal<T>) => Signal<T>;
66
+ export declare const store: <T extends object>(initial: T) => Store<T>;
14
67
  export declare const isSignal: <T = unknown>(value: unknown) => value is ReadonlySignal<T>;
15
- export declare const peekValue: <T>(input: T | ReadonlySignal<T>) => T;
16
- export declare const toValue: <T>(input: T | ReadonlySignal<T> | (() => T)) => T;
17
68
  //# sourceMappingURL=stateit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stateit.d.ts","sourceRoot":"","sources":["../src/stateit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,cAAc,EACd,aAAa,EAEb,eAAe,EACf,cAAc,EACd,MAAM,EACN,KAAK,EACL,YAAY,EACZ,YAAY,EACb,MAAM,SAAS,CAAC;AAyOjB,eAAO,MAAM,MAAM,GAAI,CAAC,EAAE,SAAS,CAAC,EAAE,UAAU,eAAe,CAAC,CAAC,CAAC,KAAG,MAAM,CAAC,CAAC,CACnC,CAAC;AAE3C,eAAO,MAAM,QAAQ,GAAI,CAAC,EAAE,SAAS,MAAM,CAAC,EAAE,UAAU,eAAe,CAAC,CAAC,CAAC,KAAG,cAAc,CAAC,CAAC,CAS5F,CAAC;AAEF,eAAO,MAAM,KAAK,GAAI,CAAC,EAAE,IAAI,MAAM,CAAC,KAAG,CActC,CAAC;AAEF,eAAO,MAAM,MAAM,GAAI,IAAI,cAAc,EAAE,UAAU,aAAa,KAAG,YAmEpE,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,CAAC,EAAE,IAAI,MAAM,CAAC,KAAG,CAExC,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,IAAI,SAAS,KAAG,IAMzC,CAAC;AA4BF,iBAAS,KAAK,CAAC,CAAC,EACd,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,EACzB,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,IAAI,EAC/B,YAAY,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,GAC7B,YAAY,CAAC;AAChB,iBAAS,KAAK,CAAC,CAAC,EAAE,CAAC,EACjB,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,EACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EACzB,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,IAAI,EAC/B,YAAY,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,GAC7B,YAAY,CAAC;AAwBhB,OAAO,EAAE,KAAK,EAAE,CAAC;AAEjB,eAAO,MAAM,KAAK,GAAI,CAAC,SAAS,MAAM,EAAE,SAAS,CAAC,EAAE,eAAe,eAAe,CAAC,CAAC,CAAC,KAAG,KAAK,CAAC,CAAC,CA+B9F,CAAC;AAIF,eAAO,MAAM,QAAQ,GAAI,CAAC,EAAE,OAAO,cAAc,CAAC,CAAC,CAAC,KAAG,cAAc,CAAC,CAAC,CAAU,CAAC;AAElF,eAAO,MAAM,QAAQ,GAAI,CAAC,EAAE,OAAO,MAAM,CAAC,CAAC,CAAC,KAAG,MAAM,CAAC,CAAC,CAAU,CAAC;AAElE,eAAO,MAAM,QAAQ,GAAI,CAAC,GAAG,OAAO,EAAE,OAAO,OAAO,KAAG,KAAK,IAAI,cAAc,CAAC,CAAC,CAM/E,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,OAAO,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,KAAG,CAA+C,CAAC;AAE5G,eAAO,MAAM,OAAO,GAAI,CAAC,EAAE,OAAO,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,KAAG,CAMrE,CAAC"}
1
+ {"version":3,"file":"stateit.d.ts","sourceRoot":"","sources":["../src/stateit.ts"],"names":[],"mappings":"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"}
package/dist/stateit.js CHANGED
@@ -1,10 +1,10 @@
1
1
  //#region src/stateit.ts
2
- var e = Symbol("stateit.uninitialized"), t = 100, n = (e) => Object.assign(e, {
2
+ var e = 100, t = Symbol("stateit.is-signal"), n = Symbol.observable ?? Symbol.for("observable"), r = n, i = (e) => Object.assign(e, {
3
3
  dispose: e,
4
4
  [Symbol.dispose]: e
5
- }), r = (e, t) => {
5
+ }), a = /* @__PURE__ */ new WeakMap(), o = (e) => e instanceof Error ? e : Error(String(e)), s = (e, t) => {
6
6
  if (typeof e != "object" || !e || Array.isArray(e)) throw TypeError(t);
7
- }, i = (e) => structuredClone(e), a = (e, t) => {
7
+ }, c = (e, t) => {
8
8
  let n = [];
9
9
  for (let t of e) try {
10
10
  t();
@@ -13,103 +13,171 @@ var e = Symbol("stateit.uninitialized"), t = 100, n = (e) => Object.assign(e, {
13
13
  }
14
14
  if (n.length === 1) throw n[0];
15
15
  if (n.length > 1) throw AggregateError(n, `[stateit] ${t}`);
16
- }, o = (e) => {
17
- let t = [];
18
- for (let n of [...e]) try {
19
- n();
16
+ }, l = (e, t, n) => {
17
+ let r = o(e);
18
+ throw t.length === 0 ? r : AggregateError([r, ...t.map(o)], `[stateit] ${n}`, { cause: r });
19
+ }, u = (e) => {
20
+ try {
21
+ return c(e, "cleanup errors"), [];
20
22
  } catch (e) {
21
- t.push(e);
22
- }
23
- if (t.length === 1) throw t[0];
24
- if (t.length > 1) throw AggregateError(t, "[stateit] subscriber errors");
25
- }, s = {
26
- cleanups: null,
27
- deps: null,
28
- effect: null
29
- }, c = (e, t, n, r) => {
30
- let i = s;
31
- s = {
32
- cleanups: n,
33
- deps: t,
34
- effect: e
35
- };
23
+ return e instanceof AggregateError ? e.errors : [e];
24
+ }
25
+ }, d = null, f = null, p = null, m = null, h = (e, t, n, r, i) => {
26
+ let a = d, o = f, s = p, c = m;
27
+ d = e, f = t, p = n, m = r;
36
28
  try {
37
- return r();
29
+ return i();
38
30
  } finally {
39
- s = i;
31
+ d = a, f = o, p = s, m = c;
40
32
  }
41
- }, l = 0, u = /* @__PURE__ */ new Set(), d = () => {
42
- for (; u.size > 0;) {
43
- let e = [...u];
44
- u.clear(), o(new Set(e));
33
+ }, g = 0, _ = /* @__PURE__ */ new Set(), v = /* @__PURE__ */ new Set(), y = (e) => {
34
+ let t = new Set(e), n = /* @__PURE__ */ new Map();
35
+ for (let t of e) n.set(t, 0);
36
+ for (let r of e) for (let e of r.computedSubscribers()) t.has(e) && n.set(e, (n.get(e) ?? 0) + 1);
37
+ let r = [];
38
+ for (let t of e) (n.get(t) ?? 0) === 0 && r.push(t);
39
+ let i = [];
40
+ for (; r.length > 0;) {
41
+ let e = r.shift();
42
+ i.push(e);
43
+ for (let i of e.computedSubscribers()) {
44
+ if (!t.has(i)) continue;
45
+ let e = (n.get(i) ?? 0) - 1;
46
+ n.set(i, e), e === 0 && r.push(i);
47
+ }
45
48
  }
46
- }, f = class {
47
- subscribers = /* @__PURE__ */ new Set();
48
- track() {
49
- !s.effect || !s.deps || (this.subscribers.add(s.effect), s.deps.add(() => this.subscribers.delete(s.effect)));
49
+ if (i.length < e.length) for (let t of e) i.includes(t) || i.push(t);
50
+ return i;
51
+ }, b = (e) => {
52
+ let t = [...e.computedSubscribers()], n = /* @__PURE__ */ new Set();
53
+ for (let t of e.subscribers()) _.add(t);
54
+ for (; t.length > 0;) {
55
+ let e = t.pop();
56
+ if (!n.has(e) && (n.add(e), e.markDirty())) {
57
+ v.add(e);
58
+ for (let n of e.computedSubscribers()) t.push(n);
59
+ }
60
+ }
61
+ }, x = () => {
62
+ for (; v.size > 0;) {
63
+ let e = y([...v]);
64
+ v.clear();
65
+ for (let t of e) if (t.hasAnySubscribers() && t.refreshIfDirty()) {
66
+ for (let e of t.subscribers()) _.add(e);
67
+ for (let e of t.computedSubscribers()) e.markDirty() && v.add(e);
68
+ }
50
69
  }
51
- hasSubscribers() {
52
- return this.subscribers.size > 0;
70
+ }, S = () => {
71
+ let t = 0;
72
+ for (; _.size > 0 || v.size > 0;) {
73
+ if (++t > e) throw Error(`[stateit] infinite flush loop (> ${e} iterations)`);
74
+ if (v.size > 0 && x(), _.size === 0) continue;
75
+ let n = [..._];
76
+ _.clear(), c(n, "subscriber errors");
53
77
  }
54
- notify() {
55
- if (this.subscribers.size !== 0) {
56
- if (l > 0) {
57
- for (let e of this.subscribers) u.add(e);
78
+ }, C = (e) => {
79
+ e.hasAnySubscribers() && (b(e), g === 0 && S());
80
+ }, w = class {
81
+ computedSubs_ = /* @__PURE__ */ new Set();
82
+ subscribers_ = /* @__PURE__ */ new Set();
83
+ track() {
84
+ if (p) {
85
+ if (f !== null) {
86
+ let e = f;
87
+ this.computedSubs_.add(e), p.add(() => this.computedSubs_.delete(e));
58
88
  return;
59
89
  }
60
- o(this.subscribers);
90
+ if (d !== null) {
91
+ let e = d;
92
+ this.subscribers_.add(e), p.add(() => this.subscribers_.delete(e));
93
+ }
61
94
  }
62
95
  }
63
- }, p = class extends f {
96
+ notify() {
97
+ C(this);
98
+ }
99
+ hasAnySubscribers() {
100
+ return this.computedSubs_.size > 0 || this.subscribers_.size > 0;
101
+ }
102
+ computedSubscribers() {
103
+ return this.computedSubs_;
104
+ }
105
+ subscribers() {
106
+ return this.subscribers_;
107
+ }
108
+ subscribe(e) {
109
+ return this.subscribers_.add(e), i(() => {
110
+ this.subscribers_.delete(e);
111
+ });
112
+ }
113
+ }, T = class extends w {
64
114
  value_;
65
115
  equals_;
116
+ [t] = !0;
66
117
  constructor(e, t) {
67
118
  super(), this.value_ = e, this.equals_ = t ?? Object.is;
68
119
  }
69
120
  get value() {
70
121
  return this.track(), this.value_;
71
122
  }
72
- set value(e) {
73
- this.equals_(this.value_, e) || (this.value_ = e, this.notify());
123
+ peek() {
124
+ return this.value_;
74
125
  }
126
+ subscribe = (e) => super.subscribe(e);
75
127
  update(e) {
76
128
  this.value = e(this.value_);
77
129
  }
78
- }, m = class extends f {
79
- value_ = e;
130
+ set value(e) {
131
+ this.equals_(this.value_, e) || (this.value_ = e, this.notify());
132
+ }
133
+ }, E = class extends w {
134
+ hasValue_ = !1;
135
+ value_;
80
136
  dirty_ = !0;
137
+ computing_ = !1;
81
138
  disposed_ = !1;
82
139
  deps_ = /* @__PURE__ */ new Set();
83
140
  compute_;
84
141
  equals_;
85
- onDepChange = () => {
86
- if (!this.disposed_) {
87
- if (this.subscribers.size === 0) {
88
- this.dirty_ = !0;
89
- return;
90
- }
91
- this.recompute() && this.notify();
92
- }
93
- };
142
+ [t] = !0;
94
143
  constructor(e, t) {
95
- super(), this.compute_ = e, this.equals_ = t ?? Object.is, this.recompute();
144
+ super(), this.compute_ = e, this.equals_ = t ?? Object.is;
145
+ }
146
+ markDirty() {
147
+ return this.disposed_ || this.dirty_ ? !1 : (this.dirty_ = !0, !0);
148
+ }
149
+ refreshIfDirty() {
150
+ return this.dirty_ ? this.recompute() : !1;
96
151
  }
97
152
  recompute() {
153
+ if (this.computing_) throw Error("[stateit] computed cycle detected");
98
154
  for (let e of this.deps_) e();
99
- this.deps_.clear();
100
- let t = c(this.onDepChange, this.deps_, null, this.compute_);
101
- return this.dirty_ = !1, this.value_ === e || !this.equals_(this.value_, t) ? (this.value_ = t, !0) : !1;
155
+ this.deps_.clear(), this.computing_ = !0;
156
+ try {
157
+ let e = h(null, this, this.deps_, null, this.compute_);
158
+ return this.dirty_ = !1, !this.hasValue_ || !this.equals_(this.value_, e) ? (this.hasValue_ = !0, this.value_ = e, !0) : !1;
159
+ } catch (e) {
160
+ let t = u(this.deps_);
161
+ return this.deps_.clear(), l(e, t, "computed failed dependency cleanup errors");
162
+ } finally {
163
+ this.computing_ = !1;
164
+ }
102
165
  }
103
166
  get value() {
104
167
  if (this.disposed_) throw Error("[stateit] Cannot read disposed computed signal");
105
- return this.dirty_ && this.recompute(), this.track(), this.value_;
168
+ return this.refreshIfDirty(), this.track(), this.value_;
106
169
  }
107
- get stale() {
108
- return this.dirty_;
170
+ peek() {
171
+ if (this.disposed_) throw Error("[stateit] Cannot read disposed computed signal");
172
+ return this.refreshIfDirty(), this.value_;
109
173
  }
174
+ subscribe = (e) => {
175
+ if (this.disposed_) throw Error("[stateit] Cannot subscribe to a disposed computed signal");
176
+ return this.refreshIfDirty(), super.subscribe(e);
177
+ };
110
178
  dispose() {
111
179
  if (!this.disposed_) {
112
- this.disposed_ = !0, this.dirty_ = !0;
180
+ this.disposed_ = !0;
113
181
  for (let e of this.deps_) e();
114
182
  this.deps_.clear();
115
183
  }
@@ -117,98 +185,152 @@ var e = Symbol("stateit.uninitialized"), t = 100, n = (e) => Object.assign(e, {
117
185
  [Symbol.dispose]() {
118
186
  this.dispose();
119
187
  }
120
- }, h = (e, t) => new p(e, t?.equals), g = (e, t) => {
121
- let n = new m(e, t?.equals);
122
- return s.effect !== null && s.cleanups !== null && b(() => n.dispose()), n;
123
- }, _ = (e) => {
124
- l++;
188
+ }, D = (e, t) => new T(e, t?.equals), O = (e, t) => {
189
+ let n = new E(e, t?.equals);
190
+ return m !== null && F(() => n.dispose()), n;
191
+ }, k = (e) => {
192
+ g++;
193
+ let t, n;
125
194
  try {
126
- let t = e();
127
- return --l === 0 && d(), t;
195
+ t = e();
128
196
  } catch (e) {
129
- throw --l === 0 && d(), e;
130
- }
131
- }, v = (e, r) => {
132
- let i, o = /* @__PURE__ */ new Set(), s = !1, l = !1, u = !1, d = r?.maxIterations ?? t, f = () => {
133
- let e = [];
134
- i && e.push(i), i = void 0;
135
- for (let t of o) e.push(t);
136
- o.clear(), a(e, "effect teardown errors");
137
- }, p = () => {
138
- if (!u) {
139
- if (s) {
140
- l = !0;
197
+ n = e;
198
+ }
199
+ if (g--, g === 0) try {
200
+ S();
201
+ } catch (e) {
202
+ throw n === void 0 ? o(e) : AggregateError([n, e], "[stateit] batch error with flush errors", { cause: e });
203
+ }
204
+ if (n !== void 0) throw o(n);
205
+ return t;
206
+ }, A = (t) => {
207
+ let n, r = /* @__PURE__ */ new Set(), a = !1, o = !1, s = !1, d = () => {
208
+ if (!n && r.size === 0) return;
209
+ let e = n ? [n, ...r] : [...r];
210
+ n = void 0, r.clear(), c(e, "effect teardown errors");
211
+ }, f = () => {
212
+ if (!s) {
213
+ if (a) {
214
+ o = !0;
141
215
  return;
142
216
  }
143
- s = !0;
217
+ a = !0;
144
218
  try {
145
- let t = 0;
219
+ let i = 0;
146
220
  do {
147
- if (++t > d) throw Error(`[stateit] infinite effect loop (> ${d} iterations)`);
148
- l = !1, f();
149
- let n = [], r = c(p, o, n, e);
150
- r && n.push(r), n.length > 0 && (i = () => {
151
- a(n, "effect cleanup errors");
152
- });
153
- } while (l && !u);
221
+ if (++i > e) throw Error(`[stateit] infinite effect loop (> ${e} iterations)`);
222
+ o = !1, d();
223
+ let a = [], s;
224
+ try {
225
+ s = h(f, null, r, a, t);
226
+ } catch (e) {
227
+ let t = [...u(r), ...u(a)];
228
+ r.clear(), l(e, t, "effect failure with cleanup errors");
229
+ }
230
+ typeof s == "function" && a.push(s), n = a.length > 0 ? () => {
231
+ c(a, "effect cleanup errors");
232
+ } : void 0;
233
+ } while (o && !s);
154
234
  } finally {
155
- s = !1;
235
+ a = !1;
156
236
  }
157
237
  }
158
238
  };
159
- return p(), n(() => {
160
- u || (u = !0, f());
239
+ return f(), i(() => {
240
+ s || (s = !0, d());
161
241
  });
162
- }, y = (e) => c(null, null, null, e), b = (e) => {
163
- if (s.cleanups === null) throw Error("[stateit] onCleanup() must be called from inside an active effect.");
164
- s.cleanups.push(e);
165
- }, x = (e, t, n) => {
166
- let r = n?.equals ?? Object.is, i = y(() => e.value);
167
- n?.immediate && t(i, i);
168
- let a = v(() => {
169
- let o = e.value;
170
- if (r(i, o)) return;
171
- let s = i;
172
- i = o, t(o, s), n?.once && a();
173
- });
174
- return a;
242
+ }, j = (e) => h(null, null, null, null, e), M = (e) => {
243
+ let t = e, n = a.get(t);
244
+ if (n) return n;
245
+ let r = {
246
+ peek() {
247
+ return e.peek();
248
+ },
249
+ subscribe(t) {
250
+ return e.subscribe(t);
251
+ },
252
+ get value() {
253
+ return e.value;
254
+ }
255
+ };
256
+ return a.set(t, r), r;
257
+ }, N = (e) => ({ subscribe(t) {
258
+ return t(e.value), e.subscribe(() => t(e.value));
259
+ } }), P = (e) => {
260
+ let t = (t) => {
261
+ let n = typeof t == "function" ? { next: t } : t;
262
+ n.next?.(e.value);
263
+ let r = e.subscribe(() => n.next?.(e.value));
264
+ return { unsubscribe() {
265
+ r();
266
+ } };
267
+ }, r = {
268
+ [n]() {
269
+ return r;
270
+ },
271
+ subscribe: t
272
+ };
273
+ return r;
274
+ }, F = (e) => {
275
+ if (m === null) throw Error("[stateit] onCleanup() must be called from within an active effect or scope.");
276
+ m.push(e);
277
+ }, I = (e) => {
278
+ let t = [], n = !1, r = (e) => {
279
+ if (n) throw Error("[stateit] Cannot run inside a disposed scope.");
280
+ return h(null, null, null, t, e);
281
+ }, i = () => {
282
+ n || (n = !0, c([...t].reverse(), "scope cleanup errors"), t.length = 0);
283
+ }, a = {
284
+ dispose: i,
285
+ run: r,
286
+ [Symbol.dispose]: i
287
+ };
288
+ return e && r(e), a;
175
289
  };
176
- function S(e, t, r, i) {
177
- if (typeof r == "function") {
178
- let a = t, o = r, s = g(() => a(e.value)), c = x(s, o, i);
179
- return n(() => {
180
- c(), s.dispose();
181
- });
182
- }
183
- return x(e, t, r);
290
+ function L(e, t, n) {
291
+ let r = typeof e == "function" ? e : () => e.value, i = n?.equals ?? Object.is, a = !1, o;
292
+ return n?.immediate && (o = j(r), a = !0, t(o, o)), A(() => {
293
+ let e = r();
294
+ if (!a) {
295
+ a = !0, o = e;
296
+ return;
297
+ }
298
+ if (i(o, e)) return;
299
+ let n = o;
300
+ o = e, t(e, n);
301
+ });
184
302
  }
185
- var C = (e, t) => {
186
- r(e, "[stateit] store() requires a plain object initial state.");
187
- let n = i(e), a = h(i(e), t);
303
+ var R = (e) => {
304
+ s(e, "[stateit] store() requires a plain object initial state.");
305
+ let n = structuredClone(e), r = D(structuredClone(e));
188
306
  return {
307
+ [t]: !0,
189
308
  patch(e) {
190
- if (typeof e != "object" || !e || Array.isArray(e)) throw TypeError("[stateit] store.patch() requires a plain object partial.");
191
- a.value = {
192
- ...a.value,
309
+ s(e, "[stateit] store.patch() requires a plain object partial.");
310
+ let t = j(() => r.value);
311
+ Object.keys(e).some((n) => !Object.is(t[n], e[n])) && (r.value = {
312
+ ...t,
193
313
  ...e
194
- };
314
+ });
315
+ },
316
+ peek() {
317
+ return r.peek();
195
318
  },
196
319
  reset() {
197
- a.value = i(n);
320
+ r.value = structuredClone(n);
321
+ },
322
+ subscribe(e) {
323
+ return r.subscribe(e);
198
324
  },
199
325
  update(e) {
200
- let t = e(a.value);
201
- r(t, "[stateit] store.update() must return a plain object."), a.value = t;
326
+ r.update(e);
202
327
  },
203
328
  get value() {
204
- return a.value;
205
- },
206
- set value(e) {
207
- r(e, "[stateit] Store value must always be a plain object."), a.value = e;
329
+ return r.value;
208
330
  }
209
331
  };
210
- }, w = (e) => e, T = (e) => e, E = (e) => typeof e != "object" || !e ? !1 : "value" in e, D = (e) => E(e) ? e.value : e, O = (e) => E(e) ? e.value : typeof e == "function" ? e() : e;
332
+ }, z = (e) => typeof e == "object" && !!e && !!e[t];
211
333
  //#endregion
212
- export { _ as batch, g as computed, v as effect, E as isSignal, b as onCleanup, D as peekValue, w as readonly, h as signal, C as store, O as toValue, y as untrack, S as watch, T as writable };
334
+ export { k as batch, O as computed, A as effect, z as isSignal, r as observableSymbol, F as onCleanup, M as readonly, I as scope, D as signal, R as store, P as toObservable, N as toStore, i as toSubscription, j as untrack, L as watch };
213
335
 
214
336
  //# sourceMappingURL=stateit.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stateit.js","names":[],"sources":["../src/stateit.ts"],"sourcesContent":["import type {\n CleanupFn,\n ComputedSignal,\n EffectCallback,\n EffectOptions,\n EqualityFn,\n ReactiveOptions,\n ReadonlySignal,\n Signal,\n Store,\n Subscription,\n WatchOptions,\n} from './types';\n\n// === CONSTANTS ===\nconst UNINITIALIZED = Symbol('stateit.uninitialized');\nconst DEFAULT_MAX_ITERATIONS = 100;\n\n// === HELPERS ===\nconst toSubscription = (dispose: () => void): Subscription =>\n Object.assign(dispose, { dispose, [Symbol.dispose]: dispose }) as Subscription;\n\nconst ensureObject = (value: unknown, message: string): void => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new TypeError(message);\n }\n};\n\nconst clone = <T>(value: T): T => structuredClone(value);\n\n// === UNIFIED ERROR HANDLING ===\nconst runCallbacks = (callbacks: CleanupFn[], context: string): void => {\n const errors: unknown[] = [];\n\n for (const callback of callbacks) {\n try {\n callback();\n } catch (e) {\n errors.push(e);\n }\n }\n\n if (errors.length === 1) throw errors[0];\n\n if (errors.length > 1) {\n throw new AggregateError(errors, `[stateit] ${context}`);\n }\n};\n\nconst runSubscribers = (subscribers: Set<EffectCallback>): void => {\n const errors: unknown[] = [];\n\n for (const fn of [...subscribers]) {\n try {\n fn();\n } catch (e) {\n errors.push(e);\n }\n }\n\n if (errors.length === 1) throw errors[0];\n\n if (errors.length > 1) {\n throw new AggregateError(errors, '[stateit] subscriber errors');\n }\n};\n\n// === GLOBAL REACTIVE GRAPH ===\ninterface EffectScope {\n effect: EffectCallback | null;\n deps: Set<CleanupFn> | null;\n cleanups: CleanupFn[] | null;\n}\n\nlet currentScope: EffectScope = {\n cleanups: null,\n deps: null,\n effect: null,\n};\n\nconst withScope = <T>(\n effect: EffectCallback | null,\n deps: Set<CleanupFn> | null,\n cleanups: CleanupFn[] | null,\n fn: () => T,\n): T => {\n const prev = currentScope;\n\n currentScope = { cleanups, deps, effect };\n\n try {\n return fn();\n } finally {\n currentScope = prev;\n }\n};\n\n// === BATCH QUEUE ===\nlet batchDepth = 0;\nconst batchQueue = new Set<EffectCallback>();\n\nconst flushBatch = (): void => {\n while (batchQueue.size > 0) {\n const pending = [...batchQueue];\n\n batchQueue.clear();\n\n runSubscribers(new Set(pending));\n }\n};\n\n// === BASE REACTIVE NODE ===\nclass ReactiveNode {\n protected subscribers = new Set<EffectCallback>();\n\n protected track(): void {\n if (!currentScope.effect || !currentScope.deps) return;\n\n this.subscribers.add(currentScope.effect);\n currentScope.deps.add(() => this.subscribers.delete(currentScope.effect!));\n }\n\n protected hasSubscribers(): boolean {\n return this.subscribers.size > 0;\n }\n\n protected notify(): void {\n if (this.subscribers.size === 0) return;\n\n if (batchDepth > 0) {\n for (const fn of this.subscribers) batchQueue.add(fn);\n\n return;\n }\n\n runSubscribers(this.subscribers);\n }\n}\n\n// === SIGNAL IMPLEMENTATION ===\nclass SignalImpl<T> extends ReactiveNode implements Signal<T> {\n private value_: T;\n private equals_: EqualityFn<T>;\n\n constructor(initial: T, equals?: EqualityFn<T>) {\n super();\n this.value_ = initial;\n this.equals_ = equals ?? Object.is;\n }\n\n get value(): T {\n this.track();\n\n return this.value_;\n }\n\n set value(next: T) {\n if (this.equals_(this.value_, next)) return;\n\n this.value_ = next;\n this.notify();\n }\n\n update(fn: (current: T) => T): void {\n this.value = fn(this.value_);\n }\n}\n\n// === COMPUTED IMPLEMENTATION ===\nclass ComputedImpl<T> extends ReactiveNode implements ComputedSignal<T> {\n private value_: T | typeof UNINITIALIZED = UNINITIALIZED;\n private dirty_ = true;\n private disposed_ = false;\n private deps_ = new Set<CleanupFn>();\n private compute_: () => T;\n private equals_: EqualityFn<T>;\n\n private readonly onDepChange: EffectCallback = () => {\n if (this.disposed_) return;\n\n if (this.subscribers.size === 0) {\n this.dirty_ = true;\n\n return;\n }\n\n if (this.recompute()) this.notify();\n };\n\n constructor(compute: () => T, equals?: EqualityFn<T>) {\n super();\n this.compute_ = compute;\n this.equals_ = equals ?? Object.is;\n this.recompute();\n }\n\n private recompute(): boolean {\n for (const unsub of this.deps_) unsub();\n this.deps_.clear();\n\n const next = withScope(this.onDepChange, this.deps_, null, this.compute_);\n\n this.dirty_ = false;\n\n if (this.value_ === UNINITIALIZED || !this.equals_(this.value_ as T, next)) {\n this.value_ = next;\n\n return true;\n }\n\n return false;\n }\n\n get value(): T {\n if (this.disposed_) {\n throw new Error('[stateit] Cannot read disposed computed signal');\n }\n\n if (this.dirty_) this.recompute();\n\n this.track();\n\n return this.value_ as T;\n }\n\n get stale(): boolean {\n return this.dirty_;\n }\n\n dispose(): void {\n if (this.disposed_) return;\n\n this.disposed_ = true;\n this.dirty_ = true;\n for (const unsub of this.deps_) unsub();\n this.deps_.clear();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\n// === CORE API ===\n\nexport const signal = <T>(initial: T, options?: ReactiveOptions<T>): Signal<T> =>\n new SignalImpl(initial, options?.equals);\n\nexport const computed = <T>(compute: () => T, options?: ReactiveOptions<T>): ComputedSignal<T> => {\n const comp = new ComputedImpl(compute, options?.equals);\n\n // Auto-dispose when created inside effect\n if (currentScope.effect !== null && currentScope.cleanups !== null) {\n onCleanup(() => comp.dispose());\n }\n\n return comp;\n};\n\nexport const batch = <T>(fn: () => T): T => {\n batchDepth++;\n\n try {\n const result = fn();\n\n if (--batchDepth === 0) flushBatch();\n\n return result;\n } catch (e) {\n if (--batchDepth === 0) flushBatch();\n\n throw e;\n }\n};\n\nexport const effect = (fn: EffectCallback, options?: EffectOptions): Subscription => {\n let cleanup: CleanupFn | undefined;\n const deps = new Set<CleanupFn>();\n let isRunning = false;\n let isDirty = false;\n let isDisposed = false;\n const maxIterations = options?.maxIterations ?? DEFAULT_MAX_ITERATIONS;\n\n const teardown = (): void => {\n const callbacks: CleanupFn[] = [];\n\n if (cleanup) callbacks.push(cleanup);\n\n cleanup = undefined;\n\n for (const unsub of deps) callbacks.push(unsub);\n deps.clear();\n\n runCallbacks(callbacks, 'effect teardown errors');\n };\n\n const run = (): void => {\n if (isDisposed) return;\n\n if (isRunning) {\n isDirty = true;\n\n return;\n }\n\n isRunning = true;\n\n try {\n let iterations = 0;\n\n do {\n if (++iterations > maxIterations) {\n throw new Error(`[stateit] infinite effect loop (> ${maxIterations} iterations)`);\n }\n\n isDirty = false;\n teardown();\n\n const localCleanups: CleanupFn[] = [];\n const returnedCleanup = withScope(run, deps, localCleanups, fn);\n\n if (returnedCleanup) localCleanups.push(returnedCleanup);\n\n if (localCleanups.length > 0) {\n cleanup = () => {\n runCallbacks(localCleanups, 'effect cleanup errors');\n };\n }\n } while (isDirty && !isDisposed);\n } finally {\n isRunning = false;\n }\n };\n\n run();\n\n return toSubscription(() => {\n if (isDisposed) return;\n\n isDisposed = true;\n teardown();\n });\n};\n\nexport const untrack = <T>(fn: () => T): T => {\n return withScope(null, null, null, fn);\n};\n\nexport const onCleanup = (fn: CleanupFn): void => {\n if (currentScope.cleanups === null) {\n throw new Error('[stateit] onCleanup() must be called from inside an active effect.');\n }\n\n currentScope.cleanups.push(fn);\n};\n\nconst watchBase = <T>(\n source: ReadonlySignal<T>,\n cb: (value: T, prev: T) => void,\n watchOptions?: WatchOptions<T>,\n): Subscription => {\n const equals = watchOptions?.equals ?? Object.is;\n let prev = untrack(() => source.value);\n\n if (watchOptions?.immediate) cb(prev, prev);\n\n const stop = effect(() => {\n const next = source.value;\n\n if (equals(prev, next)) return;\n\n const old = prev;\n\n prev = next;\n cb(next, old);\n\n if (watchOptions?.once) stop();\n });\n\n return stop;\n};\n\nfunction watch<T>(\n source: ReadonlySignal<T>,\n cb: (value: T, prev: T) => void,\n watchOptions?: WatchOptions<T>,\n): Subscription;\nfunction watch<S, T>(\n source: ReadonlySignal<S>,\n selector: (value: S) => T,\n cb: (value: T, prev: T) => void,\n watchOptions?: WatchOptions<T>,\n): Subscription;\nfunction watch<S, T>(\n source: ReadonlySignal<S>,\n selectorOrCb: ((value: S) => T) | ((value: S, prev: S) => void),\n maybeCb?: ((value: T, prev: T) => void) | WatchOptions<S>,\n maybeOptions?: WatchOptions<T>,\n): Subscription {\n if (typeof maybeCb === 'function') {\n const selector = selectorOrCb as (value: S) => T;\n const cb = maybeCb as (value: T, prev: T) => void;\n const selected = computed(() => selector(source.value));\n const stop = watchBase(selected, cb, maybeOptions);\n\n return toSubscription(() => {\n stop();\n selected.dispose();\n });\n }\n\n const cb = selectorOrCb as (value: S, prev: S) => void;\n\n return watchBase(source, cb, maybeCb as WatchOptions<S> | undefined);\n}\n\nexport { watch };\n\nexport const store = <T extends object>(initial: T, storeOptions?: ReactiveOptions<T>): Store<T> => {\n ensureObject(initial, '[stateit] store() requires a plain object initial state.');\n\n const initialSnapshot = clone(initial);\n const state = signal(clone(initial), storeOptions);\n\n return {\n patch(partial: Partial<T>): void {\n if (typeof partial !== 'object' || partial === null || Array.isArray(partial)) {\n throw new TypeError('[stateit] store.patch() requires a plain object partial.');\n }\n\n state.value = { ...state.value, ...partial };\n },\n reset(): void {\n state.value = clone(initialSnapshot);\n },\n update(fn: (current: T) => T): void {\n const next = fn(state.value);\n\n ensureObject(next, '[stateit] store.update() must return a plain object.');\n state.value = next;\n },\n get value(): T {\n return state.value;\n },\n set value(next: T) {\n ensureObject(next, '[stateit] Store value must always be a plain object.');\n state.value = next;\n },\n };\n};\n\n// === TYPE HELPERS ===\n\nexport const readonly = <T>(input: ReadonlySignal<T>): ReadonlySignal<T> => input;\n\nexport const writable = <T>(input: Signal<T>): Signal<T> => input;\n\nexport const isSignal = <T = unknown>(value: unknown): value is ReadonlySignal<T> => {\n if (typeof value !== 'object' || value === null) return false;\n\n const candidate = value as Partial<ReadonlySignal<T>>;\n\n return 'value' in candidate;\n};\n\nexport const peekValue = <T>(input: T | ReadonlySignal<T>): T => (isSignal<T>(input) ? input.value : input);\n\nexport const toValue = <T>(input: T | ReadonlySignal<T> | (() => T)): T => {\n if (isSignal<T>(input)) return input.value;\n\n if (typeof input === 'function') return (input as () => T)();\n\n return input;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"stateit.js","names":[],"sources":["../src/stateit.ts"],"sourcesContent":["// === TYPES ===\nexport type CleanupFn = () => void;\nexport type EffectCallback = () => CleanupFn | void;\nexport type EqualityFn<T> = (a: T, b: T) => boolean;\nexport type ReactiveOptions<T> = { equals?: EqualityFn<T> };\n\nexport interface Subscription {\n (): void;\n dispose(): void;\n [Symbol.dispose](): void;\n}\n\nexport interface ReadonlySignal<T> {\n peek(): T;\n subscribe(onStoreChange: () => void): Subscription;\n readonly value: T;\n}\n\nexport interface Signal<T> extends ReadonlySignal<T> {\n update(fn: (current: T) => T): void;\n value: T;\n}\n\nexport interface ComputedSignal<T> extends ReadonlySignal<T> {\n dispose(): void;\n [Symbol.dispose](): void;\n}\n\nexport type WatchOptions<T> = {\n equals?: EqualityFn<T>;\n immediate?: boolean;\n};\n\nexport interface ObservableObserver<T> {\n complete?(): void;\n error?(error: unknown): void;\n next?(value: T): void;\n}\n\nexport interface Store<T extends object> extends ReadonlySignal<T> {\n patch(partial: Partial<T>): void;\n update(fn: (state: T) => T): void;\n reset(): void;\n}\n\nexport interface Scope {\n readonly run: <T>(fn: () => T) => T;\n readonly dispose: () => void;\n readonly [Symbol.dispose]: () => void;\n}\n\n// === CONSTANTS ===\nconst DEFAULT_MAX_ITERATIONS = 100;\nconst IS_SIGNAL = Symbol('stateit.is-signal');\nconst OBSERVABLE_SYMBOL: unique symbol = ((Symbol as typeof Symbol & { observable?: symbol }).observable ??\n Symbol.for('observable')) as never;\n\nexport const observableSymbol = OBSERVABLE_SYMBOL;\n\ntype EffectRunner = () => void;\ntype Subscriber = () => void;\n\nexport type ObservableLike<T> = {\n [observableSymbol](): ObservableLike<T>;\n subscribe(observer: ObservableObserver<T> | ((value: T) => void)): { unsubscribe(): void };\n};\n\n// === HELPERS ===\nexport const toSubscription = (dispose: () => void): Subscription =>\n Object.assign(dispose, { dispose, [Symbol.dispose]: dispose }) as Subscription;\n\nconst readonlyCache = new WeakMap<object, ReadonlySignal<unknown>>();\n\nconst ensureError = (error: unknown): Error => (error instanceof Error ? error : new Error(String(error)));\n\nconst ensureObject = (value: unknown, message: string): void => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new TypeError(message);\n }\n};\n\nconst runAll = (items: Iterable<() => void>, context: string): void => {\n const errors: unknown[] = [];\n\n for (const fn of items) {\n try {\n fn();\n } catch (e) {\n errors.push(e);\n }\n }\n\n if (errors.length === 1) throw errors[0];\n\n if (errors.length > 1) {\n throw new AggregateError(errors, `[stateit] ${context}`);\n }\n};\n\nconst rethrowWithCleanupErrors = (error: unknown, cleanupErrors: unknown[], context: string): never => {\n const rootCause = ensureError(error);\n\n if (cleanupErrors.length === 0) {\n throw rootCause;\n }\n\n throw new AggregateError([rootCause, ...cleanupErrors.map(ensureError)], `[stateit] ${context}`, {\n cause: rootCause,\n });\n};\n\nconst runCleanupAndCollectErrors = (items: Iterable<() => void>): unknown[] => {\n try {\n runAll(items, 'cleanup errors');\n\n return [];\n } catch (error) {\n return error instanceof AggregateError ? error.errors : [error];\n }\n};\n\n// === GLOBAL TRACKING STATE ===\nlet currentEffect: EffectRunner | null = null;\nlet currentComputed: ComputedImpl<any> | null = null;\nlet currentDeps: Set<CleanupFn> | null = null;\nlet currentCleanups: CleanupFn[] | null = null;\n\nconst withTracking = <T>(\n effect: EffectRunner | null,\n computed: ComputedImpl<any> | null,\n deps: Set<CleanupFn> | null,\n cleanups: CleanupFn[] | null,\n fn: () => T,\n): T => {\n const prevEffect = currentEffect;\n const prevComputed = currentComputed;\n const prevDeps = currentDeps;\n const prevCleanups = currentCleanups;\n\n currentEffect = effect;\n currentComputed = computed;\n currentDeps = deps;\n currentCleanups = cleanups;\n\n try {\n return fn();\n } finally {\n currentEffect = prevEffect;\n currentComputed = prevComputed;\n currentDeps = prevDeps;\n currentCleanups = prevCleanups;\n }\n};\n\n// === NOTIFICATION QUEUES ===\nlet batchDepth = 0;\nconst pendingSubscribers = new Set<Subscriber>();\nconst pendingDirtyComputeds = new Set<ComputedImpl<any>>();\n\nconst toTopologicalOrder = (dirtyComputeds: readonly ComputedImpl<any>[]): ComputedImpl<any>[] => {\n const pendingSet = new Set(dirtyComputeds);\n const indegree = new Map<ComputedImpl<any>, number>();\n\n for (const computed of dirtyComputeds) {\n indegree.set(computed, 0);\n }\n\n for (const computed of dirtyComputeds) {\n for (const downstream of computed.computedSubscribers()) {\n if (!pendingSet.has(downstream)) continue;\n\n indegree.set(downstream, (indegree.get(downstream) ?? 0) + 1);\n }\n }\n\n const queue: ComputedImpl<any>[] = [];\n\n for (const computed of dirtyComputeds) {\n if ((indegree.get(computed) ?? 0) === 0) {\n queue.push(computed);\n }\n }\n\n const ordered: ComputedImpl<any>[] = [];\n\n while (queue.length > 0) {\n const computed = queue.shift()!;\n\n ordered.push(computed);\n\n for (const downstream of computed.computedSubscribers()) {\n if (!pendingSet.has(downstream)) continue;\n\n const nextIndegree = (indegree.get(downstream) ?? 0) - 1;\n\n indegree.set(downstream, nextIndegree);\n\n if (nextIndegree === 0) {\n queue.push(downstream);\n }\n }\n }\n\n if (ordered.length < dirtyComputeds.length) {\n for (const computed of dirtyComputeds) {\n if (!ordered.includes(computed)) {\n ordered.push(computed);\n }\n }\n }\n\n return ordered;\n};\n\nconst queueEffectsFromNode = (node: ReactiveNode): void => {\n const dirtyComputeds: ComputedImpl<any>[] = [...node.computedSubscribers()];\n const seenComputeds = new Set<ComputedImpl<any>>();\n\n for (const subscriber of node.subscribers()) {\n pendingSubscribers.add(subscriber);\n }\n\n while (dirtyComputeds.length > 0) {\n const computed = dirtyComputeds.pop()!;\n\n if (seenComputeds.has(computed)) continue;\n\n seenComputeds.add(computed);\n\n if (!computed.markDirty()) continue;\n\n pendingDirtyComputeds.add(computed);\n\n for (const downstream of computed.computedSubscribers()) {\n dirtyComputeds.push(downstream);\n }\n }\n};\n\nconst flushDirtyComputeds = (): void => {\n while (pendingDirtyComputeds.size > 0) {\n const dirtyComputeds = toTopologicalOrder([...pendingDirtyComputeds]);\n\n pendingDirtyComputeds.clear();\n\n for (const computed of dirtyComputeds) {\n if (!computed.hasAnySubscribers()) continue;\n\n const changed = computed.refreshIfDirty();\n\n if (!changed) continue;\n\n for (const subscriber of computed.subscribers()) {\n pendingSubscribers.add(subscriber);\n }\n\n for (const downstream of computed.computedSubscribers()) {\n if (downstream.markDirty()) {\n pendingDirtyComputeds.add(downstream);\n }\n }\n }\n }\n};\n\nconst flushEffects = (): void => {\n let iterations = 0;\n\n while (pendingSubscribers.size > 0 || pendingDirtyComputeds.size > 0) {\n if (++iterations > DEFAULT_MAX_ITERATIONS) {\n throw new Error(`[stateit] infinite flush loop (> ${DEFAULT_MAX_ITERATIONS} iterations)`);\n }\n\n if (pendingDirtyComputeds.size > 0) {\n flushDirtyComputeds();\n }\n\n if (pendingSubscribers.size === 0) continue;\n\n const subscribersToRun = [...pendingSubscribers];\n\n pendingSubscribers.clear();\n runAll(subscribersToRun, 'subscriber errors');\n }\n};\n\nconst notifyNodeChange = (node: ReactiveNode): void => {\n if (!node.hasAnySubscribers()) return;\n\n queueEffectsFromNode(node);\n\n if (batchDepth === 0) {\n flushEffects();\n }\n};\n\n// === BASE REACTIVE NODE ===\nclass ReactiveNode {\n private computedSubs_ = new Set<ComputedImpl<any>>();\n private subscribers_ = new Set<Subscriber>();\n\n protected track(): void {\n if (!currentDeps) return;\n\n if (currentComputed !== null) {\n const owner = currentComputed;\n\n this.computedSubs_.add(owner);\n currentDeps.add(() => this.computedSubs_.delete(owner));\n\n return;\n }\n\n if (currentEffect !== null) {\n const owner = currentEffect;\n\n this.subscribers_.add(owner);\n currentDeps.add(() => this.subscribers_.delete(owner));\n }\n }\n\n protected notify(): void {\n notifyNodeChange(this);\n }\n\n hasAnySubscribers(): boolean {\n return this.computedSubs_.size > 0 || this.subscribers_.size > 0;\n }\n\n computedSubscribers(): ReadonlySet<ComputedImpl<any>> {\n return this.computedSubs_;\n }\n\n subscribers(): ReadonlySet<Subscriber> {\n return this.subscribers_;\n }\n\n subscribe(subscriber: Subscriber): Subscription {\n this.subscribers_.add(subscriber);\n\n return toSubscription(() => {\n this.subscribers_.delete(subscriber);\n });\n }\n}\n\n// === SIGNAL IMPLEMENTATION ===\nclass SignalImpl<T> extends ReactiveNode implements Signal<T> {\n private value_: T;\n private equals_: EqualityFn<T>;\n [IS_SIGNAL] = true;\n\n constructor(initial: T, equals?: EqualityFn<T>) {\n super();\n this.value_ = initial;\n this.equals_ = equals ?? Object.is;\n }\n\n get value(): T {\n this.track();\n\n return this.value_;\n }\n\n peek(): T {\n return this.value_;\n }\n\n readonly subscribe = (onStoreChange: () => void): Subscription => {\n return super.subscribe(onStoreChange);\n };\n\n update(fn: (current: T) => T): void {\n this.value = fn(this.value_);\n }\n\n set value(next: T) {\n if (this.equals_(this.value_, next)) return;\n\n this.value_ = next;\n this.notify();\n }\n}\n\n// === COMPUTED IMPLEMENTATION ===\nclass ComputedImpl<T> extends ReactiveNode implements ComputedSignal<T> {\n private hasValue_ = false;\n private value_!: T;\n private dirty_ = true;\n private computing_ = false;\n private disposed_ = false;\n private deps_ = new Set<CleanupFn>();\n private compute_: () => T;\n private equals_: EqualityFn<T>;\n [IS_SIGNAL] = true;\n\n constructor(compute: () => T, equals?: EqualityFn<T>) {\n super();\n this.compute_ = compute;\n this.equals_ = equals ?? Object.is;\n }\n\n markDirty(): boolean {\n if (this.disposed_ || this.dirty_) return false;\n\n this.dirty_ = true;\n\n return true;\n }\n\n refreshIfDirty(): boolean {\n return this.dirty_ ? this.recompute() : false;\n }\n\n private recompute(): boolean {\n if (this.computing_) {\n throw new Error('[stateit] computed cycle detected');\n }\n\n for (const unsub of this.deps_) unsub();\n this.deps_.clear();\n\n this.computing_ = true;\n\n try {\n const next = withTracking(null, this, this.deps_, null, this.compute_);\n\n this.dirty_ = false;\n\n if (!this.hasValue_ || !this.equals_(this.value_, next)) {\n this.hasValue_ = true;\n this.value_ = next;\n\n return true;\n }\n\n return false;\n } catch (error) {\n const cleanupErrors = runCleanupAndCollectErrors(this.deps_);\n\n this.deps_.clear();\n\n return rethrowWithCleanupErrors(error, cleanupErrors, 'computed failed dependency cleanup errors');\n } finally {\n this.computing_ = false;\n }\n }\n\n get value(): T {\n if (this.disposed_) {\n throw new Error('[stateit] Cannot read disposed computed signal');\n }\n\n this.refreshIfDirty();\n\n this.track();\n\n return this.value_;\n }\n\n peek(): T {\n if (this.disposed_) {\n throw new Error('[stateit] Cannot read disposed computed signal');\n }\n\n this.refreshIfDirty();\n\n return this.value_;\n }\n\n readonly subscribe = (onStoreChange: () => void): Subscription => {\n if (this.disposed_) {\n throw new Error('[stateit] Cannot subscribe to a disposed computed signal');\n }\n\n // Subscribing should be lazy in terms of callbacks, but computed dependencies\n // must be established so upstream writes can mark this node dirty.\n this.refreshIfDirty();\n\n return super.subscribe(onStoreChange);\n };\n\n dispose(): void {\n if (this.disposed_) return;\n\n this.disposed_ = true;\n\n for (const unsub of this.deps_) unsub();\n this.deps_.clear();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\n// === CORE API ===\n\nexport const signal = <T>(initial: T, options?: ReactiveOptions<T>): Signal<T> =>\n new SignalImpl(initial, options?.equals);\n\nexport const computed = <T>(compute: () => T, options?: ReactiveOptions<T>): ComputedSignal<T> => {\n const comp = new ComputedImpl(compute, options?.equals);\n\n if (currentCleanups !== null) {\n onCleanup(() => comp.dispose());\n }\n\n return comp;\n};\n\nexport const batch = <T>(fn: () => T): T => {\n // Batch coalesces notifications. Writes that happen before an error are not rolled back.\n // Pending subscribers still flush, and caller-visible errors are aggregated.\n batchDepth++;\n\n let result: T | undefined;\n let bodyError: unknown;\n\n try {\n result = fn();\n } catch (e) {\n bodyError = e;\n }\n\n batchDepth--;\n\n if (batchDepth === 0) {\n try {\n flushEffects();\n } catch (flushError) {\n if (bodyError !== undefined) {\n throw new AggregateError([bodyError, flushError], '[stateit] batch error with flush errors', {\n cause: flushError,\n });\n }\n\n throw ensureError(flushError);\n }\n }\n\n if (bodyError !== undefined) {\n throw ensureError(bodyError);\n }\n\n return result as T;\n};\n\nexport const effect = (fn: EffectCallback): Subscription => {\n let cleanup: CleanupFn | undefined;\n const deps = new Set<CleanupFn>();\n let isRunning = false;\n let isDirty = false;\n let isDisposed = false;\n\n const teardown = (): void => {\n if (!cleanup && deps.size === 0) return;\n\n const callbacks = cleanup ? [cleanup, ...deps] : [...deps];\n\n cleanup = undefined;\n deps.clear();\n\n runAll(callbacks, 'effect teardown errors');\n };\n\n const run: EffectRunner = (): void => {\n if (isDisposed) return;\n\n if (isRunning) {\n isDirty = true;\n\n return;\n }\n\n isRunning = true;\n\n try {\n let iterations = 0;\n\n do {\n if (++iterations > DEFAULT_MAX_ITERATIONS) {\n throw new Error(`[stateit] infinite effect loop (> ${DEFAULT_MAX_ITERATIONS} iterations)`);\n }\n\n isDirty = false;\n teardown();\n\n const localCleanups: CleanupFn[] = [];\n let returnedCleanup: CleanupFn | void = undefined;\n\n try {\n returnedCleanup = withTracking(run, null, deps, localCleanups, fn);\n } catch (error) {\n const cleanupErrors = [...runCleanupAndCollectErrors(deps), ...runCleanupAndCollectErrors(localCleanups)];\n\n deps.clear();\n rethrowWithCleanupErrors(error, cleanupErrors, 'effect failure with cleanup errors');\n }\n\n if (typeof returnedCleanup === 'function') {\n localCleanups.push(returnedCleanup);\n }\n\n cleanup =\n localCleanups.length > 0\n ? () => {\n runAll(localCleanups, 'effect cleanup errors');\n }\n : undefined;\n } while (isDirty && !isDisposed);\n } finally {\n isRunning = false;\n }\n };\n\n run();\n\n return toSubscription(() => {\n if (isDisposed) return;\n\n isDisposed = true;\n teardown();\n });\n};\n\nexport const untrack = <T>(fn: () => T): T => withTracking(null, null, null, null, fn);\n\nexport const readonly = <T>(source: ReadonlySignal<T>): ReadonlySignal<T> => {\n const sourceObject = source as object;\n const cached = readonlyCache.get(sourceObject);\n\n if (cached) {\n return cached as ReadonlySignal<T>;\n }\n\n const view: ReadonlySignal<T> = {\n peek(): T {\n return source.peek();\n },\n subscribe(onStoreChange: () => void): Subscription {\n return source.subscribe(onStoreChange);\n },\n get value(): T {\n return source.value;\n },\n };\n\n readonlyCache.set(sourceObject, view as ReadonlySignal<unknown>);\n\n return view;\n};\n\nexport const toStore = <T>(source: ReadonlySignal<T>): { subscribe(run: (value: T) => void): Subscription } => ({\n subscribe(run) {\n run(source.value);\n\n return source.subscribe(() => run(source.value));\n },\n});\n\nexport const toObservable = <T>(source: ReadonlySignal<T>): ObservableLike<T> => {\n const subscribe = (observerOrNext: ObservableObserver<T> | ((value: T) => void)): { unsubscribe(): void } => {\n const observer: ObservableObserver<T> =\n typeof observerOrNext === 'function' ? { next: observerOrNext } : observerOrNext;\n\n observer.next?.(source.value);\n\n const subscription = source.subscribe(() => observer.next?.(source.value));\n\n return {\n unsubscribe(): void {\n subscription();\n },\n };\n };\n\n const observable = {\n [OBSERVABLE_SYMBOL](): ObservableLike<T> {\n return observable;\n },\n subscribe,\n };\n\n return observable;\n};\n\nexport const onCleanup = (fn: CleanupFn): void => {\n if (currentCleanups === null) {\n throw new Error('[stateit] onCleanup() must be called from within an active effect or scope.');\n }\n\n currentCleanups.push(fn);\n};\n\nexport const scope = (setup?: () => void): Scope => {\n const cleanups: CleanupFn[] = [];\n let disposed = false;\n\n const run = <T>(fn: () => T): T => {\n if (disposed) throw new Error('[stateit] Cannot run inside a disposed scope.');\n\n return withTracking(null, null, null, cleanups, fn);\n };\n\n const dispose = (): void => {\n if (disposed) return;\n\n disposed = true;\n\n runAll([...cleanups].reverse(), 'scope cleanup errors');\n cleanups.length = 0;\n };\n\n const api: Scope = { dispose, run, [Symbol.dispose]: dispose };\n\n if (setup) {\n run(setup);\n }\n\n return api;\n};\n\nfunction watch<T>(\n source: ReadonlySignal<T>,\n cb: (value: T, prev: T) => void,\n watchOptions?: WatchOptions<T>,\n): Subscription;\nfunction watch<T>(source: () => T, cb: (value: T, prev: T) => void, watchOptions?: WatchOptions<T>): Subscription;\nfunction watch<T>(\n source: ReadonlySignal<T> | (() => T),\n cb: (value: T, prev: T) => void,\n watchOptions?: WatchOptions<T>,\n): Subscription {\n const get = typeof source === 'function' ? source : () => source.value;\n const equals = watchOptions?.equals ?? Object.is;\n let initialized = false;\n let prev!: T;\n\n if (watchOptions?.immediate) {\n prev = untrack(get);\n initialized = true;\n cb(prev, prev);\n }\n\n return effect(() => {\n const next = get();\n\n if (!initialized) {\n initialized = true;\n prev = next;\n\n return;\n }\n\n if (equals(prev, next)) return;\n\n const old = prev;\n\n prev = next;\n cb(next, old);\n });\n}\nexport { watch };\n\nexport const store = <T extends object>(initial: T): Store<T> => {\n ensureObject(initial, '[stateit] store() requires a plain object initial state.');\n\n const initialSnapshot = structuredClone(initial);\n const state = signal(structuredClone(initial));\n const api: Store<T> & { [IS_SIGNAL]: true } = {\n [IS_SIGNAL]: true,\n patch(partial: Partial<T>): void {\n ensureObject(partial, '[stateit] store.patch() requires a plain object partial.');\n\n const current = untrack(() => state.value);\n const hasChange = (Object.keys(partial) as Array<keyof T>).some((k) => !Object.is(current[k], partial[k]));\n\n if (hasChange) state.value = { ...current, ...partial };\n },\n peek(): T {\n return state.peek();\n },\n reset(): void {\n state.value = structuredClone(initialSnapshot);\n },\n subscribe(onStoreChange: () => void): Subscription {\n return state.subscribe(onStoreChange);\n },\n update(fn: (current: T) => T): void {\n state.update(fn);\n },\n get value(): T {\n return state.value;\n },\n };\n\n return api;\n};\n\n// === TYPE HELPERS ===\n\nexport const isSignal = <T = unknown>(value: unknown): value is ReadonlySignal<T> =>\n typeof value === 'object' && value !== null && !!(value as Record<typeof IS_SIGNAL, unknown>)[IS_SIGNAL];\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vielzeug/stateit",
3
- "version": "2.1.0",
3
+ "version": "3.0.3",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -32,9 +32,9 @@
32
32
  "registry": "https://registry.npmjs.org/"
33
33
  },
34
34
  "devDependencies": {
35
- "@types/node": "^25.5.0",
36
- "typescript": "~6.0.2",
37
- "vite": "^8.0.3",
38
- "vitest": "^4.1.2"
35
+ "@types/node": "^25.8.0",
36
+ "typescript": "~6.0.3",
37
+ "vite": "^8.0.13",
38
+ "vitest": "^4.1.6"
39
39
  }
40
40
  }
package/dist/types.d.ts DELETED
@@ -1,38 +0,0 @@
1
- export type CleanupFn = () => void;
2
- export type EffectCallback = () => CleanupFn | void;
3
- export type EqualityFn<T> = (a: T, b: T) => boolean;
4
- export type ReactiveOptions<T> = {
5
- equals?: EqualityFn<T>;
6
- };
7
- export interface Subscription {
8
- (): void;
9
- dispose(): void;
10
- [Symbol.dispose](): void;
11
- }
12
- export interface ReadonlySignal<T> {
13
- readonly value: T;
14
- }
15
- export interface Signal<T> extends ReadonlySignal<T> {
16
- value: T;
17
- update(fn: (current: T) => T): void;
18
- }
19
- export interface ComputedSignal<T> extends ReadonlySignal<T> {
20
- readonly stale: boolean;
21
- dispose(): void;
22
- [Symbol.dispose](): void;
23
- }
24
- export type EffectOptions = {
25
- maxIterations?: number;
26
- };
27
- export type WatchOptions<T> = {
28
- equals?: EqualityFn<T>;
29
- immediate?: boolean;
30
- once?: boolean;
31
- };
32
- export interface Store<T extends object> {
33
- readonly value: T;
34
- patch(partial: Partial<T>): void;
35
- update(fn: (state: T) => T): void;
36
- reset(): void;
37
- }
38
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC;AAEnC,MAAM,MAAM,cAAc,GAAG,MAAM,SAAS,GAAG,IAAI,CAAC;AAEpD,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC;AAEpD,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI;IAAE,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;CAAE,CAAC;AAE5D,MAAM,WAAW,YAAY;IAC3B,IAAI,IAAI,CAAC;IACT,OAAO,IAAI,IAAI,CAAC;IAChB,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;CACnB;AAED,MAAM,WAAW,MAAM,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IAClD,KAAK,EAAE,CAAC,CAAC;IACT,MAAM,CAAC,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IAC1D,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,OAAO,IAAI,IAAI,CAAC;IAChB,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAC5B,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,WAAW,KAAK,CAAC,CAAC,SAAS,MAAM;IACrC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACjC,MAAM,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAClC,KAAK,IAAI,IAAI,CAAC;CACf"}