stunk 3.0.0-beta.4 → 3.0.0-rc

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.
@@ -20,4 +20,4 @@ interface ReadOnlyChunk<T> extends Omit<Chunk<T>, 'set' | 'reset'> {
20
20
  derive: <D>(fn: (value: T) => D) => ReadOnlyChunk<D>;
21
21
  }
22
22
 
23
- export type { Chunk as C, Middleware as M };
23
+ export type { Chunk as C, Middleware as M, ReadOnlyChunk as R };
@@ -1,4 +1,4 @@
1
- import { M as Middleware, C as Chunk } from '../core-DsoxfUCH.js';
1
+ import { M as Middleware, C as Chunk } from '../core-DAc7hZla.js';
2
2
 
3
3
  /**
4
4
  * Middleware that logs every value passed to `set()` to the console.
@@ -1,4 +1,4 @@
1
- import { C as Chunk } from './core-DsoxfUCH.js';
1
+ import { C as Chunk } from './core-DAc7hZla.js';
2
2
 
3
3
  interface AsyncState<T, E extends Error> {
4
4
  loading: boolean;
@@ -1,6 +1,6 @@
1
- import { A as AsyncChunk } from '../mutation-BGXZyZXA.js';
2
- export { c as AsyncState, d as AsyncStateWithPagination, M as Mutation, h as MutationFn, f as MutationOptions, b as MutationResult, g as MutationState, P as PaginatedAsyncChunk, e as asyncChunk, i as infiniteAsyncChunk, m as mutation } from '../mutation-BGXZyZXA.js';
3
- import { C as Chunk } from '../core-DsoxfUCH.js';
1
+ import { A as AsyncChunk } from '../mutation-CH7ZTMUa.js';
2
+ export { c as AsyncState, d as AsyncStateWithPagination, M as Mutation, h as MutationFn, f as MutationOptions, b as MutationResult, g as MutationState, P as PaginatedAsyncChunk, e as asyncChunk, i as infiniteAsyncChunk, m as mutation } from '../mutation-CH7ZTMUa.js';
3
+ import { C as Chunk } from '../core-DAc7hZla.js';
4
4
 
5
5
  interface GlobalQueryConfig {
6
6
  /**
@@ -1,36 +1,42 @@
1
- import { C as Chunk } from '../core-DsoxfUCH.js';
2
- import { P as PaginatedAsyncChunk, a as PaginationState, A as AsyncChunk, I as InfiniteAsyncChunk, M as Mutation, b as MutationResult } from '../mutation-BGXZyZXA.js';
1
+ import { C as Chunk, R as ReadOnlyChunk } from '../core-DAc7hZla.js';
2
+ import { P as PaginatedAsyncChunk, a as PaginationState, A as AsyncChunk, I as InfiniteAsyncChunk, M as Mutation, b as MutationResult } from '../mutation-CH7ZTMUa.js';
3
3
 
4
4
  /**
5
- * Subscribes to a chunk and returns its current value along with `set`, `reset`, and `destroy`.
5
+ * Subscribes to a chunk and returns its current value along with setters,
6
+ * reset, and destroy. Accepts both writable `Chunk<T>` and read-only
7
+ * `ReadOnlyChunk<T>` (e.g. derived chunks from `.derive()` or `select()`).
6
8
  *
7
- * Pass an optional `selector` to derive a slice of the value and avoid
8
- * unnecessary re-renders when unrelated fields change.
9
- *
10
- * @param chunk - The chunk to subscribe to.
11
- * @param selector - Optional function to select a derived value.
12
- * @returns `[value, set, reset, destroy]`
9
+ * For read-only chunks, the returned `set` and `reset` will be no-ops at
10
+ * runtime prefer `useChunkValue` for derived/read-only chunks.
13
11
  *
14
12
  * @example
15
- * const [count, setCount, reset] = useChunk(countChunk);
13
+ * const count = chunk(0);
14
+ * const [value, setValue] = useChunk(count);
16
15
  *
17
16
  * @example
18
- * // Only re-renders when `name` changes
19
- * const [name, setUser] = useChunk(userChunk, u => u.name);
17
+ * // Works with derived chunks too
18
+ * const doubled = count.derive(n => n * 2);
19
+ * const [value] = useChunk(doubled);
20
20
  */
