@zeix/cause-effect 0.17.1 → 0.17.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/.ai-context.md +13 -0
- package/.github/copilot-instructions.md +4 -0
- package/.zed/settings.json +3 -0
- package/CLAUDE.md +41 -7
- package/README.md +48 -25
- package/archive/benchmark.ts +0 -5
- package/archive/collection.ts +6 -65
- package/archive/composite.ts +85 -0
- package/archive/computed.ts +18 -20
- package/archive/list.ts +7 -75
- package/archive/memo.ts +15 -15
- package/archive/state.ts +2 -1
- package/archive/store.ts +8 -78
- package/archive/task.ts +20 -25
- package/index.dev.js +508 -526
- package/index.js +1 -1
- package/index.ts +9 -11
- package/package.json +6 -6
- package/src/classes/collection.ts +70 -107
- package/src/classes/computed.ts +165 -149
- package/src/classes/list.ts +145 -107
- package/src/classes/ref.ts +19 -17
- package/src/classes/state.ts +21 -17
- package/src/classes/store.ts +125 -73
- package/src/diff.ts +2 -1
- package/src/effect.ts +17 -10
- package/src/errors.ts +14 -1
- package/src/resolve.ts +1 -1
- package/src/signal.ts +3 -2
- package/src/system.ts +159 -61
- package/src/util.ts +0 -6
- package/test/batch.test.ts +4 -11
- package/test/benchmark.test.ts +4 -2
- package/test/collection.test.ts +106 -107
- package/test/computed.test.ts +351 -112
- package/test/effect.test.ts +2 -2
- package/test/list.test.ts +62 -102
- package/test/ref.test.ts +128 -2
- package/test/state.test.ts +16 -22
- package/test/store.test.ts +101 -108
- package/test/util/dependency-graph.ts +2 -2
- package/tsconfig.build.json +11 -0
- package/tsconfig.json +5 -7
- package/types/index.d.ts +3 -3
- package/types/src/classes/collection.d.ts +9 -10
- package/types/src/classes/computed.d.ts +17 -20
- package/types/src/classes/list.d.ts +8 -6
- package/types/src/classes/ref.d.ts +8 -12
- package/types/src/classes/state.d.ts +5 -8
- package/types/src/classes/store.d.ts +14 -13
- package/types/src/effect.d.ts +1 -2
- package/types/src/errors.d.ts +2 -1
- package/types/src/signal.d.ts +3 -2
- package/types/src/system.d.ts +47 -34
- package/types/src/util.d.ts +1 -2
- package/src/classes/composite.ts +0 -176
- package/types/src/classes/composite.d.ts +0 -15
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var B=Symbol(),o=($)=>typeof $==="string",s=($)=>typeof $==="number",E=($)=>typeof $==="symbol",M=($)=>typeof $==="function",j=($)=>M($)&&$.constructor.name==="AsyncFunction",P$=($)=>M($)&&$.constructor.name!=="AsyncFunction",J$=($)=>$!=null&&typeof $==="object",K=($,G)=>Object.prototype.toString.call($)===`[object ${G}]`,D=($)=>K($,"Object"),c=($)=>D($)||Array.isArray($),z$=($,G=(J)=>J!=null)=>Array.isArray($)&&$.every(G);var S=($)=>$ instanceof DOMException&&$.name==="AbortError",T=($)=>o($)?`"${$}"`:!!$&&typeof $==="object"?JSON.stringify($):String($);var L=($,G,J)=>{if(Object.is($,G))return!0;if(typeof $!==typeof G)return!1;if(!J$($)||!J$(G))return!1;if(!J)J=new WeakSet;if(J.has($)||J.has(G))throw new U("isEqual");J.add($),J.add(G);try{if(Array.isArray($)&&Array.isArray(G)){if($.length!==G.length)return!1;for(let z=0;z<$.length;z++)if(!L($[z],G[z],J))return!1;return!0}if(Array.isArray($)!==Array.isArray(G))return!1;if(D($)&&D(G)){let z=Object.keys($),X=Object.keys(G);if(z.length!==X.length)return!1;for(let Z of z){if(!(Z in G))return!1;if(!L($[Z],G[Z],J))return!1}return!0}return!1}finally{J.delete($),J.delete(G)}},w=($,G)=>{let J=c($),z=c(G);if(!J||!z){let H=!Object.is($,G);return{changed:H,add:H&&z?G:{},change:{},remove:H&&J?$:{}}}let X=new WeakSet,Z={},Q={},I={},f=Object.keys($),u=Object.keys(G),_=new Set([...f,...u]);for(let H of _){let W=H in $,m=H in G;if(!W&&m){Z[H]=G[H];continue}else if(W&&!m){I[H]=B;continue}let N$=$[H],Y$=G[H];if(!L(N$,Y$,X))Q[H]=Y$}return{add:Z,change:Q,remove:I,changed:!!(Object.keys(Z).length||Object.keys(Q).length||Object.keys(I).length)}};var O,g=new Set,i=0,Y=($)=>{let G=new Set,J=$;return J.onCleanup=(z)=>{G.add(z)},J.stop=()=>{for(let z of G)z();G.clear()},J},q=($)=>{if(O&&!$.has(O)){let G=O;G.onCleanup(()=>$.delete(G)),$.add(G)}},x=($)=>{for(let G of $)if(i)g.add(G);else G()},p=()=>{while(g.size){let $=Array.from(g);g.clear();for(let G of $)G()}},X$=($)=>{i++;try{$()}finally{p(),i--}},P=($,G)=>{let J=O;O=$||void 0;try{G()}finally{O=J}},A=($,G)=>{for(let J of $)if(i)g.add(()=>J(G));else J(G)};var t="Computed";class b{#G=new Set;#J;#z;#$;#X=!0;#Q=!1;#Z;constructor($,G=B){N("memo",$,l),F("memo",G),this.#J=$,this.#z=G,this.#Z=Y(()=>{if(this.#X=!0,this.#G.size)x(this.#G);else this.#Z.stop()})}get[Symbol.toStringTag](){return t}get(){if(q(this.#G),p(),this.#X)P(this.#Z,()=>{if(this.#Q)throw new U("memo");let $;this.#Q=!0;try{$=this.#J(this.#z)}catch(G){this.#z=B,this.#$=R(G),this.#Q=!1;return}if($==null||B===$)this.#z=B,this.#$=void 0;else this.#z=$,this.#$=void 0,this.#X=!1;this.#Q=!1});if(this.#$)throw this.#$;return this.#z}}class y{#G=new Set;#J;#z;#$;#X=!0;#Q=!1;#Z=!1;#x;#B;constructor($,G=B){N("task",$,r),F("task",G),this.#J=$,this.#z=G,this.#x=Y(()=>{if(this.#X=!0,this.#B?.abort(),this.#G.size)x(this.#G);else this.#x.stop()}),this.#x.onCleanup(()=>{this.#B?.abort()})}get[Symbol.toStringTag](){return t}get(){q(this.#G),p();let $=(Z)=>{if(!L(Z,this.#z))this.#z=Z,this.#Z=!0;this.#$=void 0,this.#X=!1},G=()=>{this.#Z=B!==this.#z,this.#z=B,this.#$=void 0},J=(Z)=>{let Q=R(Z);this.#Z=!this.#$||Q.name!==this.#$.name||Q.message!==this.#$.message,this.#z=B,this.#$=Q},z=(Z)=>(Q)=>{if(this.#Q=!1,this.#B=void 0,Z(Q),this.#Z)x(this.#G)},X=()=>P(this.#x,()=>{if(this.#Q)throw new U("task");if(this.#Z=!1,this.#B)return this.#z;this.#B=new AbortController,this.#B.signal.addEventListener("abort",()=>{this.#Q=!1,this.#B=void 0,X()},{once:!0});let Z;this.#Q=!0;try{Z=this.#J(this.#z,this.#B.signal)}catch(Q){if(S(Q))G();else J(Q);this.#Q=!1;return}if(Z instanceof Promise)Z.then(z($),z(J));else if(Z==null||B===Z)G();else $(Z);this.#Q=!1});if(this.#X)X();if(this.#$)throw this.#$;return this.#z}}var Z$=($,G=B)=>j($)?new y($,G):new b($,G),Q$=($)=>K($,t),l=($)=>P$($)&&$.length<2,r=($)=>j($)&&$.length<3;class k{signals=new Map;#G;#J;#z=new Map;#$={add:new Set,change:new Set,remove:new Set};#X=!1;constructor($,G,J){this.#G=G,this.#J=J,this.change({add:$,change:{},remove:{},changed:!0},!0)}#Q($){let G=Y(()=>{P(G,()=>{if(this.signals.get($)?.get(),!this.#X)A(this.#$.change,[$])})});this.#z.set($,G),G()}add($,G){if(!this.#G($,G))return!1;if(this.signals.set($,this.#J(G)),this.#$.change.size)this.#Q($);if(!this.#X)A(this.#$.add,[$]);return!0}remove($){if(!this.signals.delete($))return!1;let J=this.#z.get($);if(J)J.stop(),this.#z.delete($);if(!this.#X)A(this.#$.remove,[$]);return!0}change($,G){if(this.#X=!0,Object.keys($.add).length){for(let z in $.add)this.add(z,$.add[z]);let J=()=>A(this.#$.add,Object.keys($.add));if(G)setTimeout(J,0);else J()}if(Object.keys($.change).length)X$(()=>{for(let J in $.change){let z=$.change[J];if(!this.#G(J,z))continue;let X=this.signals.get(J);if(B$(`list item "${J}"`,z,X))X.set(z)}}),A(this.#$.change,Object.keys($.change));if(Object.keys($.remove).length){for(let J in $.remove)this.remove(J);A(this.#$.remove,Object.keys($.remove))}return this.#X=!1,$.changed}clear(){let $=Array.from(this.signals.keys());return this.signals.clear(),this.#z.clear(),A(this.#$.remove,$),!0}on($,G){if(this.#$[$].add(G),$==="change"&&!this.#z.size){this.#X=!0;for(let J of this.signals.keys())this.#Q(J);this.#X=!1}return()=>{if(this.#$[$].delete(G),$==="change"&&!this.#$.change.size){if(this.#z.size){for(let J of this.#z.values())J.stop();this.#z.clear()}}}}}var x$="State";class C{#G=new Set;#J;constructor($){F("state",$),this.#J=$}get[Symbol.toStringTag](){return x$}get(){return q(this.#G),this.#J}set($){if(F("state",$),L(this.#J,$))return;if(this.#J=$,x(this.#G),B===this.#J)this.#G.clear()}update($){N("state update",$),this.set($(this.#J))}}var a=($)=>K($,x$);var H$="List";class h{#G;#J=new Set;#z={sort:new Set};#$=[];#X;constructor($,G){F("list",$,Array.isArray);let J=0;this.#X=o(G)?()=>`${G}${J++}`:M(G)?(z)=>G(z):()=>String(J++),this.#G=new k(this.#Q($),(z,X)=>{return F(`list for key "${z}"`,X),!0},(z)=>new C(z))}#Q($){let G={};for(let J=0;J<$.length;J++){let z=$[J];if(z===void 0)continue;let X=this.#$[J];if(!X)X=this.#X(z),this.#$[J]=X;G[X]=z}return G}get#Z(){return this.#$.map(($)=>this.#G.signals.get($)?.get()).filter(($)=>$!==void 0)}get[Symbol.toStringTag](){return H$}get[Symbol.isConcatSpreadable](){return!0}*[Symbol.iterator](){for(let $ of this.#$){let G=this.#G.signals.get($);if(G)yield G}}get length(){return q(this.#J),this.#$.length}get(){return q(this.#J),this.#Z}set($){if(B===$){this.#G.clear(),x(this.#J),this.#J.clear();return}let G=this.#Z,J=w(this.#Q(G),this.#Q($)),z=Object.keys(J.remove);if(this.#G.change(J)){for(let Z of z){let Q=this.#$.indexOf(Z);if(Q!==-1)this.#$.splice(Q,1)}this.#$=this.#$.filter(()=>!0),x(this.#J)}}update($){this.set($(this.get()))}at($){return this.#G.signals.get(this.#$[$])}keys(){return this.#$.values()}byKey($){return this.#G.signals.get($)}keyAt($){return this.#$[$]}indexOfKey($){return this.#$.indexOf($)}add($){let G=this.#X($);if(this.#G.signals.has(G))throw new V("store",G,$);if(!this.#$.includes(G))this.#$.push(G);if(this.#G.add(G,$))x(this.#J);return G}remove($){let G=s($)?this.#$[$]:$;if(this.#G.remove(G)){let z=s($)?$:this.#$.indexOf(G);if(z>=0)this.#$.splice(z,1);this.#$=this.#$.filter(()=>!0),x(this.#J)}}sort($){let J=this.#$.map((z)=>[z,this.#G.signals.get(z)?.get()]).sort(M($)?(z,X)=>$(z[1],X[1]):(z,X)=>String(z[1]).localeCompare(String(X[1]))).map(([z])=>z);if(!L(this.#$,J))this.#$=J,x(this.#J),A(this.#z.sort,this.#$)}splice($,G,...J){let z=this.#$.length,X=$<0?Math.max(0,z+$):Math.min($,z),Z=Math.max(0,Math.min(G??Math.max(0,z-Math.max(0,X)),z-X)),Q={},I={};for(let _=0;_<Z;_++){let H=X+_,W=this.#$[H];if(W){let m=this.#G.signals.get(W);if(m)I[W]=m.get()}}let f=this.#$.slice(0,X);for(let _ of J){let H=this.#X(_);f.push(H),Q[H]=_}f.push(...this.#$.slice(X+Z));let u=!!(Object.keys(Q).length||Object.keys(I).length);if(u)this.#G.change({add:Q,change:{},remove:I,changed:u}),this.#$=f.filter(()=>!0),x(this.#J);return Object.values(I)}on($,G){if($==="sort")return this.#z.sort.add(G),()=>{this.#z.sort.delete(G)};return this.#G.on($,G)}deriveCollection($){return new d(this,$)}}var v=($)=>K($,H$);var M$="Store";class q${#G;#J=new Set;constructor($){F("store",$,D),this.#G=new k($,(G,J)=>{return F(`store for key "${G}"`,J),!0},(G)=>U$(G))}get#z(){let $={};for(let[G,J]of this.#G.signals.entries())$[G]=J.get();return $}get[Symbol.toStringTag](){return M$}get[Symbol.isConcatSpreadable](){return!1}*[Symbol.iterator](){for(let[$,G]of this.#G.signals.entries())yield[$,G]}get(){return q(this.#J),this.#z}set($){if(B===$){this.#G.clear(),x(this.#J),this.#J.clear();return}let G=this.#z;if(this.#G.change(w(G,$)))x(this.#J)}keys(){return this.#G.signals.keys()}byKey($){return this.#G.signals.get($)}update($){this.set($(this.get()))}add($,G){if(this.#G.signals.has($))throw new V("store",$,G);if(this.#G.add($,G))x(this.#J);return $}remove($){if(this.#G.remove($))x(this.#J)}on($,G){return this.#G.on($,G)}}var e=($)=>{let G=new q$($);return new Proxy(G,{get(J,z){if(z in J){let X=Reflect.get(J,z);return M(X)?X.bind(J):X}if(!E(z))return J.byKey(z)},has(J,z){if(z in J)return!0;return J.byKey(String(z))!==void 0},ownKeys(J){return Array.from(J.keys())},getOwnPropertyDescriptor(J,z){if(z in J)return Reflect.getOwnPropertyDescriptor(J,z);if(E(z))return;let X=J.byKey(String(z));return X?{enumerable:!0,configurable:!0,writable:!0,value:X}:void 0}})},$$=($)=>K($,M$);var T$=($)=>a($)||Q$($)||$$($),A$=($)=>a($)||$$($)||v($);function C$($){if(l($))return new b($);if(r($))return new y($);if(z$($))return new h($);if(D($))return e($);return new C($)}function U$($){if(z$($))return new h($);if(D($))return e($);return new C($)}class U extends Error{constructor($){super(`Circular dependency detected in ${$}`);this.name="CircularDependencyError"}}class V extends Error{constructor($,G,J){super(`Could not add ${$} key "${G}"${J?` with value ${T(J)}`:""} because it already exists`);this.name="DuplicateKeyError"}}class n extends TypeError{constructor($,G){super(`Invalid ${$} callback ${T(G)}`);this.name="InvalidCallbackError"}}class G$ extends TypeError{constructor($,G){super(`Invalid ${$} source ${T(G)}`);this.name="InvalidCollectionSourceError"}}class F$ extends TypeError{constructor($,G){super(`Invalid signal value ${T(G)} in ${$}`);this.name="InvalidSignalValueError"}}class I$ extends TypeError{constructor($){super(`Nullish signal values are not allowed in ${$}`);this.name="NullishSignalValueError"}}class K$ extends Error{constructor($,G){super(`Could not set ${$} to ${T(G)} because signal is read-only`);this.name="ReadonlySignalError"}}var R=($)=>$ instanceof Error?$:Error(String($)),N=($,G,J=M)=>{if(!J(G))throw new n($,G)},F=($,G,J=()=>!(E(G)&&G!==B)||M(G))=>{if(G==null)throw new I$($);if(!J(G))throw new F$($,G)},B$=($,G,J)=>{if(!A$(J))throw new K$($,G);return!0};var D$="Collection";class d{#G=new Set;#J;#z;#$=new Map;#X=new Map;#Q={add:new Set,change:new Set,remove:new Set,sort:new Set};#Z=[];constructor($,G){if(N("collection",G),M($))$=$();if(!W$($))throw new G$("derived collection",$);this.#J=$,this.#z=G;for(let J=0;J<this.#J.length;J++){let z=this.#J.keyAt(J);if(!z)continue;this.#x(z)}this.#J.on("add",(J)=>{for(let z of J)if(!this.#$.has(z)){this.#x(z);let X=this.#$.get(z);if(X&&_$(this.#z))X.get()}x(this.#G),A(this.#Q.add,J)}),this.#J.on("remove",(J)=>{for(let z of J){if(!this.#$.has(z))continue;this.#$.delete(z);let X=this.#Z.indexOf(z);if(X>=0)this.#Z.splice(X,1);let Z=this.#X.get(z);if(Z)Z.stop(),this.#X.delete(z)}this.#Z=this.#Z.filter(()=>!0),x(this.#G),A(this.#Q.remove,J)}),this.#J.on("sort",(J)=>{this.#Z=[...J],x(this.#G),A(this.#Q.sort,J)})}#x($){let G=_$(this.#z)?async(z,X)=>{let Z=this.#J.byKey($);if(!Z)return B;let Q=Z.get();if(Q===B)return B;return this.#z(Q,X)}:()=>{let z=this.#J.byKey($);if(!z)return B;let X=z.get();if(X===B)return B;return this.#z(X)},J=Z$(G);if(this.#$.set($,J),!this.#Z.includes($))this.#Z.push($);if(this.#Q.change.size)this.#B($);return!0}#B($){let G=Y(()=>{P(G,()=>{this.#$.get($)?.get()})});this.#X.set($,G),G()}get[Symbol.toStringTag](){return D$}get[Symbol.isConcatSpreadable](){return!0}*[Symbol.iterator](){for(let $ of this.#Z){let G=this.#$.get($);if(G)yield G}}get length(){return q(this.#G),this.#Z.length}get(){return q(this.#G),this.#Z.map(($)=>this.#$.get($)?.get()).filter(($)=>$!=null&&$!==B)}at($){return this.#$.get(this.#Z[$])}keys(){return this.#Z.values()}byKey($){return this.#$.get($)}keyAt($){return this.#Z[$]}indexOfKey($){return this.#Z.indexOf($)}on($,G){if(this.#Q[$].add(G),$==="change"&&!this.#X.size)for(let J of this.#$.keys())this.#B(J);return()=>{if(this.#Q[$].delete(G),$==="change"&&!this.#Q.change.size){if(this.#X.size){for(let J of this.#X.values())J.stop();this.#X.clear()}}}}deriveCollection($){return new d(this,$)}}var j$=($)=>K($,D$),W$=($)=>v($)||j$($),_$=($)=>j($);var L$="Ref";class R${#G=new Set;#J;constructor($,G){F("ref",$,G),this.#J=$}get[Symbol.toStringTag](){return L$}get(){return q(this.#G),this.#J}notify(){x(this.#G)}}var E$=($)=>K($,L$);var S$=($)=>{if(!M($)||$.length>1)throw new n("effect",$);let G=j($),J=!1,z,X=Y(()=>P(X,()=>{if(J)throw new U("effect");J=!0,z?.abort(),z=void 0;let Z;try{if(G){z=new AbortController;let Q=z;$(z.signal).then((I)=>{if(M(I)&&z===Q)X.onCleanup(I)}).catch((I)=>{if(!S(I))console.error("Async effect error:",I)})}else if(Z=$(),M(Z))X.onCleanup(Z)}catch(Q){if(!S(Q))console.error("Effect callback error:",Q)}J=!1}));return X(),()=>{z?.abort(),X.stop()}};function O$($,G){try{if($.pending)G.nil?.();else if($.errors)G.err?.($.errors);else if($.ok)G.ok($.values)}catch(J){let z=R(J);if(G.err&&(!$.errors||!$.errors.includes(z)))G.err($.errors?[...$.errors,z]:[z]);else throw z}}function V$($){let G=[],J=!1,z={};for(let[X,Z]of Object.entries($))try{let Q=Z.get();if(Q===B)J=!0;else z[X]=Q}catch(Q){G.push(R(Q))}if(J)return{ok:!1,pending:!0};if(G.length>0)return{ok:!1,errors:G};return{ok:!0,values:z}}export{T as valueString,F as validateSignalValue,N as validateCallback,P as trackSignalReads,q as subscribeActiveWatcher,V$ as resolve,x as notifyWatchers,O$ as match,r as isTaskCallback,E as isSymbol,o as isString,$$ as isStore,a as isState,T$ as isSignal,E$ as isRef,c as isRecordOrArray,D as isRecord,K as isObjectOfType,s as isNumber,A$ as isMutableSignal,l as isMemoCallback,v as isList,M as isFunction,L as isEqual,Q$ as isComputed,j$ as isCollection,j as isAsyncFunction,S as isAbortError,B$ as guardMutableSignal,p as flushPendingReactions,A as emitNotification,w as diff,Y as createWatcher,e as createStore,C$ as createSignal,R as createError,S$ as createEffect,Z$ as createComputed,X$ as batchSignalWrites,B as UNSET,y as Task,M$ as TYPE_STORE,x$ as TYPE_STATE,L$ as TYPE_REF,H$ as TYPE_LIST,t as TYPE_COMPUTED,D$ as TYPE_COLLECTION,C as State,R$ as Ref,K$ as ReadonlySignalError,I$ as NullishSignalValueError,b as Memo,h as List,F$ as InvalidSignalValueError,G$ as InvalidCollectionSourceError,n as InvalidCallbackError,V as DuplicateKeyError,d as DerivedCollection,U as CircularDependencyError,q$ as BaseStore};
|
|
1
|
+
var M,V=new WeakMap,U$=new WeakMap,Y$=new WeakMap,s=new Set,B$=0,Z=Symbol(),Y=($,G)=>{let J=new Set,z=$;return z.run=()=>{let Q=M;M=z;try{G()}finally{M=Q}},z.onCleanup=(Q)=>{J.add(Q)},z.stop=()=>{try{for(let Q of J)Q()}finally{J.clear()}},z},q$=($)=>{let G=M;M=void 0;try{$()}finally{M=G}},K=($,G,J)=>{if(U$.set($,G),J)Y$.set($,J)},q=($)=>{if(!M||V.get($)?.has(M))return!1;let G=M;if(!V.has($))V.set($,new Set);let J=V.get($);if(j$(J),!J.size){let z=U$.get($);if(z)q$(z)}return J.add(G),G.onCleanup(()=>{if(J.delete(G),!J.size){let z=Y$.get($);if(z)q$(z)}}),!0};var C=($)=>{let G=V.get($);if(!G)return;for(let J of G)J.stop();G.clear()},x=($)=>{let G=V.get($);if(!G?.size)return!1;for(let J of G)if(B$)s.add(J);else J();return!0};var y=()=>{while(s.size){let $=Array.from(s);s.clear();for(let G of $)G()}},d=($)=>{B$++;try{$()}finally{y(),B$--}},C$=($,G)=>{let J=M;M=$||void 0;try{G()}finally{M=J}};var l=($)=>typeof $==="string",a=($)=>typeof $==="number",E=($)=>typeof $==="symbol",H=($)=>typeof $==="function",j=($)=>H($)&&$.constructor.name==="AsyncFunction",P$=($)=>H($)&&$.constructor.name!=="AsyncFunction",A$=($)=>$!=null&&typeof $==="object",I=($,G)=>Object.prototype.toString.call($)===`[object ${G}]`,L=($)=>I($,"Object"),e=($)=>L($)||Array.isArray($),H$=($,G=(J)=>J!=null)=>Array.isArray($)&&$.every(G);var T=($)=>$ instanceof DOMException&&$.name==="AbortError",_=($)=>l($)?`"${$}"`:!!$&&typeof $==="object"?JSON.stringify($):String($);var N=($,G,J)=>{if(Object.is($,G))return!0;if(typeof $!==typeof G)return!1;if(!A$($)||!A$(G))return!1;if(!J)J=new WeakSet;if(J.has($)||J.has(G))throw new R("isEqual");J.add($),J.add(G);try{if(Array.isArray($)&&Array.isArray(G)){if($.length!==G.length)return!1;for(let z=0;z<$.length;z++)if(!N($[z],G[z],J))return!1;return!0}if(Array.isArray($)!==Array.isArray(G))return!1;if(L($)&&L(G)){let z=Object.keys($),Q=Object.keys(G);if(z.length!==Q.length)return!1;for(let X of z){if(!(X in G))return!1;if(!N($[X],G[X],J))return!1}return!0}return!1}finally{J.delete($),J.delete(G)}},k=($,G)=>{let J=e($),z=e(G);if(!J||!z){let A=!Object.is($,G);return{changed:A,add:A&&z?G:{},change:{},remove:A&&J?$:{}}}let Q=new WeakSet,X={},B={},F={},g=Object.keys($),t=Object.keys(G),U=new Set([...g,...t]);for(let A of U){let S=A in $,b=A in G;if(!S&&b){X[A]=G[A];continue}else if(S&&!b){F[A]=Z;continue}let V$=$[A],R$=G[A];if(!N(V$,R$,Q))B[A]=R$}return{add:X,change:B,remove:F,changed:!!(Object.keys(X).length||Object.keys(B).length||Object.keys(F).length)}};var $$="Computed";class v{#G;#$;#J;#z=!0;#Q=!1;#X;constructor($,G){m(this.constructor.name,$,G$);let J=G?.initialValue??Z;if(D(this.constructor.name,J,G?.guard),this.#G=$,this.#$=J,G?.watched)K(this,G.watched,G.unwatched)}#Z(){return this.#X||=Y(()=>{if(this.#z=!0,!x(this))this.#X?.stop()},()=>{if(this.#Q)throw new R("memo");let $;this.#Q=!0;try{$=this.#G(this.#$)}catch(G){this.#$=Z,this.#J=P(G),this.#Q=!1;return}if($==null||Z===$)this.#$=Z,this.#J=void 0;else this.#$=$,this.#J=void 0,this.#z=!1;this.#Q=!1}),this.#X.onCleanup(()=>{this.#X=void 0}),this.#X}get[Symbol.toStringTag](){return $$}get(){if(q(this),y(),this.#z)this.#Z().run();if(this.#J)throw this.#J;return this.#$}}class h{#G;#$;#J;#z=!0;#Q=!1;#X=!1;#Z;#x;constructor($,G){m(this.constructor.name,$,J$);let J=G?.initialValue??Z;if(D(this.constructor.name,J,G?.guard),this.#G=$,this.#$=J,G?.watched)K(this,G.watched,G.unwatched)}#B(){if(!this.#Z){let $=(Q)=>{if(!N(Q,this.#$))this.#$=Q,this.#X=!0;this.#J=void 0,this.#z=!1},G=()=>{this.#X=Z!==this.#$,this.#$=Z,this.#J=void 0},J=(Q)=>{let X=P(Q);this.#X=!this.#J||X.name!==this.#J.name||X.message!==this.#J.message,this.#$=Z,this.#J=X},z=(Q)=>(X)=>{if(this.#Q=!1,this.#x=void 0,Q(X),this.#X&&!x(this))this.#Z?.stop()};this.#Z=Y(()=>{if(this.#z=!0,this.#x?.abort(),!x(this))this.#Z?.stop()},()=>{if(this.#Q)throw new R("task");if(this.#X=!1,this.#x)return this.#$;this.#x=new AbortController,this.#x.signal.addEventListener("abort",()=>{this.#Q=!1,this.#x=void 0,this.#B().run()},{once:!0});let Q;this.#Q=!0;try{Q=this.#G(this.#$,this.#x.signal)}catch(X){if(T(X))G();else J(X);this.#Q=!1;return}if(Q instanceof Promise)Q.then(z($),z(J));else if(Q==null||Z===Q)G();else $(Q);this.#Q=!1}),this.#Z.onCleanup(()=>{this.#x?.abort(),this.#x=void 0,this.#Z=void 0})}return this.#Z}get[Symbol.toStringTag](){return $$}get(){if(q(this),y(),this.#z)this.#B().run();if(this.#J)throw this.#J;return this.#$}}var D$=($,G)=>j($)?new h($,G):new v($,G),F$=($)=>I($,$$),G$=($)=>P$($)&&$.length<2,J$=($)=>j($)&&$.length<3;var f="State";class W{#G;constructor($,G){if(D(f,$,G?.guard),this.#G=$,G?.watched)K(this,G.watched,G.unwatched)}get[Symbol.toStringTag](){return f}get(){return q(this),this.#G}set($){if(D(f,$),N(this.#G,$))return;if(this.#G=$,x(this),Z===this.#G)C(this)}update($){m(`${f} update`,$),this.set($(this.#G))}}var z$=($)=>I($,f);var O="List";class o{#G=new Map;#$=[];#J;#z;constructor($,G){D(O,$,Array.isArray);let J=0,z=G?.keyConfig;if(this.#J=l(z)?()=>`${z}${J++}`:H(z)?(Q)=>z(Q):()=>String(J++),this.#z=(Q,X)=>{return D(`${O} item for key "${Q}"`,X,G?.guard),!0},this.#Z({add:this.#Q($),change:{},remove:{},changed:!0}),G?.watched)K(this,G.watched,G.unwatched)}#Q($){let G={};for(let J=0;J<$.length;J++){let z=$[J];if(z===void 0)continue;let Q=this.#$[J];if(!Q)Q=this.#J(z),this.#$[J]=Q;G[Q]=z}return G}#X($,G){if(!this.#z($,G))return!1;return this.#G.set($,new W(G)),!0}#Z($){if(Object.keys($.add).length)for(let G in $.add)this.#X(G,$.add[G]);if(Object.keys($.change).length)d(()=>{for(let G in $.change){let J=$.change[G];if(!this.#z(G,J))continue;let z=this.#G.get(G);if(u(`${O} item "${G}"`,J,z))z.set(J)}});if(Object.keys($.remove).length){for(let G in $.remove){this.#G.delete(G);let J=this.#$.indexOf(G);if(J!==-1)this.#$.splice(J,1)}this.#$=this.#$.filter(()=>!0)}return $.changed}get#x(){return this.#$.map(($)=>this.#G.get($)?.get()).filter(($)=>$!==void 0)}get[Symbol.toStringTag](){return O}get[Symbol.isConcatSpreadable](){return!0}*[Symbol.iterator](){for(let $ of this.#$){let G=this.#G.get($);if(G)yield G}}get length(){return q(this),this.#$.length}get(){return q(this),this.#x}set($){if(Z===$){this.#G.clear(),x(this),C(this);return}let G=k(this.#Q(this.#x),this.#Q($));if(this.#Z(G))x(this)}update($){this.set($(this.get()))}at($){return this.#G.get(this.#$[$])}keys(){return q(this),this.#$.values()}byKey($){return this.#G.get($)}keyAt($){return this.#$[$]}indexOfKey($){return this.#$.indexOf($)}add($){let G=this.#J($);if(this.#G.has(G))throw new w("store",G,$);if(!this.#$.includes(G))this.#$.push(G);if(this.#X(G,$))x(this);return G}remove($){let G=a($)?this.#$[$]:$;if(this.#G.delete(G)){let z=a($)?$:this.#$.indexOf(G);if(z>=0)this.#$.splice(z,1);this.#$=this.#$.filter(()=>!0),x(this)}}sort($){let J=this.#$.map((z)=>[z,this.#G.get(z)?.get()]).sort(H($)?(z,Q)=>$(z[1],Q[1]):(z,Q)=>String(z[1]).localeCompare(String(Q[1]))).map(([z])=>z);if(!N(this.#$,J))this.#$=J,x(this)}splice($,G,...J){let z=this.#$.length,Q=$<0?Math.max(0,z+$):Math.min($,z),X=Math.max(0,Math.min(G??Math.max(0,z-Math.max(0,Q)),z-Q)),B={},F={};for(let U=0;U<X;U++){let A=Q+U,S=this.#$[A];if(S){let b=this.#G.get(S);if(b)F[S]=b.get()}}let g=this.#$.slice(0,Q);for(let U of J){let A=this.#J(U);g.push(A),B[A]=U}g.push(...this.#$.slice(Q+X));let t=!!(Object.keys(B).length||Object.keys(F).length);if(t)this.#Z({add:B,change:{},remove:F,changed:t}),this.#$=g.filter(()=>!0),x(this);return Object.values(F)}deriveCollection($,G){return new i(this,$,G)}}var n=($)=>I($,O);var p="Store";class I${#G=new Map;constructor($,G){if(D(p,$,G?.guard??L),this.#Q({add:$,change:{},remove:{},changed:!0}),G?.watched)K(this,G.watched,G.unwatched)}get#$(){let $={};for(let[G,J]of this.#G.entries())$[G]=J.get();return $}#J($,G){return D(`${p} for key "${$}"`,G),!0}#z($,G){if(!this.#J($,G))return!1;return this.#G.set($,m$(G)),!0}#Q($){if(Object.keys($.add).length)for(let G in $.add)this.#z(G,$.add[G]);if(Object.keys($.change).length)d(()=>{for(let G in $.change){let J=$.change[G];if(!this.#J(G,J))continue;let z=this.#G.get(G);if(u(`list item "${G}"`,J,z))z.set(J)}});if(Object.keys($.remove).length)for(let G in $.remove)this.remove(G);return $.changed}get[Symbol.toStringTag](){return p}get[Symbol.isConcatSpreadable](){return!1}*[Symbol.iterator](){for(let[$,G]of this.#G.entries())yield[$,G]}keys(){return q(this),this.#G.keys()}byKey($){return this.#G.get($)}get(){return q(this),this.#$}set($){if(Z===$){this.#G.clear(),x(this),C(this);return}if(this.#Q(k(this.#$,$)))x(this)}update($){this.set($(this.get()))}add($,G){if(this.#G.has($))throw new w(p,$,G);if(this.#z($,G))x(this);return $}remove($){if(this.#G.delete($))x(this)}}var Q$=($,G)=>{let J=new I$($,G);return new Proxy(J,{get(z,Q){if(Q in z){let X=Reflect.get(z,Q);return H(X)?X.bind(z):X}if(!E(Q))return z.byKey(Q)},has(z,Q){if(Q in z)return!0;return z.byKey(String(Q))!==void 0},ownKeys(z){return Array.from(z.keys())},getOwnPropertyDescriptor(z,Q){if(Q in z)return Reflect.getOwnPropertyDescriptor(z,Q);if(E(Q))return;let X=z.byKey(String(Q));return X?{enumerable:!0,configurable:!0,writable:!0,value:X}:void 0}})},X$=($)=>I($,p);var E$=($)=>z$($)||F$($)||X$($),K$=($)=>z$($)||X$($)||n($);function T$($){if(G$($))return new v($);if(J$($))return new h($);if(H$($))return new o($);if(L($))return Q$($);return new W($)}function m$($){if(H$($))return new o($);if(L($))return Q$($);return new W($)}class R extends Error{constructor($){super(`Circular dependency detected in ${$}`);this.name="CircularDependencyError"}}class w extends Error{constructor($,G,J){super(`Could not add ${$} key "${G}"${J?` with value ${_(J)}`:""} because it already exists`);this.name="DuplicateKeyError"}}class _$ extends Error{constructor($="unexpected condition"){super(`Assertion failed: ${$}`);this.name="FailedAssertionError"}}class c extends TypeError{constructor($,G){super(`Invalid ${$} callback ${_(G)}`);this.name="InvalidCallbackError"}}class Z$ extends TypeError{constructor($,G){super(`Invalid ${$} source ${_(G)}`);this.name="InvalidCollectionSourceError"}}class M$ extends TypeError{constructor($,G){super(`Invalid signal value ${_(G)} in ${$}`);this.name="InvalidSignalValueError"}}class L$ extends TypeError{constructor($){super(`Nullish signal values are not allowed in ${$}`);this.name="NullishSignalValueError"}}class N$ extends Error{constructor($,G){super(`Could not set ${$} to ${_(G)} because signal is read-only`);this.name="ReadonlySignalError"}}function j$($,G){if(!$)throw new _$(G)}var P=($)=>$ instanceof Error?$:Error(String($)),m=($,G,J=H)=>{if(!J(G))throw new c($,G)},D=($,G,J=()=>!(E(G)&&G!==Z)||H(G))=>{if(G==null)throw new L$($);if(!J(G))throw new M$($,G)},u=($,G,J)=>{if(!K$(J))throw new N$($,G);return!0};var r="Collection";class i{#G;#$;#J=new Map;#z=[];#Q=!0;#X;constructor($,G,J){if(m(r,G),H($))$=$();if(!f$($))throw new Z$(r,$);this.#G=$,this.#$=G;for(let z=0;z<this.#G.length;z++){let Q=this.#G.keyAt(z);if(!Q)continue;this.#x(Q)}if(J?.watched)K(this,J.watched,J.unwatched)}#Z(){return this.#X||=Y(()=>{if(this.#Q=!0,!x(this))this.#X?.stop()},()=>{let $=Array.from(this.#G.keys()),G=new Set([...this.#z,...$]),J=[],z=[];for(let Q of G){let X=this.#z.includes(Q),B=$.includes(Q);if(!X&&B)J.push(Q);else if(X&&!B)z.push(Q)}for(let Q of z)this.#J.delete(Q);for(let Q of J)this.#x(Q);this.#z=$,this.#Q=!1}),this.#X.onCleanup(()=>{this.#X=void 0}),this.#X}#x($){let G=O$(this.#$)?async(z,Q)=>{let X=this.#G.byKey($)?.get();if(X===Z)return Z;return this.#$(X,Q)}:()=>{let z=this.#G.byKey($)?.get();if(z===Z)return Z;return this.#$(z)},J=D$(G);if(this.#J.set($,J),!this.#z.includes($))this.#z.push($);return!0}get[Symbol.toStringTag](){return r}get[Symbol.isConcatSpreadable](){return!0}*[Symbol.iterator](){for(let $ of this.#z){let G=this.#J.get($);if(G)yield G}}keys(){if(q(this),this.#Q)this.#Z().run();return this.#z.values()}get(){if(q(this),this.#Q)this.#Z().run();return this.#z.map(($)=>this.#J.get($)?.get()).filter(($)=>$!=null&&$!==Z)}at($){return this.#J.get(this.#z[$])}byKey($){return this.#J.get($)}keyAt($){return this.#z[$]}indexOfKey($){return this.#z.indexOf($)}deriveCollection($,G){return new i(this,$,G)}get length(){if(q(this),this.#Q)this.#Z().run();return this.#z.length}}var W$=($)=>I($,r),f$=($)=>n($)||W$($),O$=($)=>j($);var x$="Ref";class S${#G;constructor($,G){if(D(x$,$,G?.guard),this.#G=$,G?.watched)K(this,G.watched,G.unwatched)}get[Symbol.toStringTag](){return x$}get(){return q(this),this.#G}notify(){x(this)}}var w$=($)=>I($,x$);var p$=($)=>{if(!H($)||$.length>1)throw new c("effect",$);let G=j($),J=!1,z,Q=Y(()=>{Q.run()},()=>{if(J)throw new R("effect");J=!0,z?.abort(),z=void 0;let X;try{if(G){z=new AbortController;let B=z;$(z.signal).then((F)=>{if(H(F)&&z===B)Q.onCleanup(F)}).catch((F)=>{if(!T(F))console.error("Error in async effect callback:",F)})}else if(X=$(),H(X))Q.onCleanup(X)}catch(B){if(!T(B))console.error("Error in effect callback:",B)}J=!1});return Q(),()=>{z?.abort();try{Q.stop()}catch(X){console.error("Error in effect cleanup:",X)}}};function g$($,G){try{if($.pending)G.nil?.();else if($.errors)G.err?.($.errors);else if($.ok)G.ok($.values)}catch(J){let z=P(J);if(G.err&&(!$.errors||!$.errors.includes(z)))G.err($.errors?[...$.errors,z]:[z]);else throw z}}function b$($){let G=[],J=!1,z={};for(let[Q,X]of Object.entries($))try{let B=X.get();if(B===Z)J=!0;else z[Q]=B}catch(B){G.push(P(B))}if(J)return{ok:!1,pending:!0};if(G.length>0)return{ok:!1,errors:G};return{ok:!0,values:z}}export{_ as valueString,D as validateSignalValue,m as validateCallback,q$ as untrack,C$ as track,q as subscribeTo,b$ as resolve,x as notifyOf,g$ as match,J$ as isTaskCallback,E as isSymbol,l as isString,X$ as isStore,z$ as isState,E$ as isSignal,w$ as isRef,e as isRecordOrArray,L as isRecord,I as isObjectOfType,a as isNumber,K$ as isMutableSignal,G$ as isMemoCallback,n as isList,H as isFunction,N as isEqual,F$ as isComputed,W$ as isCollection,j as isAsyncFunction,T as isAbortError,u as guardMutableSignal,y as flush,k as diff,Y as createWatcher,Q$ as createStore,T$ as createSignal,P as createError,p$ as createEffect,D$ as createComputed,d as batch,Z as UNSET,h as Task,p as TYPE_STORE,f as TYPE_STATE,x$ as TYPE_REF,O as TYPE_LIST,$$ as TYPE_COMPUTED,r as TYPE_COLLECTION,W as State,S$ as Ref,N$ as ReadonlySignalError,L$ as NullishSignalValueError,v as Memo,o as List,M$ as InvalidSignalValueError,Z$ as InvalidCollectionSourceError,c as InvalidCallbackError,w as DuplicateKeyError,i as DerivedCollection,R as CircularDependencyError,I$ as BaseStore};
|
package/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @name Cause & Effect
|
|
3
|
-
* @version 0.17.
|
|
3
|
+
* @version 0.17.3
|
|
4
4
|
* @author Esther Brunner
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -77,17 +77,16 @@ export {
|
|
|
77
77
|
type UnknownSignalRecord,
|
|
78
78
|
} from './src/signal'
|
|
79
79
|
export {
|
|
80
|
-
|
|
80
|
+
batch,
|
|
81
81
|
type Cleanup,
|
|
82
82
|
createWatcher,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
type
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
trackSignalReads,
|
|
83
|
+
flush,
|
|
84
|
+
notifyOf,
|
|
85
|
+
type SignalOptions,
|
|
86
|
+
subscribeTo,
|
|
87
|
+
track,
|
|
88
|
+
UNSET,
|
|
89
|
+
untrack,
|
|
91
90
|
type Watcher,
|
|
92
91
|
} from './src/system'
|
|
93
92
|
export {
|
|
@@ -100,6 +99,5 @@ export {
|
|
|
100
99
|
isRecordOrArray,
|
|
101
100
|
isString,
|
|
102
101
|
isSymbol,
|
|
103
|
-
UNSET,
|
|
104
102
|
valueString,
|
|
105
103
|
} from './src/util'
|
package/package.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeix/cause-effect",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.3",
|
|
4
4
|
"author": "Esther Brunner",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "index.js",
|
|
6
7
|
"module": "index.ts",
|
|
8
|
+
"types": "types/index.d.ts",
|
|
7
9
|
"devDependencies": {
|
|
8
10
|
"@biomejs/biome": "2.1.4",
|
|
9
11
|
"@types/bun": "latest",
|
|
@@ -12,7 +14,7 @@
|
|
|
12
14
|
"peerDependencies": {
|
|
13
15
|
"typescript": "^5.6.3"
|
|
14
16
|
},
|
|
15
|
-
"description": "Cause & Effect - reactive state management
|
|
17
|
+
"description": "Cause & Effect - fine-grained reactive state management library.",
|
|
16
18
|
"license": "MIT",
|
|
17
19
|
"keywords": [
|
|
18
20
|
"Cause & Effect",
|
|
@@ -24,10 +26,8 @@
|
|
|
24
26
|
"access": "public"
|
|
25
27
|
},
|
|
26
28
|
"scripts": {
|
|
27
|
-
"build": "bunx tsc && bun build index.ts --outdir ./ --minify && bun build index.ts --outfile index.dev.js",
|
|
29
|
+
"build": "bunx tsc --project tsconfig.build.json && bun build index.ts --outdir ./ --minify && bun build index.ts --outfile index.dev.js",
|
|
28
30
|
"test": "bun test",
|
|
29
31
|
"lint": "bunx biome lint --write"
|
|
30
|
-
}
|
|
31
|
-
"type": "module",
|
|
32
|
-
"types": "types/index.d.ts"
|
|
32
|
+
}
|
|
33
33
|
}
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { InvalidCollectionSourceError, validateCallback } from '../errors'
|
|
2
2
|
import type { Signal } from '../signal'
|
|
3
3
|
import {
|
|
4
|
-
type Cleanup,
|
|
5
4
|
createWatcher,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
trackSignalReads,
|
|
5
|
+
notifyOf,
|
|
6
|
+
registerWatchCallbacks,
|
|
7
|
+
type SignalOptions,
|
|
8
|
+
subscribeTo,
|
|
9
|
+
UNSET,
|
|
12
10
|
type Watcher,
|
|
13
11
|
} from '../system'
|
|
14
|
-
import { isAsyncFunction, isFunction, isObjectOfType
|
|
12
|
+
import { isAsyncFunction, isFunction, isObjectOfType } from '../util'
|
|
15
13
|
import { type Computed, createComputed } from './computed'
|
|
16
14
|
import { isList, type List } from './list'
|
|
17
15
|
|
|
@@ -27,12 +25,12 @@ type Collection<T extends {}> = {
|
|
|
27
25
|
readonly [Symbol.toStringTag]: 'Collection'
|
|
28
26
|
readonly [Symbol.isConcatSpreadable]: true
|
|
29
27
|
[Symbol.iterator](): IterableIterator<Signal<T>>
|
|
28
|
+
keys(): IterableIterator<string>
|
|
30
29
|
get: () => T[]
|
|
31
30
|
at: (index: number) => Signal<T> | undefined
|
|
32
31
|
byKey: (key: string) => Signal<T> | undefined
|
|
33
32
|
keyAt: (index: number) => string | undefined
|
|
34
33
|
indexOfKey: (key: string) => number | undefined
|
|
35
|
-
on: <K extends keyof Listeners>(type: K, listener: Listener<K>) => Cleanup
|
|
36
34
|
deriveCollection: <R extends {}>(
|
|
37
35
|
callback: CollectionCallback<R, T>,
|
|
38
36
|
) => DerivedCollection<R, T>
|
|
@@ -46,28 +44,23 @@ const TYPE_COLLECTION = 'Collection' as const
|
|
|
46
44
|
/* === Class === */
|
|
47
45
|
|
|
48
46
|
class DerivedCollection<T extends {}, U extends {}> implements Collection<T> {
|
|
49
|
-
#watchers = new Set<Watcher>()
|
|
50
47
|
#source: CollectionSource<U>
|
|
51
48
|
#callback: CollectionCallback<T, U>
|
|
52
49
|
#signals = new Map<string, Computed<T>>()
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
|
|
56
|
-
change: new Set<Listener<'change'>>(),
|
|
57
|
-
remove: new Set<Listener<'remove'>>(),
|
|
58
|
-
sort: new Set<Listener<'sort'>>(),
|
|
59
|
-
}
|
|
60
|
-
#order: string[] = []
|
|
50
|
+
#keys: string[] = []
|
|
51
|
+
#dirty = true
|
|
52
|
+
#watcher: Watcher | undefined
|
|
61
53
|
|
|
62
54
|
constructor(
|
|
63
55
|
source: CollectionSource<U> | (() => CollectionSource<U>),
|
|
64
56
|
callback: CollectionCallback<T, U>,
|
|
57
|
+
options?: SignalOptions<T[]>,
|
|
65
58
|
) {
|
|
66
|
-
validateCallback(
|
|
59
|
+
validateCallback(TYPE_COLLECTION, callback)
|
|
67
60
|
|
|
68
61
|
if (isFunction(source)) source = source()
|
|
69
62
|
if (!isCollectionSource(source))
|
|
70
|
-
throw new InvalidCollectionSourceError(
|
|
63
|
+
throw new InvalidCollectionSourceError(TYPE_COLLECTION, source)
|
|
71
64
|
this.#source = source
|
|
72
65
|
|
|
73
66
|
this.#callback = callback
|
|
@@ -79,61 +72,52 @@ class DerivedCollection<T extends {}, U extends {}> implements Collection<T> {
|
|
|
79
72
|
this.#add(key)
|
|
80
73
|
}
|
|
81
74
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
this.#add(key)
|
|
86
|
-
// For async computations, trigger initial computation
|
|
87
|
-
const signal = this.#signals.get(key)
|
|
88
|
-
if (signal && isAsyncCollectionCallback(this.#callback))
|
|
89
|
-
signal.get()
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
notifyWatchers(this.#watchers)
|
|
93
|
-
emitNotification(this.#listeners.add, additions)
|
|
94
|
-
})
|
|
75
|
+
if (options?.watched)
|
|
76
|
+
registerWatchCallbacks(this, options.watched, options.unwatched)
|
|
77
|
+
}
|
|
95
78
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
79
|
+
#getWatcher(): Watcher {
|
|
80
|
+
this.#watcher ||= createWatcher(
|
|
81
|
+
() => {
|
|
82
|
+
this.#dirty = true
|
|
83
|
+
if (!notifyOf(this)) this.#watcher?.stop()
|
|
84
|
+
},
|
|
85
|
+
() => {
|
|
86
|
+
const newKeys = Array.from(this.#source.keys())
|
|
87
|
+
const allKeys = new Set([...this.#keys, ...newKeys])
|
|
88
|
+
const addedKeys: string[] = []
|
|
89
|
+
const removedKeys: string[] = []
|
|
99
90
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
91
|
+
for (const key of allKeys) {
|
|
92
|
+
const oldHas = this.#keys.includes(key)
|
|
93
|
+
const newHas = newKeys.includes(key)
|
|
103
94
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
watcher.stop()
|
|
107
|
-
this.#ownWatchers.delete(key)
|
|
95
|
+
if (!oldHas && newHas) addedKeys.push(key)
|
|
96
|
+
else if (oldHas && !newHas) removedKeys.push(key)
|
|
108
97
|
}
|
|
109
|
-
}
|
|
110
|
-
this.#order = this.#order.filter(() => true) // Compact array
|
|
111
|
-
notifyWatchers(this.#watchers)
|
|
112
|
-
emitNotification(this.#listeners.remove, removals)
|
|
113
|
-
})
|
|
114
98
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
99
|
+
for (const key of removedKeys) this.#signals.delete(key)
|
|
100
|
+
for (const key of addedKeys) this.#add(key)
|
|
101
|
+
this.#keys = newKeys
|
|
102
|
+
this.#dirty = false
|
|
103
|
+
},
|
|
104
|
+
)
|
|
105
|
+
this.#watcher.onCleanup(() => {
|
|
106
|
+
this.#watcher = undefined
|
|
119
107
|
})
|
|
108
|
+
|
|
109
|
+
return this.#watcher
|
|
120
110
|
}
|
|
121
111
|
|
|
122
112
|
#add(key: string): boolean {
|
|
123
113
|
const computedCallback = isAsyncCollectionCallback<T>(this.#callback)
|
|
124
114
|
? async (_: T, abort: AbortSignal) => {
|
|
125
|
-
const
|
|
126
|
-
if (!sourceSignal) return UNSET
|
|
127
|
-
|
|
128
|
-
const sourceValue = sourceSignal.get() as U
|
|
115
|
+
const sourceValue = this.#source.byKey(key)?.get() as U
|
|
129
116
|
if (sourceValue === UNSET) return UNSET
|
|
130
117
|
return this.#callback(sourceValue, abort)
|
|
131
118
|
}
|
|
132
119
|
: () => {
|
|
133
|
-
const
|
|
134
|
-
if (!sourceSignal) return UNSET
|
|
135
|
-
|
|
136
|
-
const sourceValue = sourceSignal.get() as U
|
|
120
|
+
const sourceValue = this.#source.byKey(key)?.get() as U
|
|
137
121
|
if (sourceValue === UNSET) return UNSET
|
|
138
122
|
return (this.#callback as (sourceValue: U) => T)(
|
|
139
123
|
sourceValue,
|
|
@@ -143,21 +127,10 @@ class DerivedCollection<T extends {}, U extends {}> implements Collection<T> {
|
|
|
143
127
|
const signal = createComputed(computedCallback)
|
|
144
128
|
|
|
145
129
|
this.#signals.set(key, signal)
|
|
146
|
-
if (!this.#
|
|
147
|
-
if (this.#listeners.change.size) this.#addWatcher(key)
|
|
130
|
+
if (!this.#keys.includes(key)) this.#keys.push(key)
|
|
148
131
|
return true
|
|
149
132
|
}
|
|
150
133
|
|
|
151
|
-
#addWatcher(key: string): void {
|
|
152
|
-
const watcher = createWatcher(() => {
|
|
153
|
-
trackSignalReads(watcher, () => {
|
|
154
|
-
this.#signals.get(key)?.get() // Subscribe to the signal
|
|
155
|
-
})
|
|
156
|
-
})
|
|
157
|
-
this.#ownWatchers.set(key, watcher)
|
|
158
|
-
watcher()
|
|
159
|
-
}
|
|
160
|
-
|
|
161
134
|
get [Symbol.toStringTag](): 'Collection' {
|
|
162
135
|
return TYPE_COLLECTION
|
|
163
136
|
}
|
|
@@ -167,30 +140,29 @@ class DerivedCollection<T extends {}, U extends {}> implements Collection<T> {
|
|
|
167
140
|
}
|
|
168
141
|
|
|
169
142
|
*[Symbol.iterator](): IterableIterator<Computed<T>> {
|
|
170
|
-
for (const key of this.#
|
|
143
|
+
for (const key of this.#keys) {
|
|
171
144
|
const signal = this.#signals.get(key)
|
|
172
145
|
if (signal) yield signal as Computed<T>
|
|
173
146
|
}
|
|
174
147
|
}
|
|
175
148
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
149
|
+
keys(): IterableIterator<string> {
|
|
150
|
+
subscribeTo(this)
|
|
151
|
+
if (this.#dirty) this.#getWatcher().run()
|
|
152
|
+
return this.#keys.values()
|
|
179
153
|
}
|
|
180
154
|
|
|
181
155
|
get(): T[] {
|
|
182
|
-
|
|
183
|
-
|
|
156
|
+
subscribeTo(this)
|
|
157
|
+
|
|
158
|
+
if (this.#dirty) this.#getWatcher().run()
|
|
159
|
+
return this.#keys
|
|
184
160
|
.map(key => this.#signals.get(key)?.get())
|
|
185
161
|
.filter(v => v != null && v !== UNSET) as T[]
|
|
186
162
|
}
|
|
187
163
|
|
|
188
164
|
at(index: number): Computed<T> | undefined {
|
|
189
|
-
return this.#signals.get(this.#
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
keys(): IterableIterator<string> {
|
|
193
|
-
return this.#order.values()
|
|
165
|
+
return this.#signals.get(this.#keys[index])
|
|
194
166
|
}
|
|
195
167
|
|
|
196
168
|
byKey(key: string): Computed<T> | undefined {
|
|
@@ -198,41 +170,32 @@ class DerivedCollection<T extends {}, U extends {}> implements Collection<T> {
|
|
|
198
170
|
}
|
|
199
171
|
|
|
200
172
|
keyAt(index: number): string | undefined {
|
|
201
|
-
return this.#
|
|
173
|
+
return this.#keys[index]
|
|
202
174
|
}
|
|
203
175
|
|
|
204
176
|
indexOfKey(key: string): number {
|
|
205
|
-
return this.#
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
on<K extends keyof Listeners>(type: K, listener: Listener<K>): Cleanup {
|
|
209
|
-
this.#listeners[type].add(listener)
|
|
210
|
-
if (type === 'change' && !this.#ownWatchers.size) {
|
|
211
|
-
for (const key of this.#signals.keys()) this.#addWatcher(key)
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return () => {
|
|
215
|
-
this.#listeners[type].delete(listener)
|
|
216
|
-
if (type === 'change' && !this.#listeners.change.size) {
|
|
217
|
-
if (this.#ownWatchers.size) {
|
|
218
|
-
for (const watcher of this.#ownWatchers.values())
|
|
219
|
-
watcher.stop()
|
|
220
|
-
this.#ownWatchers.clear()
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
177
|
+
return this.#keys.indexOf(key)
|
|
224
178
|
}
|
|
225
179
|
|
|
226
180
|
deriveCollection<R extends {}>(
|
|
227
181
|
callback: (sourceValue: T) => R,
|
|
182
|
+
options?: SignalOptions<R[]>,
|
|
228
183
|
): DerivedCollection<R, T>
|
|
229
184
|
deriveCollection<R extends {}>(
|
|
230
185
|
callback: (sourceValue: T, abort: AbortSignal) => Promise<R>,
|
|
186
|
+
options?: SignalOptions<R[]>,
|
|
231
187
|
): DerivedCollection<R, T>
|
|
232
188
|
deriveCollection<R extends {}>(
|
|
233
189
|
callback: CollectionCallback<R, T>,
|
|
190
|
+
options?: SignalOptions<R[]>,
|
|
234
191
|
): DerivedCollection<R, T> {
|
|
235
|
-
return new DerivedCollection(this, callback)
|
|
192
|
+
return new DerivedCollection(this, callback, options)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
get length(): number {
|
|
196
|
+
subscribeTo(this)
|
|
197
|
+
if (this.#dirty) this.#getWatcher().run()
|
|
198
|
+
return this.#keys.length
|
|
236
199
|
}
|
|
237
200
|
}
|
|
238
201
|
|
|
@@ -241,13 +204,13 @@ class DerivedCollection<T extends {}, U extends {}> implements Collection<T> {
|
|
|
241
204
|
/**
|
|
242
205
|
* Check if a value is a collection signal
|
|
243
206
|
*
|
|
244
|
-
* @since 0.17.
|
|
207
|
+
* @since 0.17.2
|
|
245
208
|
* @param {unknown} value - Value to check
|
|
246
209
|
* @returns {boolean} - True if value is a collection signal, false otherwise
|
|
247
210
|
*/
|
|
248
|
-
const isCollection = /*#__PURE__*/ <T extends {}
|
|
211
|
+
const isCollection = /*#__PURE__*/ <T extends {}>(
|
|
249
212
|
value: unknown,
|
|
250
|
-
): value is
|
|
213
|
+
): value is Collection<T> => isObjectOfType(value, TYPE_COLLECTION)
|
|
251
214
|
|
|
252
215
|
/**
|
|
253
216
|
* Check if a value is a collection source
|