@zeix/cause-effect 0.15.2 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -1 +1 @@
1
- class A extends Error{constructor($){super(`Circular dependency detected in ${$}`);this.name="CircularDependencyError"}}class c extends TypeError{constructor($,B){super(`Invalid signal value ${B} in ${$}`);this.name="InvalidSignalValueError"}}class V extends TypeError{constructor($){super(`Nullish signal values are not allowed in ${$}`);this.name="NullishSignalValueError"}}class n extends Error{constructor($,B){super(`Could not add store key "${$}" with value ${B} because it already exists`);this.name="StoreKeyExistsError"}}class v extends RangeError{constructor($){super(`Could not remove store index ${String($)} because it is out of range`);this.name="StoreKeyRangeError"}}class t extends Error{constructor($,B){super(`Could not set store key "${$}" to ${B} because it is readonly`);this.name="StoreKeyReadonlyError"}}var z=Symbol(),$$=($)=>typeof $==="string",M$=($)=>typeof $==="number",w=($)=>typeof $==="symbol",q=($)=>typeof $==="function",g=($)=>q($)&&$.constructor.name==="AsyncFunction",U$=($)=>!!$&&typeof $==="object",f=($,B)=>Object.prototype.toString.call($)===`[object ${B}]`,L=($)=>f($,"Object"),u=($)=>L($)||Array.isArray($),q$=($)=>{if(!$.length)return null;let B=$.map((Q)=>$$(Q)?parseInt(Q,10):M$(Q)?Q:NaN);return B.every((Q)=>Number.isFinite(Q)&&Q>=0)?B.sort((Q,X)=>Q-X):null};var O=($)=>$ instanceof DOMException&&$.name==="AbortError",N=($)=>$ instanceof Error?$:Error(String($));var s=($)=>{let B=q$(Object.keys($));if(B===null)return $;let Q=[];for(let X of B)Q.push($[String(X)]);return Q},i=($)=>$$($)?`"${$}"`:U$($)?JSON.stringify($):String($);var P=($,B,Q)=>{if(Object.is($,B))return!0;if(typeof $!==typeof B)return!1;if(typeof $!=="object"||$===null||B===null)return!1;if(!Q)Q=new WeakSet;if(Q.has($)||Q.has(B))throw new A("isEqual");Q.add($),Q.add(B);try{if(Array.isArray($)&&Array.isArray(B)){if($.length!==B.length)return!1;for(let X=0;X<$.length;X++)if(!P($[X],B[X],Q))return!1;return!0}if(Array.isArray($)!==Array.isArray(B))return!1;if(L($)&&L(B)){let X=Object.keys($),Z=Object.keys(B);if(X.length!==Z.length)return!1;for(let R of X){if(!(R in B))return!1;if(!P($[R],B[R],Q))return!1}return!0}return!1}finally{Q.delete($),Q.delete(B)}},B$=($,B)=>{let Q=u($),X=u(B);if(!Q||!X){let M=!Object.is($,B);return{changed:M,add:M&&X?B:{},change:{},remove:M&&Q?$:{}}}let Z=new WeakSet,R={},K={},H={},Y=Object.keys($),m=Object.keys(B),S=new Set([...Y,...m]);for(let M of S){let D=M in $,U=M in B;if(!D&&U){R[M]=B[M];continue}else if(D&&!U){H[M]=z;continue}let W=$[M],J=B[M];if(!P(W,J,Z))K[M]=J}return{changed:Object.keys(R).length>0||Object.keys(K).length>0||Object.keys(H).length>0,add:R,change:K,remove:H}};var T,r=new Set,J$=0,W$=new Map,l,z$=()=>{l=void 0;let $=Array.from(W$.values());W$.clear();for(let B of $)B()},L$=()=>{if(l)cancelAnimationFrame(l);l=requestAnimationFrame(z$)};queueMicrotask(z$);var b=($)=>{let B=new Set,Q=$;return Q.off=(X)=>{B.add(X)},Q.cleanup=()=>{for(let X of B)X();B.clear()},Q},j=($)=>{if(T&&!$.has(T)){let B=T;$.add(B),T.off(()=>{$.delete(B)})}},I=($)=>{for(let B of $)if(J$)r.add(B);else B()},a=()=>{while(r.size){let $=Array.from(r);r.clear();for(let B of $)B()}},Q$=($)=>{J$++;try{$()}finally{a(),J$--}},k=($,B)=>{let Q=T;T=B;try{$()}finally{T=Q}},N$=($,B)=>new Promise((Q,X)=>{W$.set(B||Symbol(),()=>{try{Q($())}catch(Z){X(Z)}}),L$()});var X$="Computed",Z$=($)=>{let B=new Set,Q=z,X,Z,R=!0,K=!1,H=!1,Y=(W)=>{if(!P(W,Q))Q=W,K=!0;X=void 0,R=!1},m=()=>{K=z!==Q,Q=z,X=void 0},S=(W)=>{let J=N(W);K=!X||J.name!==X.name||J.message!==X.message,Q=z,X=J},_=(W)=>(J)=>{if(H=!1,Z=void 0,W(J),K)I(B)},M=b(()=>{if(R=!0,Z?.abort(),B.size)I(B);else M.cleanup()});M.off(()=>{Z?.abort()});let D=()=>k(()=>{if(H)throw new A("computed");if(K=!1,g($)){if(Z)return Q;Z=new AbortController,Z.signal.addEventListener("abort",()=>{H=!1,Z=void 0,D()},{once:!0})}let W;H=!0;try{W=Z?$(Z.signal):$()}catch(J){if(O(J))m();else S(J);H=!1;return}if(W instanceof Promise)W.then(_(Y),_(S));else if(W==null||z===W)m();else Y(W);H=!1},M);return{[Symbol.toStringTag]:X$,get:()=>{if(j(B),a(),R)D();if(X)throw X;return Q}}},h=($)=>f($,X$),x$=($)=>q($)&&$.length<2;var C$=($)=>{let B=g($),Q=!1,X,Z=b(()=>k(()=>{if(Q)throw new A("effect");Q=!0,X?.abort(),X=void 0;let R;try{if(B){X=new AbortController;let K=X;$(X.signal).then((H)=>{if(q(H)&&X===K)Z.off(H)}).catch((H)=>{if(!O(H))console.error("Async effect error:",H)})}else if(R=$(),q(R))Z.off(R)}catch(K){if(!O(K))console.error("Effect callback error:",K)}Q=!1},Z));return Z(),()=>{X?.abort(),Z.cleanup()}};function A$($,B){try{if($.pending)B.nil?.();else if($.errors)B.err?.($.errors);else if($.ok)B.ok($.values)}catch(Q){if(B.err&&(!$.errors||!$.errors.includes(N(Q))))B.err($.errors?[...$.errors,N(Q)]:[N(Q)]);else throw Q}}function P$($){let B=[],Q=!1,X={};for(let[Z,R]of Object.entries($))try{let K=R.get();if(K===z)Q=!0;else X[Z]=K}catch(K){B.push(N(K))}if(Q)return{ok:!1,pending:!0};if(B.length>0)return{ok:!1,errors:B};return{ok:!0,values:X}}var G$="State",y=($)=>{let B=new Set,Q=$,X={[Symbol.toStringTag]:G$,get:()=>{return j(B),Q},set:(Z)=>{if(Z==null)throw new V("state");if(P(Q,Z))return;if(Q=Z,I(B),z===Q)B.clear()},update:(Z)=>{X.set(Z(Q))}};return X},E=($)=>f($,G$);var e="Store",R$="store-add",F$="store-change",Y$="store-remove",j$="store-sort",p=($)=>{let B=new Set,Q=new EventTarget,X=new Map,Z=new Map,R=Array.isArray($),K=y(0),H=()=>{let W={};for(let[J,C]of X)W[J]=C.get();return W},Y=(W,J)=>Q.dispatchEvent(new CustomEvent(W,{detail:J})),m=()=>Array.from(X.keys()).map((W)=>Number(W)).filter((W)=>Number.isInteger(W)).sort((W,J)=>W-J),S=(W,J)=>{if(J==null)throw new V(`store for key "${W}"`);if(J===z)return!0;if(w(J)||q(J)||h(J))throw new c(`store for key "${W}"`,i(J));return!0},_=(W,J,C=!1)=>{if(!S(W,J))return!1;let x=E(J)||o(J)?J:L(J)?p(J):Array.isArray(J)?p(J):y(J);X.set(W,x);let G=C$(()=>{let F=x.get();if(F!=null)Y(F$,{[W]:F})});if(Z.set(W,G),C)K.set(X.size),I(B),Y(R$,{[W]:J});return!0},M=(W,J=!1)=>{let C=X.delete(W);if(C){let x=Z.get(W);if(x)x();Z.delete(W)}if(J)K.set(X.size),I(B),Y(Y$,{[W]:z});return C},D=(W,J,C)=>{let x=B$(W,J);return Q$(()=>{if(Object.keys(x.add).length){for(let G in x.add){let F=x.add[G]??z;_(G,F)}if(C)setTimeout(()=>{Y(R$,x.add)},0);else Y(R$,x.add)}if(Object.keys(x.change).length){for(let G in x.change){let F=x.change[G];if(!S(G,F))continue;let d=X.get(G);if(K$(d))d.set(F);else throw new t(G,i(F))}Y(F$,x.change)}if(Object.keys(x.remove).length){for(let G in x.remove)M(G);Y(Y$,x.remove)}K.set(X.size)}),x.changed};D({},$,!0);let U={add:R?(W)=>{let J=X.size,C=String(J);_(C,W,!0)}:(W,J)=>{if(!X.has(W))_(W,J,!0);else throw new n(W,i(J))},get:()=>{return j(B),s(H())},remove:R?(W)=>{let J=s(H()),C=X.size;if(!Array.isArray(J)||W<=-C||W>=C)throw new v(W);let x=[...J];if(x.splice(W,1),D(J,x))I(B)}:(W)=>{if(X.has(W))M(W,!0)},set:(W)=>{if(D(H(),W)){if(I(B),z===W)B.clear()}},update:(W)=>{let J=H(),C=W(s(J));if(D(J,C)){if(I(B),z===C)B.clear()}},sort:(W)=>{let J=Array.from(X.entries()).map(([G,F])=>[G,F.get()]).sort(W?(G,F)=>W(G[1],F[1]):(G,F)=>String(G[1]).localeCompare(String(F[1]))),C=J.map(([G])=>String(G)),x=new Map;J.forEach(([G],F)=>{let d=String(G),D$=R?String(F):String(G),H$=X.get(d);if(H$)x.set(D$,H$)}),X.clear(),x.forEach((G,F)=>X.set(F,G)),I(B),Y(j$,C)},addEventListener:Q.addEventListener.bind(Q),removeEventListener:Q.removeEventListener.bind(Q),dispatchEvent:Q.dispatchEvent.bind(Q),size:K};return new Proxy({},{get(W,J){if(J===Symbol.toStringTag)return e;if(J===Symbol.isConcatSpreadable)return R;if(J===Symbol.iterator)return R?function*(){let C=m();for(let x of C){let G=X.get(String(x));if(G)yield G}}:function*(){for(let[C,x]of X)yield[C,x]};if(w(J))return;if(J in U)return U[J];if(J==="length"&&R)return j(B),K.get();return X.get(J)},has(W,J){let C=String(J);return C&&X.has(C)||Object.keys(U).includes(C)||J===Symbol.toStringTag||J===Symbol.iterator||J===Symbol.isConcatSpreadable||J==="length"&&R},ownKeys(){return R?m().map((W)=>String(W)).concat(["length"]):Array.from(X.keys()).map((W)=>String(W))},getOwnPropertyDescriptor(W,J){let C=(G)=>({enumerable:!1,configurable:!0,writable:!1,value:G});if(J==="length"&&R)return{enumerable:!0,configurable:!0,writable:!1,value:K.get()};if(J===Symbol.isConcatSpreadable)return C(R);if(J===Symbol.toStringTag)return C(e);if(w(J))return;if(Object.keys(U).includes(J))return C(U[J]);let x=X.get(J);return x?{enumerable:!0,configurable:!0,writable:!0,value:x}:void 0}})},o=($)=>f($,e);var I$=($)=>E($)||h($)||o($),K$=($)=>E($)||o($);function m$($){if(I$($))return $;if(x$($))return Z$($);if(Array.isArray($)||L($))return p($);return y($)}export{b as watch,m$ as toSignal,N as toError,j as subscribe,p as store,y as state,P$ as resolve,k as observe,I as notify,A$ as match,w as isSymbol,$$ as isString,o as isStore,E as isState,I$ as isSignal,u as isRecordOrArray,L as isRecord,M$ as isNumber,K$ as isMutableSignal,q as isFunction,P as isEqual,x$ as isComputedCallback,h as isComputed,g as isAsyncFunction,O as isAbortError,a as flush,N$ as enqueue,C$ as effect,B$ as diff,Z$ as computed,Q$ as batch,z as UNSET,e as TYPE_STORE,G$ as TYPE_STATE,X$ as TYPE_COMPUTED,t as StoreKeyReadonlyError,v as StoreKeyRangeError,n as StoreKeyExistsError,V as NullishSignalValueError,c as InvalidSignalValueError,A as CircularDependencyError};
1
+ class _ extends Error{constructor($){super(`Circular dependency detected in ${$}`);this.name="CircularDependencyError"}}class W extends TypeError{constructor($,x){super(`Invalid ${$} callback ${x}`);this.name="InvalidCallbackError"}}class h extends TypeError{constructor($,x){super(`Invalid signal value ${x} in ${$}`);this.name="InvalidSignalValueError"}}class L extends TypeError{constructor($){super(`Nullish signal values are not allowed in ${$}`);this.name="NullishSignalValueError"}}class v extends Error{constructor($,x){super(`Could not add store key "${$}" with value ${x} because it already exists`);this.name="StoreKeyExistsError"}}class n extends RangeError{constructor($){super(`Could not remove store index ${String($)} because it is out of range`);this.name="StoreKeyRangeError"}}class u extends Error{constructor($,x){super(`Could not set store key "${$}" to ${x} because it is readonly`);this.name="StoreKeyReadonlyError"}}var q=Symbol(),e=($)=>typeof $==="string",X$=($)=>typeof $==="number",c=($)=>typeof $==="symbol",K=($)=>typeof $==="function",g=($)=>K($)&&$.constructor.name==="AsyncFunction",m=($,x)=>Object.prototype.toString.call($)===`[object ${x}]`,A=($)=>m($,"Object"),s=($)=>A($)||Array.isArray($),H$=($)=>{if(!$.length)return null;let x=$.map((z)=>e(z)?parseInt(z,10):X$(z)?z:NaN);return x.every((z)=>Number.isFinite(z)&&z>=0)?x.sort((z,J)=>z-J):null};var y=($)=>$ instanceof DOMException&&$.name==="AbortError",U=($)=>$ instanceof Error?$:Error(String($));var t=($)=>{let x=H$(Object.keys($));if(x===null)return $;let z=[];for(let J of x)z.push($[String(J)]);return z},F=($)=>e($)?`"${$}"`:!!$&&typeof $==="object"?JSON.stringify($):String($);var f=($,x,z)=>{if(Object.is($,x))return!0;if(typeof $!==typeof x)return!1;if(typeof $!=="object"||$===null||x===null)return!1;if(!z)z=new WeakSet;if(z.has($)||z.has(x))throw new _("isEqual");z.add($),z.add(x);try{if(Array.isArray($)&&Array.isArray(x)){if($.length!==x.length)return!1;for(let J=0;J<$.length;J++)if(!f($[J],x[J],z))return!1;return!0}if(Array.isArray($)!==Array.isArray(x))return!1;if(A($)&&A(x)){let J=Object.keys($),X=Object.keys(x);if(J.length!==X.length)return!1;for(let M of J){if(!(M in x))return!1;if(!f($[M],x[M],z))return!1}return!0}return!1}finally{z.delete($),z.delete(x)}},$$=($,x)=>{let z=s($),J=s(x);if(!z||!J){let C=!Object.is($,x);return{changed:C,add:C&&J?x:{},change:{},remove:C&&z?$:{}}}let X=new WeakSet,M={},H={},I={},Y=Object.keys($),E=Object.keys(x),P=new Set([...Y,...E]);for(let C of P){let N=C in $,R=C in x;if(!N&&R){M[C]=x[C];continue}else if(N&&!R){I[C]=q;continue}let B=$[C],G=x[C];if(!f(B,G,X))H[C]=G}return{changed:Object.keys(M).length>0||Object.keys(H).length>0||Object.keys(I).length>0,add:M,change:H,remove:I}};var p,i=new Set,x$=0,O=($)=>{let x=new Set,z=$;return z.unwatch=(J)=>{x.add(J)},z.cleanup=()=>{for(let J of x)J();x.clear()},z},j=($)=>{if(p&&!$.has(p)){let x=p;x.unwatch(()=>{$.delete(x)}),$.add(x)}},T=($)=>{for(let x of $)if(x$)i.add(x);else x()},r=()=>{while(i.size){let $=Array.from(i);i.clear();for(let x of $)x()}},R$=($)=>{x$++;try{$()}finally{r(),x$--}},S=($,x)=>{let z=p;p=x;try{$()}finally{p=z}};var B$="Computed",J$=($,x=q)=>{if(!l($))throw new W("computed",F($));if(x==null)throw new L("computed");let z=new Set,J=x,X,M,H=!0,I=!1,Y=!1,E=(G)=>{if(!f(G,J))J=G,I=!0;X=void 0,H=!1},P=()=>{I=q!==J,J=q,X=void 0},V=(G)=>{let Q=U(G);I=!X||Q.name!==X.name||Q.message!==X.message,J=q,X=Q},C=(G)=>(Q)=>{if(Y=!1,M=void 0,G(Q),I)T(z)},N=O(()=>{if(H=!0,M?.abort(),z.size)T(z);else N.cleanup()});N.unwatch(()=>{M?.abort()});let R=()=>S(()=>{if(Y)throw new _("computed");if(I=!1,g($)){if(M)return J;M=new AbortController,M.signal.addEventListener("abort",()=>{Y=!1,M=void 0,R()},{once:!0})}let G;Y=!0;try{G=M?$(J,M.signal):$(J)}catch(Q){if(y(Q))P();else V(Q);Y=!1;return}if(G instanceof Promise)G.then(C(E),C(V));else if(G==null||q===G)P();else E(G);Y=!1},N),B={};return Object.defineProperties(B,{[Symbol.toStringTag]:{value:B$},get:{value:()=>{if(j(z),r(),H)R();if(X)throw X;return J}}}),B},w=($)=>m($,B$),l=($)=>K($)&&$.length<3;var C$=($)=>{if(!K($)||$.length>1)throw new W("effect",F($));let x=g($),z=!1,J,X=O(()=>S(()=>{if(z)throw new _("effect");z=!0,J?.abort(),J=void 0;let M;try{if(x){J=new AbortController;let H=J;$(J.signal).then((I)=>{if(K(I)&&J===H)X.unwatch(I)}).catch((I)=>{if(!y(I))console.error("Async effect error:",I)})}else if(M=$(),K(M))X.unwatch(M)}catch(H){if(!y(H))console.error("Effect callback error:",H)}z=!1},X));return X(),()=>{J?.abort(),X.cleanup()}};function q$($,x){try{if($.pending)x.nil?.();else if($.errors)x.err?.($.errors);else if($.ok)x.ok($.values)}catch(z){if(x.err&&(!$.errors||!$.errors.includes(U(z))))x.err($.errors?[...$.errors,U(z)]:[U(z)]);else throw z}}function D$($){let x=[],z=!1,J={};for(let[X,M]of Object.entries($))try{let H=M.get();if(H===q)z=!0;else J[X]=H}catch(H){x.push(U(H))}if(z)return{ok:!1,pending:!0};if(x.length>0)return{ok:!1,errors:x};return{ok:!0,values:J}}var z$="State",k=($)=>{if($==null)throw new L("state");let x=new Set,z=$,J=(M)=>{if(M==null)throw new L("state");if(f(z,M))return;if(z=M,T(x),q===z)x.clear()},X={};return Object.defineProperties(X,{[Symbol.toStringTag]:{value:z$},get:{value:()=>{return j(x),z}},set:{value:(M)=>{J(M)}},update:{value:(M)=>{if(!K(M))throw new W("state update",F(M));J(M(z))}}}),X},b=($)=>m($,z$);var G$="Store",a=($)=>{if($==null)throw new L("store");let x=new Set,z={add:new Set,change:new Set,remove:new Set,sort:new Set},J=new Map,X=new Map,M=Array.isArray($),H=()=>{let R={};for(let[B,G]of J)R[B]=G.get();return R},I=(R,B)=>{Object.freeze(B);for(let G of z[R])G(B)},Y=()=>Array.from(J.keys()).map((R)=>Number(R)).filter((R)=>Number.isInteger(R)).sort((R,B)=>R-B),E=(R,B)=>{if(B==null)throw new L(`store for key "${R}"`);if(B===q)return!0;if(c(B)||K(B)||w(B))throw new h(`store for key "${R}"`,F(B));return!0},P=(R,B,G=!1)=>{if(!E(R,B))return!1;let Q=b(B)||o(B)?B:A(B)||Array.isArray(B)?a(B):k(B);J.set(R,Q);let Z=O(()=>S(()=>{I("change",{[R]:Q.get()})},Z));if(Z(),X.set(R,Z),G)T(x),I("add",{[R]:B});return!0},V=(R,B=!1)=>{let G=J.delete(R);if(G){let Q=X.get(R);if(Q)Q.cleanup();X.delete(R)}if(B)T(x),I("remove",{[R]:q});return G},C=(R,B,G)=>{let Q=$$(R,B);return R$(()=>{if(Object.keys(Q.add).length){for(let Z in Q.add)P(Z,Q.add[Z]??q);if(G)setTimeout(()=>{I("add",Q.add)},0);else I("add",Q.add)}if(Object.keys(Q.change).length){for(let Z in Q.change){let D=Q.change[Z];if(!E(Z,D))continue;let d=J.get(Z);if(M$(d))d.set(D);else throw new u(Z,F(D))}I("change",Q.change)}if(Object.keys(Q.remove).length){for(let Z in Q.remove)V(Z);I("remove",Q.remove)}}),Q.changed};C({},$,!0);let N={};return Object.defineProperties(N,{[Symbol.toStringTag]:{value:G$},[Symbol.isConcatSpreadable]:{value:M},[Symbol.iterator]:{value:M?function*(){let R=Y();for(let B of R){let G=J.get(String(B));if(G)yield G}}:function*(){for(let[R,B]of J)yield[R,B]}},add:{value:M?(R)=>{P(String(J.size),R,!0)}:(R,B)=>{if(!J.has(R))P(R,B,!0);else throw new v(R,F(B))}},get:{value:()=>{return j(x),t(H())}},remove:{value:M?(R)=>{let B=t(H()),G=J.size;if(!Array.isArray(B)||R<=-G||R>=G)throw new n(R);let Q=[...B];if(Q.splice(R,1),C(B,Q))T(x)}:(R)=>{if(J.has(R))V(R,!0)}},set:{value:(R)=>{if(C(H(),R)){if(T(x),q===R)x.clear()}}},update:{value:(R)=>{let B=H(),G=R(t(B));if(C(B,G)){if(T(x),q===G)x.clear()}}},sort:{value:(R)=>{let B=Array.from(J.entries()).map(([Z,D])=>[Z,D.get()]).sort(R?(Z,D)=>R(Z[1],D[1]):(Z,D)=>String(Z[1]).localeCompare(String(D[1]))),G=B.map(([Z])=>String(Z)),Q=new Map;B.forEach(([Z],D)=>{let d=String(Z),I$=M?String(D):String(Z),Q$=J.get(d);if(Q$)Q.set(I$,Q$)}),J.clear(),Q.forEach((Z,D)=>J.set(D,Z)),T(x),I("sort",G)}},on:{value:(R,B)=>{return z[R].add(B),()=>z[R].delete(B)}},length:{get(){return j(x),J.size}}}),new Proxy(N,{get(R,B){if(B in R)return Reflect.get(R,B);if(c(B))return;return J.get(B)},has(R,B){if(B in R)return!0;return J.has(String(B))},ownKeys(R){let B=Reflect.ownKeys(R),G=M?Y().map((Q)=>String(Q)):Array.from(J.keys());return[...new Set([...G,...B])]},getOwnPropertyDescriptor(R,B){if(B in R)return Reflect.getOwnPropertyDescriptor(R,B);let G=J.get(String(B));return G?{enumerable:!0,configurable:!0,writable:!0,value:G}:void 0}})},o=($)=>m($,G$);var Z$=($)=>b($)||w($)||o($),M$=($)=>b($)||o($);function T$($){if(Z$($))return $;if(l($))return J$($);if(Array.isArray($)||A($))return a($);return k($)}export{F as valueString,T$ as toSignal,U as toError,j as subscribe,D$ as resolve,S as observe,T as notify,q$ as match,c as isSymbol,e as isString,o as isStore,b as isState,Z$ as isSignal,s as isRecordOrArray,A as isRecord,m as isObjectOfType,X$ as isNumber,M$ as isMutableSignal,K as isFunction,f as isEqual,l as isComputedCallback,w as isComputed,g as isAsyncFunction,y as isAbortError,r as flush,$$ as diff,O as createWatcher,a as createStore,k as createState,C$ as createEffect,J$ as createComputed,R$ as batch,q as UNSET,G$ as TYPE_STORE,z$ as TYPE_STATE,B$ as TYPE_COMPUTED,u as StoreKeyReadonlyError,n as StoreKeyRangeError,v as StoreKeyExistsError,L as NullishSignalValueError,h as InvalidSignalValueError,W as InvalidCallbackError,_ as CircularDependencyError};
package/index.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * @name Cause & Effect
3
- * @version 0.15.1
3
+ * @version 0.16.1
4
4
  * @author Esther Brunner