21
- declare function useChunk<T, S = T>(chunk: Chunk<T>, selector?: (value: T) => S): readonly [S, (valueOrUpdater: T | ((currentValue: T) => T)) => void, () => void, () => void];
21
+ declare function useChunk<T, S = T>(chunk: Chunk<T> | ReadOnlyChunk<T>, selector?: (value: T) => S): readonly [S, (valueOrUpdater: T | ((currentValue: T) => T)) => void, () => void, () => void];
22
22
 
23
23
  /**
24
24
  * Subscribes to a chunk and returns only its current value.
25
- * Use this in read-only components that never need to call `set`.
25
+ * Accepts both writable `Chunk<T>` and read-only `ReadOnlyChunk<T>`
26
+ * (e.g. derived chunks from `.derive()`, `select()`, or `computed()`).
27
+ *
28
+ * Prefer this over `useChunk` when you only need to read — it makes
29
+ * the read-only intent explicit and works correctly with derived chunks.
26
30
  *
27
- * @param chunk - The chunk to subscribe to.
28
- * @param selector - Optional function to select a derived value.
31
+ * @example
32
+ * const isAuthenticated = userChunk.derive(u => u !== null);
33
+ * const auth = useChunkValue(isAuthenticated); // ✅ no type error
29
34
  *
30
35
  * @example
31
- * const name = useChunkValue(userChunk, u => u.name);
36
+ * const total = computed(() => price.get() * qty.get());
37
+ * const value = useChunkValue(total); // ✅ no type error
32
38
  */
33
- declare function useChunkValue<T, S = T>(chunk: Chunk<T>, selector?: (value: T) => S): S;
39
+ declare function useChunkValue<T, S = T>(chunk: Chunk<T> | ReadOnlyChunk<T>, selector?: (value: T) => S): S;
34
40
 
35
41
  interface UseAsyncChunkResult<T, E extends Error, P extends Record<string, any>> {
36
42
  data: T | null;
@@ -1 +1 @@
1
- import {a}from'../chunk-7PLFRQ2T.js';import {b}from'../chunk-PZ7A72TA.js';import {useState,useEffect,useCallback,useRef}from'react';function k(e,s,t={}){let{useShallowEqual:i=false}=t,u=e.get(),n=s(u),a$1=a(n),P=()=>{let m=e.get(),l=s(m);(i?!b(l,n):l!==n)&&(n=l,a$1.set(l));},o=e.subscribe(P),{set:d,reset:T,...E}=a$1;return {...E,derive:m=>k(a$1,m,t),destroy:()=>{o(),a$1.destroy();}}}function U(e,s){let t=s?k(e,s):e,[i,u]=useState(()=>t.get());useEffect(()=>{let o=t.subscribe(d=>{u(()=>d);});return ()=>o()},[t]);let n=useCallback(o=>{e.set(o);},[e]),a=useCallback(()=>{e.reset();},[e]),P=useCallback(()=>{e.destroy();},[e]);return [i,n,a,P]}function _(e,s){let[t]=U(e,s);return t}function x(e){return "nextPage"in e}function M(e){return "setParams"in e}function G(e){return "clearParams"in e}function O(e,s={}){let{initialParams:t,fetchOnMount:i=false}=s,[u,n]=useState(()=>e.get()),a=useRef({initialParams:t,fetchOnMount:i});a.current={initialParams:t,fetchOnMount:i},useEffect(()=>{n(e.get());let r=e.subscribe(q=>{n(q);}),{initialParams:D,fetchOnMount:F}=a.current;return D&&M(e)?e.setParams(D):F&&e.reload(),()=>{r(),e.cleanup();}},[e]);let P=useCallback(r=>e.reload(r),[e]),o=useCallback(r=>e.refresh(r),[e]),d=useCallback(r=>e.mutate(r),[e]),T=useCallback(()=>e.reset(),[e]),E=useCallback(r=>{M(e)&&e.setParams(r);},[e]),m=useCallback(()=>{G(e)&&e.clearParams();},[e]),l=useCallback(()=>x(e)?e.nextPage():Promise.resolve(),[e]),f=useCallback(()=>x(e)?e.prevPage():Promise.resolve(),[e]),h=useCallback(r=>x(e)?e.goToPage(r):Promise.resolve(),[e]),y=useCallback(()=>x(e)?e.resetPagination():Promise.resolve(),[e]),{data:b,loading:v,error:p,lastFetched:g,isPlaceholderData:C=false,pagination:w}=u,A={data:b,loading:v,error:p,lastFetched:g,isPlaceholderData:C,reload:P,refresh:o,mutate:d,reset:T};if(M(e)&&(A.setParams=E,A.clearParams=m),x(e)){let r=A;r.pagination=w,r.nextPage=l,r.prevPage=f,r.goToPage=h,r.resetPagination=y;}return A}function N(e,s={}){let{initialParams:t,autoLoad:i=true,threshold:u=1,fetchOnMount:n}=s,a=O(e,{...t&&{initialParams:t},fetchOnMount:n}),{loading:P,pagination:o,nextPage:d,data:T,error:E,isPlaceholderData:m}=a,l=useRef(P),f=useRef(o?.hasMore??false),h=useRef(d);l.current=P,f.current=o?.hasMore??false,h.current=d;let y=useRef(null);useEffect(()=>{if(!i||typeof window>"u"||!("IntersectionObserver"in window))return;let p=new IntersectionObserver(C=>{C[0].isIntersecting&&!l.current&&f.current&&h.current();},{threshold:u}),g=y.current;return g&&p.observe(g),()=>{g&&p.unobserve(g),p.disconnect();}},[i,u]);let b=useCallback(()=>{!l.current&&f.current&&h.current();},[]),v=P&&T!==null&&T.length>0&&(o?.page??1)>1;return {...a,data:T,error:E,isPlaceholderData:m??false,isFetchingMore:v,hasMore:o?.hasMore??false,loadMore:b,observerTarget:y}}function Y(e){let[s,t]=useState(()=>e.get());useEffect(()=>(t(e.get()),e.subscribe(a=>{t(a);})),[e]);let i=useCallback((...n)=>e.mutate(...n),[e]),u=useCallback(()=>e.reset(),[e]);return {loading:s.loading,data:s.data,error:s.error,isSuccess:s.isSuccess,mutate:i,reset:u}}export{O as useAsyncChunk,U as useChunk,_ as useChunkValue,N as useInfiniteAsyncChunk,Y as useMutation};
1
+ import {a}from'../chunk-7PLFRQ2T.js';import {b}from'../chunk-PZ7A72TA.js';import {useState,useEffect,useCallback,useRef}from'react';function k(e,s,t={}){let{useShallowEqual:i=false}=t,u=e.get(),n=s(u),a$1=a(n),P=()=>{let m=e.get(),l=s(m);(i?!b(l,n):l!==n)&&(n=l,a$1.set(l));},o=e.subscribe(P),{set:d,reset:T,...h}=a$1;return {...h,derive:m=>k(a$1,m,t),destroy:()=>{o(),a$1.destroy();}}}function U(e,s){let t=s?k(e,s):e,[i,u]=useState(()=>t.get());useEffect(()=>{let o=t.subscribe(d=>{u(()=>d);});return ()=>o()},[t]);let n=useCallback(o=>{"set"in e&&e.set(o);},[e]),a=useCallback(()=>{"reset"in e&&e.reset();},[e]),P=useCallback(()=>{e.destroy();},[e]);return [i,n,a,P]}function _(e,s){let[t]=U(e,s);return t}function y(e){return "nextPage"in e}function M(e){return "setParams"in e}function G(e){return "clearParams"in e}function O(e,s={}){let{initialParams:t,fetchOnMount:i=false}=s,[u,n]=useState(()=>e.get()),a=useRef({initialParams:t,fetchOnMount:i});a.current={initialParams:t,fetchOnMount:i},useEffect(()=>{n(e.get());let r=e.subscribe(q=>{n(q);}),{initialParams:D,fetchOnMount:F}=a.current;return D&&M(e)?e.setParams(D):F&&e.reload(),()=>{r(),e.cleanup();}},[e]);let P=useCallback(r=>e.reload(r),[e]),o=useCallback(r=>e.refresh(r),[e]),d=useCallback(r=>e.mutate(r),[e]),T=useCallback(()=>e.reset(),[e]),h=useCallback(r=>{M(e)&&e.setParams(r);},[e]),m=useCallback(()=>{G(e)&&e.clearParams();},[e]),l=useCallback(()=>y(e)?e.nextPage():Promise.resolve(),[e]),f=useCallback(()=>y(e)?e.prevPage():Promise.resolve(),[e]),E=useCallback(r=>y(e)?e.goToPage(r):Promise.resolve(),[e]),x=useCallback(()=>y(e)?e.resetPagination():Promise.resolve(),[e]),{data:b,loading:C,error:p,lastFetched:g,isPlaceholderData:v=false,pagination:w}=u,R={data:b,loading:C,error:p,lastFetched:g,isPlaceholderData:v,reload:P,refresh:o,mutate:d,reset:T};if(M(e)&&(R.setParams=h,R.clearParams=m),y(e)){let r=R;r.pagination=w,r.nextPage=l,r.prevPage=f,r.goToPage=E,r.resetPagination=x;}return R}function N(e,s={}){let{initialParams:t,autoLoad:i=true,threshold:u=1,fetchOnMount:n}=s,a=O(e,{...t&&{initialParams:t},fetchOnMount:n}),{loading:P,pagination:o,nextPage:d,data:T,error:h,isPlaceholderData:m}=a,l=useRef(P),f=useRef(o?.hasMore??false),E=useRef(d);l.current=P,f.current=o?.hasMore??false,E.current=d;let x=useRef(null);useEffect(()=>{if(!i||typeof window>"u"||!("IntersectionObserver"in window))return;let p=new IntersectionObserver(v=>{v[0].isIntersecting&&!l.current&&f.current&&E.current();},{threshold:u}),g=x.current;return g&&p.observe(g),()=>{g&&p.unobserve(g),p.disconnect();}},[i,u]);let b=useCallback(()=>{!l.current&&f.current&&E.current();},[]),C=P&&T!==null&&T.length>0&&(o?.page??1)>1;return {...a,data:T,error:h,isPlaceholderData:m??false,isFetchingMore:C,hasMore:o?.hasMore??false,loadMore:b,observerTarget:x}}function Y(e){let[s,t]=useState(()=>e.get());useEffect(()=>(t(e.get()),e.subscribe(a=>{t(a);})),[e]);let i=useCallback((...n)=>e.mutate(...n),[e]),u=useCallback(()=>e.reset(),[e]);return {loading:s.loading,data:s.data,error:s.error,isSuccess:s.isSuccess,mutate:i,reset:u}}export{O as useAsyncChunk,U as useChunk,_ as useChunkValue,N as useInfiniteAsyncChunk,Y as useMutation};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stunk",
3
- "version": "3.0.0-beta.4",
3
+ "version": "3.0.0-rc",
4
4
  "description": "Stunk is a lightweight, framework-agnostic state management library for JavaScript and TypeScript. It uses chunk-based state units for efficient updates, reactivity, and performance optimization in React, Vue(WIP), Svelte(Coming soon), and Vanilla JS/TS applications.",
5
5
  "type": "module",
6
6
  "repository": {