5
5
  */
6
6
 
7
7
  export {
8
8
  type Computed,
9
9
  type ComputedCallback,
10
- computed,
10
+ createComputed,
11
11
  isComputed,
12
12
  isComputedCallback,
13
13
  TYPE_COMPUTED,
@@ -16,13 +16,18 @@ export {
16
16
  type DiffResult,
17
17
  diff,
18
18
  isEqual,
19
+ type PartialRecord,
19
20
  type UnknownArray,
20
21
  type UnknownRecord,
21
- type UnknownRecordOrArray,
22
22
  } from './src/diff'
23
- export { type EffectCallback, effect, type MaybeCleanup } from './src/effect'
23
+ export {
24
+ createEffect,
25
+ type EffectCallback,
26
+ type MaybeCleanup,
27
+ } from './src/effect'
24
28
  export {
25
29
  CircularDependencyError,
30
+ InvalidCallbackError,
26
31
  InvalidSignalValueError,
27
32
  NullishSignalValueError,
28
33
  StoreKeyExistsError,
@@ -31,18 +36,6 @@ export {
31
36
  } from './src/errors'
32
37
  export { type MatchHandlers, match } from './src/match'
33
38
  export { type ResolveResult, resolve } from './src/resolve'
34
- export {
35
- batch,
36
- type Cleanup,
37
- enqueue,
38
- flush,
39
- notify,
40
- observe,
41
- subscribe,
42
- type Updater,
43
- type Watcher,
44
- watch,
45
- } from './src/scheduler'
46
39
  export {
47
40
  isMutableSignal,
48
41
  isSignal,
@@ -51,27 +44,35 @@ export {
51
44
  toSignal,
52
45
  type UnknownSignalRecord,
53
46
  } from './src/signal'
54
- export { isState, type State, state, TYPE_STATE } from './src/state'
47
+ export { createState, isState, type State, TYPE_STATE } from './src/state'
55
48
  export {
49
+ createStore,
56
50
  isStore,
57
51
  type Store,
58
- type StoreAddEvent,
59
- type StoreChangeEvent,
60
- type StoreEventMap,
61
- type StoreRemoveEvent,
62
- type StoreSortEvent,
63
- store,
52
+ type StoreChanges,
64
53
  TYPE_STORE,
65
54
  } from './src/store'
55
+ export {
56
+ batch,
57
+ type Cleanup,
58
+ createWatcher,
59
+ flush,
60
+ notify,
61
+ observe,
62
+ subscribe,
63
+ type Watcher,
64
+ } from './src/system'
66
65
  export {
67
66
  isAbortError,
68
67
  isAsyncFunction,
69
68
  isFunction,
70
69
  isNumber,
70
+ isObjectOfType,
71
71
  isRecord,
72
72
  isRecordOrArray,
73
73
  isString,
74
74
  isSymbol,
75
75
  toError,
76
76
  UNSET,
77
+ valueString,
77
78
  } from './src/util'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeix/cause-effect",
3
- "version": "0.15.2",
3
+ "version": "0.16.1",
4
4
  "author": "Esther Brunner",
5
5
  "main": "index.js",
6
6
  "module": "index.ts",
package/src/computed.ts CHANGED
@@ -1,13 +1,17 @@
1
1
  import { isEqual } from './diff'
2
- import { CircularDependencyError } from './errors'
3
2
  import {
3
+ CircularDependencyError,
4
+ InvalidCallbackError,
5
+ NullishSignalValueError,
6
+ } from './errors'
7
+ import {
8
+ createWatcher,
4
9
  flush,
5
10
  notify,
6
11
  observe,
7
12
  subscribe,
8
13
  type Watcher,
9
- watch,
10
- } from './scheduler'
14
+ } from './system'
11
15
  import {
12
16
  isAbortError,
13
17
  isAsyncFunction,
@@ -15,17 +19,18 @@ import {
15
19
  isObjectOfType,
16
20
  toError,
17
21
  UNSET,
22
+ valueString,
18
23
  } from './util'
19
24
 
20
25
  /* === Types === */
21
26
 
22
27
  type Computed<T extends {}> = {
23
- [Symbol.toStringTag]: 'Computed'
28
+ readonly [Symbol.toStringTag]: 'Computed'
24
29
  get(): T
25
30
  }
26
31
  type ComputedCallback<T extends {} & { then?: undefined }> =
27
- | ((abort: AbortSignal) => Promise<T>)
28
- | (() => T)
32
+ | ((oldValue: T, abort: AbortSignal) => Promise<T>)
33
+ | ((oldValue: T) => T)
29
34
 
30
35
  /* === Constants === */
31
36
 
@@ -37,14 +42,21 @@ const TYPE_COMPUTED = 'Computed'
37
42
  * Create a derived signal from existing signals
38
43
  *
39
44
  * @since 0.9.0
40
- * @param {ComputedCallback<T>} fn - computation callback function
45
+ * @param {ComputedCallback<T>} callback - Computation callback function
41
46
  * @returns {Computed<T>} - Computed signal
42
47
  */
43
- const computed = <T extends {}>(fn: ComputedCallback<T>): Computed<T> => {
48
+ const createComputed = <T extends {}>(
49
+ callback: ComputedCallback<T>,
50
+ initialValue: T = UNSET,
51
+ ): Computed<T> => {
52
+ if (!isComputedCallback(callback))
53
+ throw new InvalidCallbackError('computed', valueString(callback))
54
+ if (initialValue == null) throw new NullishSignalValueError('computed')
55
+
44
56
  const watchers: Set<Watcher> = new Set()
45
57
 
46
58
  // Internal state
47
- let value: T = UNSET
59
+ let value: T = initialValue
48
60
  let error: Error | undefined
49
61
  let controller: AbortController | undefined
50
62
  let dirty = true
@@ -75,22 +87,22 @@ const computed = <T extends {}>(fn: ComputedCallback<T>): Computed<T> => {
75
87
  error = newError
76
88
  }
77
89
  const settle =
78
- <T>(settleFn: (arg: T) => void) =>
90
+ <T>(fn: (arg: T) => void) =>
79
91
  (arg: T) => {
80
92
  computing = false
81
93
  controller = undefined
82
- settleFn(arg)
94
+ fn(arg)
83
95
  if (changed) notify(watchers)
84
96
  }
85
97
 
86
98
  // Own watcher: called when notified from sources (push)
87
- const mark = watch(() => {
99
+ const watcher = createWatcher(() => {
88
100
  dirty = true
89
101
  controller?.abort()
90
102
  if (watchers.size) notify(watchers)
91
- else mark.cleanup()
103
+ else watcher.cleanup()
92
104
  })
93
- mark.off(() => {
105
+ watcher.unwatch(() => {
94
106
  controller?.abort()
95
107
  })
96
108
 
@@ -99,7 +111,7 @@ const computed = <T extends {}>(fn: ComputedCallback<T>): Computed<T> => {
99
111
  observe(() => {
100
112
  if (computing) throw new CircularDependencyError('computed')
101
113
  changed = false
102
- if (isAsyncFunction(fn)) {
114
+ if (isAsyncFunction(callback)) {
103
115
  // Return current value until promise resolves
104
116
  if (controller) return value
105
117
  controller = new AbortController()
@@ -108,9 +120,7 @@ const computed = <T extends {}>(fn: ComputedCallback<T>): Computed<T> => {
108
120
  () => {
109
121
  computing = false
110
122
  controller = undefined
111
-
112
- // Retry computation with updated state
113
- compute()
123
+ compute() // Retry computation with updated state
114
124
  },
115
125
  {
116
126
  once: true,
@@ -120,7 +130,9 @@ const computed = <T extends {}>(fn: ComputedCallback<T>): Computed<T> => {
120
130
  let result: T | Promise<T>
121
131
  computing = true
122
132
  try {
123
- result = controller ? fn(controller.signal) : (fn as () => T)()
133
+ result = controller
134
+ ? callback(value, controller.signal)
135
+ : (callback as (oldValue: T) => T)(value)
124
136
  } catch (e) {
125
137
  if (isAbortError(e)) nil()
126
138
  else err(e)
@@ -131,34 +143,32 @@ const computed = <T extends {}>(fn: ComputedCallback<T>): Computed<T> => {
131
143
  else if (null == result || UNSET === result) nil()
132
144
  else ok(result)
133
145
  computing = false
134
- }, mark)
135
-
136
- const c: Computed<T> = {
137
- [Symbol.toStringTag]: TYPE_COMPUTED,
138
-
139
- /**
140
- * Get the current value of the computed
141
- *
142
- * @since 0.9.0
143
- * @returns {T} - current value of the computed
144
- */
145
- get: (): T => {
146
- subscribe(watchers)
147
- flush()
148
- if (dirty) compute()
149
- if (error) throw error
150
- return value
146
+ }, watcher)
147
+
148
+ const computed: Record<PropertyKey, unknown> = {}
149
+ Object.defineProperties(computed, {
150
+ [Symbol.toStringTag]: {
151
+ value: TYPE_COMPUTED,
151
152
  },
152
- }
153
- return c
153
+ get: {
154
+ value: (): T => {
155
+ subscribe(watchers)
156
+ flush()
157
+ if (dirty) compute()
158
+ if (error) throw error
159
+ return value
160
+ },
161
+ },
162
+ })
163
+ return computed as Computed<T>
154
164
  }
155
165
 
156
166
  /**
157
- * Check if a value is a computed state
167
+ * Check if a value is a computed signal
158
168
  *
159
169
  * @since 0.9.0
160
- * @param {unknown} value - value to check
161
- * @returns {boolean} - true if value is a computed state, false otherwise
170
+ * @param {unknown} value - Value to check
171
+ * @returns {boolean} - true if value is a computed signal, false otherwise
162
172
  */
163
173
  const isComputed = /*#__PURE__*/ <T extends {}>(
164
174
  value: unknown,
@@ -168,18 +178,18 @@ const isComputed = /*#__PURE__*/ <T extends {}>(
168
178
  * Check if the provided value is a callback that may be used as input for toSignal() to derive a computed state
169
179
  *
170
180
  * @since 0.12.0
171
- * @param {unknown} value - value to check
181
+ * @param {unknown} value - Value to check
172
182
  * @returns {boolean} - true if value is a callback or callbacks object, false otherwise
173
183
  */
174
184
  const isComputedCallback = /*#__PURE__*/ <T extends {}>(
175
185
  value: unknown,
176
- ): value is ComputedCallback<T> => isFunction(value) && value.length < 2
186
+ ): value is ComputedCallback<T> => isFunction(value) && value.length < 3
177
187
 
178
188
  /* === Exports === */
179
189
 
180
190
  export {
181
191
  TYPE_COMPUTED,
182
- computed,
192
+ createComputed,
183
193
  isComputed,
184
194
  isComputedCallback,
185
195
  type Computed,
package/src/diff.ts CHANGED
@@ -5,16 +5,20 @@ import { isRecord, isRecordOrArray, UNSET } from './util'
5
5
 
6
6
  type UnknownRecord = Record<string, unknown & {}>
7
7
  type UnknownArray = ReadonlyArray<unknown & {}>
8
+
8
9
  type ArrayToRecord<T extends UnknownArray> = {
9
10
  [key: string]: T extends Array<infer U extends {}> ? U : never
10
11
  }
11
- type UnknownRecordOrArray = UnknownRecord | ArrayToRecord<UnknownArray>
12
12
 
13
- type DiffResult<T extends UnknownRecordOrArray = UnknownRecord> = {
13
+ type PartialRecord<T> = T extends UnknownArray
14
+ ? Partial<ArrayToRecord<T>>
15
+ : Partial<T>
16
+
17
+ type DiffResult<T extends UnknownRecord | UnknownArray = UnknownRecord> = {
14
18
  changed: boolean
15
- add: Partial<T>
16
- change: Partial<T>
17
- remove: Partial<T>
19
+ add: PartialRecord<T>
20
+ change: PartialRecord<T>
21
+ remove: PartialRecord<T>
18
22
  }
19
23
 
20
24
  /* === Functions === */
@@ -88,9 +92,9 @@ const isEqual = <T>(a: T, b: T, visited?: WeakSet<object>): boolean => {
88
92
  * @param {T} newObj - The new record to compare
89
93
  * @returns {DiffResult<T>} The result of the comparison
90
94
  */
91
- const diff = <T extends UnknownRecordOrArray>(
92
- oldObj: T,
93
- newObj: T,
95
+ const diff = <T extends UnknownRecord | UnknownArray>(
96
+ oldObj: T extends UnknownArray ? ArrayToRecord<T> : T,
97
+ newObj: T extends UnknownArray ? ArrayToRecord<T> : T,
94
98
  ): DiffResult<T> => {
95
99
  // Guard against non-objects that can't be diffed properly with Object.keys and 'in' operator
96
100
  const oldValid = isRecordOrArray(oldObj)
@@ -100,17 +104,17 @@ const diff = <T extends UnknownRecordOrArray>(
100
104
  const changed = !Object.is(oldObj, newObj)
101
105
  return {
102
106
  changed,
103
- add: changed && newValid ? newObj : {},
104
- change: {},
105
- remove: changed && oldValid ? oldObj : {},
107
+ add: changed && newValid ? newObj : ({} as PartialRecord<T>),
108
+ change: {} as PartialRecord<T>,
109
+ remove: changed && oldValid ? oldObj : ({} as PartialRecord<T>),
106
110
  }
107
111
  }
108
112
 
109
113
  const visited = new WeakSet()
110
114
 
111
- const add: Partial<T> = {}
112
- const change: Partial<T> = {}
113
- const remove: Partial<T> = {}
115
+ const add = {} as PartialRecord<T>
116
+ const change = {} as PartialRecord<T>
117
+ const remove = {} as PartialRecord<T>
114
118
 
115
119
  const oldKeys = Object.keys(oldObj)
116
120
  const newKeys = Object.keys(newObj)
@@ -121,18 +125,17 @@ const diff = <T extends UnknownRecordOrArray>(
121
125
  const newHas = key in newObj
122
126
 
123
127
  if (!oldHas && newHas) {
124
- add[key as keyof T] = newObj[key] as T[keyof T]
128
+ add[key] = newObj[key]
125
129
  continue
126
130
  } else if (oldHas && !newHas) {
127
- remove[key as keyof T] = UNSET
131
+ remove[key] = UNSET
128
132
  continue
129
133
  }
130
134
 
131
- const oldValue = oldObj[key] as T[keyof T]
132
- const newValue = newObj[key] as T[keyof T]
135
+ const oldValue = oldObj[key]
136
+ const newValue = newObj[key]
133
137
 
134
- if (!isEqual(oldValue, newValue, visited))
135
- change[key as keyof T] = newValue
138
+ if (!isEqual(oldValue, newValue, visited)) change[key] = newValue
136
139
  }
137
140
 
138
141
  const changed =
@@ -157,5 +160,5 @@ export {
157
160
  isEqual,
158
161
  type UnknownRecord,
159
162
  type UnknownArray,
160
- type UnknownRecordOrArray,
163
+ type PartialRecord,
161
164
  }
package/src/effect.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { CircularDependencyError } from './errors'
2
- import { type Cleanup, observe, watch } from './scheduler'
3
- import { isAbortError, isAsyncFunction, isFunction } from './util'
1
+ import { CircularDependencyError, InvalidCallbackError } from './errors'
2
+ import { type Cleanup, createWatcher, observe } from './system'
3
+ import { isAbortError, isAsyncFunction, isFunction, valueString } from './util'
4
4
 
5
5
  /* === Types === */
6
6
 
@@ -24,12 +24,15 @@ type EffectCallback =
24
24
  * @param {EffectCallback} callback - Synchronous or asynchronous effect callback
25
25
  * @returns {Cleanup} - Cleanup function for the effect
26
26
  */
27
- const effect = (callback: EffectCallback): Cleanup => {
28
- const isAsync = isAsyncFunction<MaybeCleanup>(callback)
27
+ const createEffect = (callback: EffectCallback): Cleanup => {
28
+ if (!isFunction(callback) || callback.length > 1)
29
+ throw new InvalidCallbackError('effect', valueString(callback))
30
+
31
+ const isAsync = isAsyncFunction(callback)
29
32
  let running = false
30
33
  let controller: AbortController | undefined
31
34
 
32
- const run = watch(() =>
35
+ const watcher = createWatcher(() =>
33
36
  observe(() => {
34
37
  if (running) throw new CircularDependencyError('effect')
35
38
  running = true
@@ -52,7 +55,7 @@ const effect = (callback: EffectCallback): Cleanup => {
52
55
  isFunction(cleanup) &&
53
56
  controller === currentController
54
57
  )
55
- run.off(cleanup)
58
+ watcher.unwatch(cleanup)
56
59
  })
57
60
  .catch(error => {
58
61
  if (!isAbortError(error))
@@ -60,7 +63,7 @@ const effect = (callback: EffectCallback): Cleanup => {
60
63
  })
61
64
  } else {
62
65
  cleanup = (callback as () => MaybeCleanup)()
63
- if (isFunction(cleanup)) run.off(cleanup)
66
+ if (isFunction(cleanup)) watcher.unwatch(cleanup)
64
67
  }
65
68
  } catch (error) {
66
69
  if (!isAbortError(error))
@@ -68,16 +71,16 @@ const effect = (callback: EffectCallback): Cleanup => {
68
71
  }
69
72
 
70
73
  running = false
71
- }, run),
74
+ }, watcher),
72
75
  )
73
76
 
74
- run()
77
+ watcher()
75
78
  return () => {
76
79
  controller?.abort()
77
- run.cleanup()
80
+ watcher.cleanup()
78
81
  }
79
82
  }
80
83
 
81
84
  /* === Exports === */
82
85
 
83
- export { type MaybeCleanup, type EffectCallback, effect }
86
+ export { type MaybeCleanup, type EffectCallback, createEffect }
package/src/errors.ts CHANGED
@@ -5,6 +5,13 @@ class CircularDependencyError extends Error {
5
5
  }
6
6
  }
7
7
 
8
+ class InvalidCallbackError extends TypeError {
9
+ constructor(where: string, value: string) {
10
+ super(`Invalid ${where} callback ${value}`)
11
+ this.name = 'InvalidCallbackError'
12
+ }
13
+ }
14
+
8
15
  class InvalidSignalValueError extends TypeError {
9
16
  constructor(where: string, value: string) {
10
17
  super(`Invalid signal value ${value} in ${where}`)
@@ -48,6 +55,7 @@ class StoreKeyReadonlyError extends Error {
48
55
 
49
56
  export {
50
57
  CircularDependencyError,
58
+ InvalidCallbackError,
51
59
  InvalidSignalValueError,
52
60
  NullishSignalValueError,
53
61
  StoreKeyExistsError,
package/src/signal.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  type Computed,
3
3
  type ComputedCallback,
4
- computed,
4
+ createComputed,
5
5
  isComputed,
6
6
  isComputedCallback,
7
7
  } from './computed'
8
- import { isState, type State, state } from './state'
9
- import { isStore, type Store, store } from './store'
8
+ import { createState, isState, type State } from './state'
9
+ import { createStore, isStore, type Store } from './store'
10
10
  import { isRecord } from './util'
11
11
 
12
12
  /* === Types === */
@@ -71,9 +71,9 @@ function toSignal<T extends {}>(
71
71
  : State<T>
72
72
  function toSignal<T extends {}>(value: T) {
73
73
  if (isSignal<T>(value)) return value
74
- if (isComputedCallback(value)) return computed(value)
75
- if (Array.isArray(value) || isRecord(value)) return store(value)
76
- return state(value)
74
+ if (isComputedCallback(value)) return createComputed(value)
75
+ if (Array.isArray(value) || isRecord(value)) return createStore(value)
76
+ return createState(value)
77
77
  }
78
78
 
79
79
  /* === Exports === */