stunk 2.8.1 → 3.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +171 -128
- package/dist/chunk-3DOB632D.js +1 -0
- package/dist/chunk-HPKV6WRO.js +1 -0
- package/dist/{core-DMY69lzg.d.cts → core-DsoxfUCH.d.cts} +6 -1
- package/dist/{core-DMY69lzg.d.ts → core-DsoxfUCH.d.ts} +6 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +503 -150
- package/dist/index.d.ts +503 -150
- package/dist/index.js +1 -1
- package/dist/middleware/index.cjs +1 -1
- package/dist/middleware/index.d.cts +77 -23
- package/dist/middleware/index.d.ts +77 -23
- package/dist/middleware/index.js +1 -1
- package/dist/mutation-BGXZyZXA.d.ts +214 -0
- package/dist/mutation-Txd2ni6w.d.cts +214 -0
- package/dist/query/index.cjs +1 -0
- package/dist/query/index.d.cts +107 -0
- package/dist/query/index.d.ts +107 -0
- package/dist/query/index.js +1 -0
- package/dist/use-react/index.cjs +1 -1
- package/dist/use-react/index.d.cts +131 -94
- package/dist/use-react/index.d.ts +131 -94
- package/dist/use-react/index.js +1 -1
- package/package.json +122 -121
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { C as Chunk } from './core-DsoxfUCH.cjs';
|
|
2
|
+
|
|
3
|
+
interface AsyncState<T, E extends Error> {
|
|
4
|
+
loading: boolean;
|
|
5
|
+
error: E | null;
|
|
6
|
+
data: T | null;
|
|
7
|
+
lastFetched?: number;
|
|
8
|
+
/** True when showing previous data while new data is loading (keepPreviousData: true) */
|
|
9
|
+
isPlaceholderData?: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface PaginationState {
|
|
12
|
+
page: number;
|
|
13
|
+
pageSize: number;
|
|
14
|
+
total?: number;
|
|
15
|
+
hasMore?: boolean;
|
|
16
|
+
}
|
|
17
|
+
interface AsyncStateWithPagination<T, E extends Error> extends AsyncState<T, E> {
|
|
18
|
+
pagination?: PaginationState;
|
|
19
|
+
}
|
|
20
|
+
interface FetcherResponse<T> {
|
|
21
|
+
data: T;
|
|
22
|
+
total?: number;
|
|
23
|
+
hasMore?: boolean;
|
|
24
|
+
}
|
|
25
|
+
interface AsyncChunkOptions<T, E extends Error = Error> {
|
|
26
|
+
/** Deduplication key — concurrent calls with the same key share one in-flight request */
|
|
27
|
+
key?: string;
|
|
28
|
+
/** Seed data shown before the first fetch completes */
|
|
29
|
+
initialData?: T | null;
|
|
30
|
+
/** Disable fetching until ready — pass a function for dynamic evaluation */
|
|
31
|
+
enabled?: boolean | (() => boolean);
|
|
32
|
+
/** Called after every successful fetch */
|
|
33
|
+
onSuccess?: (data: T) => void;
|
|
34
|
+
/** Called when all retries are exhausted */
|
|
35
|
+
onError?: (error: E) => void;
|
|
36
|
+
/** Number of retries on failure (default: 0) */
|
|
37
|
+
retryCount?: number;
|
|
38
|
+
/** Delay in ms between retries (default: 1000) */
|
|
39
|
+
retryDelay?: number;
|
|
40
|
+
/** Show previous data while refetching — prevents UI flicker on param changes (default: false) */
|
|
41
|
+
keepPreviousData?: boolean;
|
|
42
|
+
/** Time in ms before data is considered stale (default: 0) */
|
|
43
|
+
staleTime?: number;
|
|
44
|
+
/** Time in ms to cache data after last subscriber leaves (default: 300_000) */
|
|
45
|
+
cacheTime?: number;
|
|
46
|
+
/** Auto-refetch interval in ms */
|
|
47
|
+
refetchInterval?: number;
|
|
48
|
+
/** Refetch when window regains focus (default: false) */
|
|
49
|
+
refetchOnWindowFocus?: boolean;
|
|
50
|
+
pagination?: {
|
|
51
|
+
/** Initial page number (default: 1) */
|
|
52
|
+
initialPage?: number;
|
|
53
|
+
/** Items per page (default: 10) */
|
|
54
|
+
pageSize?: number;
|
|
55
|
+
/** Replace data on each page load, or accumulate for infinite scroll (default: 'replace') */
|
|
56
|
+
mode?: 'replace' | 'accumulate';
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
interface AsyncChunk<T, E extends Error = Error> extends Chunk<AsyncStateWithPagination<T, E>> {
|
|
60
|
+
/** Force a fresh fetch, ignoring stale time */
|
|
61
|
+
reload: (params?: any) => Promise<void>;
|
|
62
|
+
/** Fetch only if data is stale — respects staleTime */
|
|
63
|
+
refresh: (params?: any) => Promise<void>;
|
|
64
|
+
/** Update data directly without a network request */
|
|
65
|
+
mutate: (mutator: (currentData: T | null) => T) => void;
|
|
66
|
+
/** Reset to initial state and re-fetch */
|
|
67
|
+
reset: () => void;
|
|
68
|
+
/** Safe cleanup — only tears down if no active subscribers remain */
|
|
69
|
+
cleanup: () => void;
|
|
70
|
+
/** Force cleanup regardless of subscriber count */
|
|
71
|
+
forceCleanup: () => void;
|
|
72
|
+
/** Clear all current params and refetch */
|
|
73
|
+
clearParams: () => void;
|
|
74
|
+
}
|
|
75
|
+
interface PaginatedAsyncChunk<T, E extends Error = Error> extends AsyncChunk<T, E> {
|
|
76
|
+
/** Load the next page */
|
|
77
|
+
nextPage: () => Promise<void>;
|
|
78
|
+
/** Load the previous page */
|
|
79
|
+
prevPage: () => Promise<void>;
|
|
80
|
+
/** Jump to a specific page */
|
|
81
|
+
goToPage: (page: number) => Promise<void>;
|
|
82
|
+
/** Reset pagination to page 1 and re-fetch */
|
|
83
|
+
resetPagination: () => Promise<void>;
|
|
84
|
+
}
|
|
85
|
+
declare function asyncChunk<T, E extends Error = Error>(fetcher: () => Promise<T | FetcherResponse<T>>, options?: AsyncChunkOptions<T, E>): AsyncChunk<T, E> | PaginatedAsyncChunk<T, E>;
|
|
86
|
+
declare function asyncChunk<T, E extends Error = Error, P extends Record<string, any> = {}>(fetcher: (params: P & {
|
|
87
|
+
page?: number;
|
|
88
|
+
pageSize?: number;
|
|
89
|
+
}) => Promise<T | FetcherResponse<T>>, options?: AsyncChunkOptions<T, E>): (AsyncChunk<T, E> | PaginatedAsyncChunk<T, E>) & {
|
|
90
|
+
setParams: (params: Partial<P>) => void;
|
|
91
|
+
reload: (params?: Partial<P>) => Promise<void>;
|
|
92
|
+
refresh: (params?: Partial<P>) => Promise<void>;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
type InfiniteAsyncChunkOptions<T, E extends Error = Error> = Omit<AsyncChunkOptions<T[], E>, 'pagination'> & {
|
|
96
|
+
/** Items per page (default: 10) */
|
|
97
|
+
pageSize?: number;
|
|
98
|
+
};
|
|
99
|
+
type InfiniteAsyncChunk<T, E extends Error = Error, P extends Record<string, any> = {}> = PaginatedAsyncChunk<T[], E> & {
|
|
100
|
+
setParams: (params: Partial<Record<keyof P, P[keyof P] | null>>) => void;
|
|
101
|
+
clearParams: () => void;
|
|
102
|
+
reload: (params?: Partial<P>) => Promise<void>;
|
|
103
|
+
refresh: (params?: Partial<P>) => Promise<void>;
|
|
104
|
+
forceCleanup: () => void;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Creates an infinite scroll async chunk that accumulates pages.
|
|
108
|
+
*
|
|
109
|
+
* A convenience wrapper around `asyncChunk` with `pagination.mode: 'accumulate'`
|
|
110
|
+
* pre-configured. Each `nextPage()` appends to the existing data array.
|
|
111
|
+
*
|
|
112
|
+
* @param fetcher - Async function receiving `{ page, pageSize, ...params }`,
|
|
113
|
+
* returning `{ data: T[], hasMore?, total? }`.
|
|
114
|
+
* @param options.pageSize - Items per page (default: 10).
|
|
115
|
+
* @param options.key - Deduplication key.
|
|
116
|
+
* @param options.onSuccess - Called with the full accumulated array after each fetch.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* const posts = infiniteAsyncChunk(
|
|
120
|
+
* async ({ page, pageSize }) => fetchPosts({ page, pageSize }),
|
|
121
|
+
* { pageSize: 20 }
|
|
122
|
+
* );
|
|
123
|
+
* posts.reload(); // page 1
|
|
124
|
+
* posts.nextPage(); // page 2 appended
|
|
125
|
+
*/
|
|
126
|
+
declare function infiniteAsyncChunk<T, E extends Error = Error, P extends Record<string, any> = {}>(fetcher: (params: P & {
|
|
127
|
+
page: number;
|
|
128
|
+
pageSize: number;
|
|
129
|
+
}) => Promise<{
|
|
130
|
+
data: T[];
|
|
131
|
+
hasMore?: boolean;
|
|
132
|
+
total?: number;
|
|
133
|
+
}>, options?: InfiniteAsyncChunkOptions<T, E>): InfiniteAsyncChunk<T, E, P>;
|
|
134
|
+
|
|
135
|
+
type MutationFn<TData, TVariables> = (variables: TVariables) => Promise<TData>;
|
|
136
|
+
interface MutationOptions<TData, TError extends Error = Error, TVariables = void> {
|
|
137
|
+
/** Chunks to automatically reload after a successful mutation */
|
|
138
|
+
invalidates?: AsyncChunk<any, any>[];
|
|
139
|
+
/** Called after a successful mutation with the returned data and original variables */
|
|
140
|
+
onSuccess?: (data: TData, variables: TVariables) => void;
|
|
141
|
+
/** Called when the mutation fails with the error and original variables */
|
|
142
|
+
onError?: (error: TError, variables: TVariables) => void;
|
|
143
|
+
/** Called after every attempt — success or failure — useful for unconditional cleanup */
|
|
144
|
+
onSettled?: (data: TData | null, error: TError | null, variables: TVariables) => void;
|
|
145
|
+
}
|
|
146
|
+
interface MutationState<TData, TError extends Error = Error> {
|
|
147
|
+
/** True while the mutation is in progress */
|
|
148
|
+
loading: boolean;
|
|
149
|
+
/** The data returned from the last successful mutation, or null */
|
|
150
|
+
data: TData | null;
|
|
151
|
+
/** The error from the last failed mutation, or null */
|
|
152
|
+
error: TError | null;
|
|
153
|
+
/** True after a successful mutation — distinct from data since data can be null on success */
|
|
154
|
+
isSuccess: boolean;
|
|
155
|
+
}
|
|
156
|
+
interface MutationResult<TData, TError extends Error = Error> {
|
|
157
|
+
/** The returned data on success, or null on failure */
|
|
158
|
+
data: TData | null;
|
|
159
|
+
/** The error on failure, or null on success */
|
|
160
|
+
error: TError | null;
|
|
161
|
+
}
|
|
162
|
+
interface Mutation<TData, TError extends Error = Error, TVariables = void> {
|
|
163
|
+
/**
|
|
164
|
+
* Execute the mutation. Always resolves — never throws.
|
|
165
|
+
* Returns `{ data, error }` so you can await it or fire and forget safely.
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* // Fire and forget — safe
|
|
169
|
+
* createPost.mutate({ title: 'Hello' });
|
|
170
|
+
*
|
|
171
|
+
* // Await for local UI control — no try/catch needed
|
|
172
|
+
* const { data, error } = await createPost.mutate({ title: 'Hello' });
|
|
173
|
+
* if (!error) router.push('/posts');
|
|
174
|
+
*/
|
|
175
|
+
mutate: (...args: TVariables extends void ? [] : [variables: TVariables]) => Promise<MutationResult<TData, TError>>;
|
|
176
|
+
/** Returns the current mutation state */
|
|
177
|
+
get: () => MutationState<TData, TError>;
|
|
178
|
+
/** Subscribe to state changes. Returns an unsubscribe function. */
|
|
179
|
+
subscribe: (callback: (state: MutationState<TData, TError>) => void) => () => void;
|
|
180
|
+
/** Reset state back to initial — clears data, error, isSuccess */
|
|
181
|
+
reset: () => void;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Creates a reactive mutation for POST, PUT, DELETE, or any async side effect.
|
|
185
|
+
*
|
|
186
|
+
* Always returns a promise that resolves — never throws.
|
|
187
|
+
* On success, automatically reloads any chunks listed in `invalidates`.
|
|
188
|
+
*
|
|
189
|
+
* @param mutationFn - Async function that performs the side effect.
|
|
190
|
+
* @param options.invalidates - Chunks to reload after a successful mutation.
|
|
191
|
+
* @param options.onSuccess - Called with data and variables on success.
|
|
192
|
+
* @param options.onError - Called with error and variables on failure.
|
|
193
|
+
* @param options.onSettled - Called after every attempt regardless of outcome.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* const createPost = mutation(
|
|
197
|
+
* async (data: NewPost) => fetchAPI('/posts', { method: 'POST', body: data }),
|
|
198
|
+
* {
|
|
199
|
+
* invalidates: [postsChunk],
|
|
200
|
+
* onSuccess: (data) => toast.success('Post created!'),
|
|
201
|
+
* onError: (err) => toast.error(err.message),
|
|
202
|
+
* }
|
|
203
|
+
* );
|
|
204
|
+
*
|
|
205
|
+
* // Fire and forget
|
|
206
|
+
* createPost.mutate({ title: 'Hello' });
|
|
207
|
+
*
|
|
208
|
+
* // Await for local control
|
|
209
|
+
* const { data, error } = await createPost.mutate({ title: 'Hello' });
|
|
210
|
+
* if (!error) router.push('/posts');
|
|
211
|
+
*/
|
|
212
|
+
declare function mutation<TData, TError extends Error = Error, TVariables = void>(mutationFn: MutationFn<TData, TVariables>, options?: MutationOptions<TData, TError, TVariables>): Mutation<TData, TError, TVariables>;
|
|
213
|
+
|
|
214
|
+
export { type AsyncChunk as A, type InfiniteAsyncChunk as I, type Mutation as M, type PaginatedAsyncChunk as P, type PaginationState as a, type MutationResult as b, type AsyncState as c, type AsyncStateWithPagination as d, asyncChunk as e, type MutationOptions as f, type MutationState as g, type MutationFn as h, infiniteAsyncChunk as i, mutation as m };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';function Y(e,a){if(e===void 0)throw new Error("Value cannot be undefined.");if(a.length===0)return e;let n=e;for(let l=0;l<a.length;l++){let y=a[l],m=typeof y=="function"?y:y.fn,d=typeof y=="function"?`index ${l}`:y.name||`index ${l}`;try{let o=m(n);if(o===void 0)break;if(o===null)throw new Error(`Middleware "${d}" returned null value.`);n=o;}catch(o){let t=o instanceof Error?o.message:String(o);throw new Error(`Middleware "${d}" threw an error: ${t}`)}}return n}function q(e,a,n="",l={}){let{checkMissing:y=true,checkTypes:m=true}=l;if(e===null||a===null||e===void 0||a===void 0)return;if(typeof e!=typeof a){console.error(`\u{1F6A8} Stunk: Type mismatch at '${n||"root"}'. Expected ${typeof e}, got ${typeof a}.`);return}if(typeof e!="object"||typeof a!="object")return;if(Array.isArray(e)!==Array.isArray(a)){console.error(`\u{1F6A8} Stunk: Type mismatch at '${n||"root"}'. Expected ${Array.isArray(e)?"array":"object"}, got ${Array.isArray(a)?"array":"object"}.`);return}if(Array.isArray(e)&&Array.isArray(a)){if(e.length>0&&typeof e[0]=="object")for(let i=0;i<a.length;i++)q(e[0],a[i],`${n}[${i}]`,l);return}let d=Object.keys(e),o=Object.keys(a),t=o.filter(i=>!d.includes(i));if(t.length>0&&(console.error(`\u{1F6A8} Stunk: Unknown properties at '${n||"root"}': ${t.join(", ")}`),console.error("Expected keys:",d),console.error("Received keys:",o)),y){let i=d.filter(u=>!o.includes(u));i.length>0&&console.error(`\u{1F6A8} Stunk: Missing properties at '${n||"root"}': ${i.join(", ")}`);}for(let i of d){let u=e[i],c=a[i];u===void 0||c===void 0||c===null||(m&&typeof u!="object"&&typeof u!=typeof c&&console.error(`\u{1F6A8} Stunk: Type mismatch at '${n?n+".":""}${i}'. Expected ${typeof u}, got ${typeof c}.`),q(u,c,n?`${n}.${i}`:i,l));}}var ee=new Set,K=new Map,oe=0;function O(e,a={}){let n=oe++,l=a.name||`chunk_${n}`,y=a.middleware||[],m=a.strict??false;if(e===void 0)throw new Error(`[${l}] Initial value cannot be undefined.`);let d=e!==null&&typeof e=="object"&&!Array.isArray(e)?new Set(Object.keys(e)):null,o=e,t=new Set,i=()=>{t.forEach(p=>p(o));};K.set(n,{notify:i});let u=()=>{if(t.size===0){K.delete(n);return}i();},c=()=>(o),b=()=>o,h=p=>{let T;if(typeof p=="function"?T=p(o):T=p,q(o,T),d&&T!==null&&typeof T=="object"&&!Array.isArray(T)){let s=Object.keys(T).filter(f=>!d.has(f));if(s.length>0){let f=`[${l}] Unexpected keys in set(): ${s.join(", ")}. These keys were not present in the initial shape.`;if(m)throw new Error(`\u{1F6A8} Stunk: ${f}`);console.error(`\u{1F6A8} Stunk: ${f}`);}}let P=Y(T,y);P!==o&&(o=P,u());},A=p=>{if(typeof p!="function")throw new Error("Callback must be a function.");return t.add(p),()=>t.delete(p)},S={get:c,peek:b,set:h,subscribe:A,derive:p=>{if(typeof p!="function")throw new Error("Derive function must be a function.");let T=p(o),P=O(T),s=A(()=>{let $=p(o);P.set($);}),f=P.destroy;return P.destroy=()=>{s(),f();},P},reset:()=>{o=e,u();},destroy:()=>{t.clear(),o=e,ee.delete(n),K.delete(n);},[Symbol.for("stunk.meta")]:{name:l,id:n}};return S}var R={};function ie(e){R={...e.query!==void 0&&{query:{...R.query,...e.query}},...e.mutation!==void 0&&{mutation:{...R.mutation,...e.mutation}}};}function _(){return R}function se(){R={};}var I=new Map,ue=0;function N(e,a={}){let n=_().query??{},{key:l,initialData:y=null,enabled:m=true,onSuccess:d=n.onSuccess,onError:o=n.onError,retryCount:t=n.retryCount??0,retryDelay:i=n.retryDelay??1e3,keepPreviousData:u=false,staleTime:c=n.staleTime??0,cacheTime:b=n.cacheTime??5*60*1e3,refetchInterval:h=n.refetchInterval,refetchOnWindowFocus:A=n.refetchOnWindowFocus??false,pagination:w}=a,E=l??`async_chunk_${ue++}`,C=()=>typeof m=="function"?m():m,S=!!w,p=w?.mode||"replace",T=e.length>0,P={loading:C()&&!T,error:null,data:y,lastFetched:void 0,isPlaceholderData:false,pagination:S?{page:w.initialPage||1,pageSize:w.pageSize||10,total:void 0,hasMore:void 0}:void 0},s=O(P),f={},$=null,j=null,F=null,z=0,B=()=>{let r=s.get();return !r.lastFetched||c===0?true:Date.now()-r.lastFetched>c},te=()=>{s.set({...s.get(),data:y,lastFetched:void 0});},re=()=>{j&&clearTimeout(j),b>0&&(j=setTimeout(te,b));},G=()=>{$&&(clearInterval($),$=null),j&&(clearTimeout(j),j=null),F&&typeof window<"u"&&(window.removeEventListener("focus",F),F=null);},L=()=>{C()&&(typeof window>"u"||(h&&h>0&&($=setInterval(()=>{k(void 0,0,false);},h)),A&&(F=()=>{B()&&k(void 0,0,false);},window.addEventListener("focus",F))));},k=async(r,g=t,D=false)=>{if(!C()||(r!==void 0&&(f={...f,...r}),!D&&!B()&&s.get().data!==null))return;if(I.has(E))return I.get(E);let W=s.get();s.set({...W,loading:true,error:null,data:W.data,isPlaceholderData:u&&W.data!==null});let U=(async()=>{try{let V={...f};if(S){let M=s.get().pagination;M&&(V.page=M.page,V.pageSize=M.pageSize);}let v=T?await e(V):await e(),x,J,X;if(v&&typeof v=="object"&&"data"in v){let M=v;x=M.data,J=M.total,X=M.hasMore;}else x=v;let Q=s.get();S&&p==="accumulate"&&Q.data&&Array.isArray(Q.data)&&Array.isArray(x)&&(x=[...Q.data,...x]),s.set({loading:!1,error:null,data:x,lastFetched:Date.now(),isPlaceholderData:!1,pagination:S?{...Q.pagination,total:J,hasMore:X}:void 0}),re(),d&&d(x);}catch(V){if(g>0)return await new Promise(x=>setTimeout(x,i)),I.delete(E),k(r,g-1,D);let v=s.get();s.set({loading:false,error:V,data:v.data,lastFetched:v.lastFetched,isPlaceholderData:false,pagination:v.pagination}),o&&o(V);}finally{I.delete(E);}})();return I.set(E,U),U};L(),C()&&!T&&k();let H={...s,subscribe:r=>{z++;let g=s.subscribe(r);return ()=>{g(),z--;}},reload:async r=>{await k(r,t,true);},refresh:async r=>{await k(r,t,false);},mutate:r=>{let g=s.get();s.set({...g,data:r(g.data)});},reset:()=>{G(),f={},s.set({...P,loading:C()&&!T}),L(),C()&&!T&&k();},cleanup:()=>{z<=0&&G();},forceCleanup:()=>{G();},setParams:r=>{let g={...f};for(let D in r)r[D]===null?delete g[D]:g[D]=r[D];f=g,C()&&k(f,t,true);},clearParams:()=>{f={},C()&&k(void 0,t,true);}};return S?{...H,nextPage:async()=>{let r=s.get();!r.pagination||r.pagination.hasMore===false||(s.set({...r,pagination:{...r.pagination,page:r.pagination.page+1}}),await k(f,t,true));},prevPage:async()=>{let r=s.get();!r.pagination||r.pagination.page<=1||(s.set({...r,pagination:{...r.pagination,page:r.pagination.page-1}}),await k(f,t,true));},goToPage:async r=>{let g=s.get();!g.pagination||r<1||(s.set({...g,pagination:{...g.pagination,page:r}}),await k(f,t,true));},resetPagination:async()=>{let r=s.get();r.pagination&&(s.set({...r,data:p==="accumulate"?y:r.data,pagination:{...r.pagination,page:w?.initialPage||1}}),await k(f,t,true));}}:H}function ce(e,a={}){let{pageSize:n=10,...l}=a;return N(e,{...l,pagination:{pageSize:n,mode:"accumulate",initialPage:1}})}function le(e){let a=Object.entries(e),n=a.reduce((t,[i,u])=>(t[i]=u.get().data,t),{}),l=a.reduce((t,[i,u])=>{let c=u.get().error;return c&&(t[i]=c),t},{}),y=a.some(([,t])=>t.get().loading),m=a.find(([,t])=>t.get().error)?.[1].get().error??null,o=O({loading:y,error:m,errors:l,data:n});return a.forEach(([t,i])=>{i.subscribe(()=>{let u=false,c=null,b={},h={...o.get().data};a.forEach(([A,w])=>{let E=w.get();E.loading&&(u=true),E.error&&(c||(c=E.error),b[A]=E.error),h[A]=E.data;}),o.set({loading:u,error:c,errors:b,data:h});});}),o}function de(e,a={}){let n=_().mutation??{},{invalidates:l=[],onSuccess:y=n.onSuccess,onError:m=n.onError,onSettled:d}=a,o={loading:false,data:null,error:null,isSuccess:false},t=O(o);return {mutate:async(...u)=>{let c=u[0];t.set({loading:true,data:null,error:null,isSuccess:false});try{let b=await e(c);return t.set({loading:!1,data:b,error:null,isSuccess:!0}),l.length>0&&await Promise.all(l.map(h=>h.reload())),y&&y(b,c),d&&d(b,null,c),{data:b,error:null}}catch(b){let h=b;return t.set({loading:false,data:null,error:h,isSuccess:false}),m&&m(h,c),d&&d(null,h,c),{data:null,error:h}}},get:()=>t.get(),subscribe:u=>t.subscribe(u),reset:()=>t.set(o)}}exports.asyncChunk=N;exports.combineAsyncChunks=le;exports.configureQuery=ie;exports.getGlobalQueryConfig=_;exports.infiniteAsyncChunk=ce;exports.mutation=de;exports.resetQueryConfig=se;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { A as AsyncChunk } from '../mutation-Txd2ni6w.cjs';
|
|
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-Txd2ni6w.cjs';
|
|
3
|
+
import { C as Chunk } from '../core-DsoxfUCH.cjs';
|
|
4
|
+
|
|
5
|
+
interface GlobalQueryConfig {
|
|
6
|
+
/**
|
|
7
|
+
* Default configuration applied to all asyncChunk instances.
|
|
8
|
+
* Per-chunk options always override these defaults.
|
|
9
|
+
*/
|
|
10
|
+
query?: {
|
|
11
|
+
/** Time in ms before data is considered stale (default: 0) */
|
|
12
|
+
staleTime?: number;
|
|
13
|
+
/** Time in ms to cache data after last subscriber leaves (default: 300_000) */
|
|
14
|
+
cacheTime?: number;
|
|
15
|
+
/** Auto-refetch interval in ms */
|
|
16
|
+
refetchInterval?: number;
|
|
17
|
+
/** Refetch when window regains focus (default: false) */
|
|
18
|
+
refetchOnWindowFocus?: boolean;
|
|
19
|
+
/** Number of retries on failure (default: 0) */
|
|
20
|
+
retryCount?: number;
|
|
21
|
+
/** Delay in ms between retries (default: 1000) */
|
|
22
|
+
retryDelay?: number;
|
|
23
|
+
/** Global error handler — called when all retries are exhausted */
|
|
24
|
+
onError?: (error: Error) => void;
|
|
25
|
+
/** Global success handler — called after every successful fetch */
|
|
26
|
+
onSuccess?: (data: unknown) => void;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Default configuration applied to all mutation instances.
|
|
30
|
+
* Reserved for when mutation() ships — per-mutation options always override.
|
|
31
|
+
*/
|
|
32
|
+
mutation?: {
|
|
33
|
+
/** Global error handler for mutations */
|
|
34
|
+
onError?: (error: Error) => void;
|
|
35
|
+
/** Global success handler for mutations */
|
|
36
|
+
onSuccess?: (data: unknown) => void;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Configures global defaults for all `asyncChunk` and `mutation` instances.
|
|
41
|
+
*
|
|
42
|
+
* Call this once at app entry — before any `asyncChunk` is created.
|
|
43
|
+
* Per-chunk options always take precedence over these defaults.
|
|
44
|
+
*
|
|
45
|
+
* @param config.query - Defaults for all async chunks (staleTime, retryCount, onError, etc.)
|
|
46
|
+
* @param config.mutation - Defaults for all mutations (onError, onSuccess)
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* import { configureQuery } from "stunk/query";
|
|
50
|
+
*
|
|
51
|
+
* configureQuery({
|
|
52
|
+
* query: {
|
|
53
|
+
* staleTime: 30_000,
|
|
54
|
+
* retryCount: 3,
|
|
55
|
+
* refetchOnWindowFocus: true,
|
|
56
|
+
* onError: (err) => toast.error(err.message),
|
|
57
|
+
* },
|
|
58
|
+
* mutation: {
|
|
59
|
+
* onError: (err) => toast.error(err.message),
|
|
60
|
+
* onSuccess: () => toast.success("Done!"),
|
|
61
|
+
* },
|
|
62
|
+
* });
|
|
63
|
+
*/
|
|
64
|
+
declare function configureQuery(config: GlobalQueryConfig): void;
|
|
65
|
+
/**
|
|
66
|
+
* Returns the current global query config.
|
|
67
|
+
* Used internally by asyncChunk and mutation to read defaults.
|
|
68
|
+
*/
|
|
69
|
+
declare function getGlobalQueryConfig(): GlobalQueryConfig;
|
|
70
|
+
/**
|
|
71
|
+
* Resets the global config back to defaults.
|
|
72
|
+
* Primarily useful in tests to avoid config bleed between test cases.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* afterEach(() => resetQueryConfig());
|
|
76
|
+
*/
|
|
77
|
+
declare function resetQueryConfig(): void;
|
|
78
|
+
|
|
79
|
+
type InferAsyncData<T> = T extends AsyncChunk<infer U, Error> ? U : never;
|
|
80
|
+
type CombinedData<T extends Record<string, AsyncChunk<any>>> = {
|
|
81
|
+
[K in keyof T]: InferAsyncData<T[K]> | null;
|
|
82
|
+
};
|
|
83
|
+
type CombinedState<T extends Record<string, AsyncChunk<any>>> = {
|
|
84
|
+
loading: boolean;
|
|
85
|
+
error: Error | null;
|
|
86
|
+
errors: Partial<{
|
|
87
|
+
[K in keyof T]: Error;
|
|
88
|
+
}>;
|
|
89
|
+
data: CombinedData<T>;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Combines multiple async chunks into a single unified state chunk.
|
|
94
|
+
*
|
|
95
|
+
* The result tracks `loading` (true if any chunk is loading), `error` (first
|
|
96
|
+
* error encountered), `errors` (per-chunk errors), and `data` (per-chunk data).
|
|
97
|
+
*
|
|
98
|
+
* @param chunks - A record of named `AsyncChunk` instances.
|
|
99
|
+
* @returns A `Chunk<CombinedState<T>>` that reflects the live state of all inputs.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* const combined = combineAsyncChunks({ user: userChunk, posts: postsChunk });
|
|
103
|
+
* combined.get(); // { loading, error, errors, data: { user, posts } }
|
|
104
|
+
*/
|
|
105
|
+
declare function combineAsyncChunks<T extends Record<string, AsyncChunk<any>>>(chunks: T): Chunk<CombinedState<T>>;
|
|
106
|
+
|
|
107
|
+
export { AsyncChunk, type GlobalQueryConfig, combineAsyncChunks, configureQuery, getGlobalQueryConfig, resetQueryConfig };
|
|
@@ -0,0 +1,107 @@
|
|
|
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';
|
|
4
|
+
|
|
5
|
+
interface GlobalQueryConfig {
|
|
6
|
+
/**
|
|
7
|
+
* Default configuration applied to all asyncChunk instances.
|
|
8
|
+
* Per-chunk options always override these defaults.
|
|
9
|
+
*/
|
|
10
|
+
query?: {
|
|
11
|
+
/** Time in ms before data is considered stale (default: 0) */
|
|
12
|
+
staleTime?: number;
|
|
13
|
+
/** Time in ms to cache data after last subscriber leaves (default: 300_000) */
|
|
14
|
+
cacheTime?: number;
|
|
15
|
+
/** Auto-refetch interval in ms */
|
|
16
|
+
refetchInterval?: number;
|
|
17
|
+
/** Refetch when window regains focus (default: false) */
|
|
18
|
+
refetchOnWindowFocus?: boolean;
|
|
19
|
+
/** Number of retries on failure (default: 0) */
|
|
20
|
+
retryCount?: number;
|
|
21
|
+
/** Delay in ms between retries (default: 1000) */
|
|
22
|
+
retryDelay?: number;
|
|
23
|
+
/** Global error handler — called when all retries are exhausted */
|
|
24
|
+
onError?: (error: Error) => void;
|
|
25
|
+
/** Global success handler — called after every successful fetch */
|
|
26
|
+
onSuccess?: (data: unknown) => void;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Default configuration applied to all mutation instances.
|
|
30
|
+
* Reserved for when mutation() ships — per-mutation options always override.
|
|
31
|
+
*/
|
|
32
|
+
mutation?: {
|
|
33
|
+
/** Global error handler for mutations */
|
|
34
|
+
onError?: (error: Error) => void;
|
|
35
|
+
/** Global success handler for mutations */
|
|
36
|
+
onSuccess?: (data: unknown) => void;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Configures global defaults for all `asyncChunk` and `mutation` instances.
|
|
41
|
+
*
|
|
42
|
+
* Call this once at app entry — before any `asyncChunk` is created.
|
|
43
|
+
* Per-chunk options always take precedence over these defaults.
|
|
44
|
+
*
|
|
45
|
+
* @param config.query - Defaults for all async chunks (staleTime, retryCount, onError, etc.)
|
|
46
|
+
* @param config.mutation - Defaults for all mutations (onError, onSuccess)
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* import { configureQuery } from "stunk/query";
|
|
50
|
+
*
|
|
51
|
+
* configureQuery({
|
|
52
|
+
* query: {
|
|
53
|
+
* staleTime: 30_000,
|
|
54
|
+
* retryCount: 3,
|
|
55
|
+
* refetchOnWindowFocus: true,
|
|
56
|
+
* onError: (err) => toast.error(err.message),
|
|
57
|
+
* },
|
|
58
|
+
* mutation: {
|
|
59
|
+
* onError: (err) => toast.error(err.message),
|
|
60
|
+
* onSuccess: () => toast.success("Done!"),
|
|
61
|
+
* },
|
|
62
|
+
* });
|
|
63
|
+
*/
|
|
64
|
+
declare function configureQuery(config: GlobalQueryConfig): void;
|
|
65
|
+
/**
|
|
66
|
+
* Returns the current global query config.
|
|
67
|
+
* Used internally by asyncChunk and mutation to read defaults.
|
|
68
|
+
*/
|
|
69
|
+
declare function getGlobalQueryConfig(): GlobalQueryConfig;
|
|
70
|
+
/**
|
|
71
|
+
* Resets the global config back to defaults.
|
|
72
|
+
* Primarily useful in tests to avoid config bleed between test cases.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* afterEach(() => resetQueryConfig());
|
|
76
|
+
*/
|
|
77
|
+
declare function resetQueryConfig(): void;
|
|
78
|
+
|
|
79
|
+
type InferAsyncData<T> = T extends AsyncChunk<infer U, Error> ? U : never;
|
|
80
|
+
type CombinedData<T extends Record<string, AsyncChunk<any>>> = {
|
|
81
|
+
[K in keyof T]: InferAsyncData<T[K]> | null;
|
|
82
|
+
};
|
|
83
|
+
type CombinedState<T extends Record<string, AsyncChunk<any>>> = {
|
|
84
|
+
loading: boolean;
|
|
85
|
+
error: Error | null;
|
|
86
|
+
errors: Partial<{
|
|
87
|
+
[K in keyof T]: Error;
|
|
88
|
+
}>;
|
|
89
|
+
data: CombinedData<T>;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Combines multiple async chunks into a single unified state chunk.
|
|
94
|
+
*
|
|
95
|
+
* The result tracks `loading` (true if any chunk is loading), `error` (first
|
|
96
|
+
* error encountered), `errors` (per-chunk errors), and `data` (per-chunk data).
|
|
97
|
+
*
|
|
98
|
+
* @param chunks - A record of named `AsyncChunk` instances.
|
|
99
|
+
* @returns A `Chunk<CombinedState<T>>` that reflects the live state of all inputs.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* const combined = combineAsyncChunks({ user: userChunk, posts: postsChunk });
|
|
103
|
+
* combined.get(); // { loading, error, errors, data: { user, posts } }
|
|
104
|
+
*/
|
|
105
|
+
declare function combineAsyncChunks<T extends Record<string, AsyncChunk<any>>>(chunks: T): Chunk<CombinedState<T>>;
|
|
106
|
+
|
|
107
|
+
export { AsyncChunk, type GlobalQueryConfig, combineAsyncChunks, configureQuery, getGlobalQueryConfig, resetQueryConfig };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {a}from'../chunk-HPKV6WRO.js';import'../chunk-3DOB632D.js';var O={};function Y(i){O={...i.query!==void 0&&{query:{...O.query,...i.query}},...i.mutation!==void 0&&{mutation:{...O.mutation,...i.mutation}}};}function R(){return O}function Z(){O={};}var V=new Map,ee=0;function L(i,l={}){let r=R().query??{},{key:T,initialData:b=null,enabled:h=true,onSuccess:E=r.onSuccess,onError:p=r.onError,retryCount:a$1=r.retryCount??0,retryDelay:P=r.retryDelay??1e3,keepPreviousData:c=false,staleTime:n=r.staleTime??0,cacheTime:d=r.cacheTime??5*60*1e3,refetchInterval:s=r.refetchInterval,refetchOnWindowFocus:Q=r.refetchOnWindowFocus??false,pagination:k}=l,g=T??`async_chunk_${ee++}`,C=()=>typeof h=="function"?h():h,w=!!k,j=k?.mode||"replace",M=i.length>0,K={loading:C()&&!M,error:null,data:b,lastFetched:void 0,isPlaceholderData:false,pagination:w?{page:k.initialPage||1,pageSize:k.pageSize||10,total:void 0,hasMore:void 0}:void 0},t=a(K),f={},I=null,S=null,F=null,G=0,N=()=>{let e=t.get();return !e.lastFetched||n===0?true:Date.now()-e.lastFetched>n},U=()=>{t.set({...t.get(),data:b,lastFetched:void 0});},X=()=>{S&&clearTimeout(S),d>0&&(S=setTimeout(U,d));},q=()=>{I&&(clearInterval(I),I=null),S&&(clearTimeout(S),S=null),F&&typeof window<"u"&&(window.removeEventListener("focus",F),F=null);},_=()=>{C()&&(typeof window>"u"||(s&&s>0&&(I=setInterval(()=>{u(void 0,0,false);},s)),Q&&(F=()=>{N()&&u(void 0,0,false);},window.addEventListener("focus",F))));},u=async(e,o=a$1,v=false)=>{if(!C()||(e!==void 0&&(f={...f,...e}),!v&&!N()&&t.get().data!==null))return;if(V.has(g))return V.get(g);let W=t.get();t.set({...W,loading:true,error:null,data:W.data,isPlaceholderData:c&&W.data!==null});let $=(async()=>{try{let A={...f};if(w){let x=t.get().pagination;x&&(A.page=x.page,A.pageSize=x.pageSize);}let m=M?await i(A):await i(),y,B,J;if(m&&typeof m=="object"&&"data"in m){let x=m;y=x.data,B=x.total,J=x.hasMore;}else y=m;let z=t.get();w&&j==="accumulate"&&z.data&&Array.isArray(z.data)&&Array.isArray(y)&&(y=[...z.data,...y]),t.set({loading:!1,error:null,data:y,lastFetched:Date.now(),isPlaceholderData:!1,pagination:w?{...z.pagination,total:B,hasMore:J}:void 0}),X(),E&&E(y);}catch(A){if(o>0)return await new Promise(y=>setTimeout(y,P)),V.delete(g),u(e,o-1,v);let m=t.get();t.set({loading:false,error:A,data:m.data,lastFetched:m.lastFetched,isPlaceholderData:false,pagination:m.pagination}),p&&p(A);}finally{V.delete(g);}})();return V.set(g,$),$};_(),C()&&!M&&u();let H={...t,subscribe:e=>{G++;let o=t.subscribe(e);return ()=>{o(),G--;}},reload:async e=>{await u(e,a$1,true);},refresh:async e=>{await u(e,a$1,false);},mutate:e=>{let o=t.get();t.set({...o,data:e(o.data)});},reset:()=>{q(),f={},t.set({...K,loading:C()&&!M}),_(),C()&&!M&&u();},cleanup:()=>{G<=0&&q();},forceCleanup:()=>{q();},setParams:e=>{let o={...f};for(let v in e)e[v]===null?delete o[v]:o[v]=e[v];f=o,C()&&u(f,a$1,true);},clearParams:()=>{f={},C()&&u(void 0,a$1,true);}};return w?{...H,nextPage:async()=>{let e=t.get();!e.pagination||e.pagination.hasMore===false||(t.set({...e,pagination:{...e.pagination,page:e.pagination.page+1}}),await u(f,a$1,true));},prevPage:async()=>{let e=t.get();!e.pagination||e.pagination.page<=1||(t.set({...e,pagination:{...e.pagination,page:e.pagination.page-1}}),await u(f,a$1,true));},goToPage:async e=>{let o=t.get();!o.pagination||e<1||(t.set({...o,pagination:{...o.pagination,page:e}}),await u(f,a$1,true));},resetPagination:async()=>{let e=t.get();e.pagination&&(t.set({...e,data:j==="accumulate"?b:e.data,pagination:{...e.pagination,page:k?.initialPage||1}}),await u(f,a$1,true));}}:H}function ae(i,l={}){let{pageSize:r=10,...T}=l;return L(i,{...T,pagination:{pageSize:r,mode:"accumulate",initialPage:1}})}function te(i){let l=Object.entries(i),r=l.reduce((a,[P,c])=>(a[P]=c.get().data,a),{}),T=l.reduce((a,[P,c])=>{let n=c.get().error;return n&&(a[P]=n),a},{}),b=l.some(([,a])=>a.get().loading),h=l.find(([,a])=>a.get().error)?.[1].get().error??null,p=a({loading:b,error:h,errors:T,data:r});return l.forEach(([a,P])=>{P.subscribe(()=>{let c=false,n=null,d={},s={...p.get().data};l.forEach(([Q,k])=>{let g=k.get();g.loading&&(c=true),g.error&&(n||(n=g.error),d[Q]=g.error),s[Q]=g.data;}),p.set({loading:c,error:n,errors:d,data:s});});}),p}function re(i,l={}){let r=R().mutation??{},{invalidates:T=[],onSuccess:b=r.onSuccess,onError:h=r.onError,onSettled:E}=l,p={loading:false,data:null,error:null,isSuccess:false},a$1=a(p);return {mutate:async(...c)=>{let n=c[0];a$1.set({loading:true,data:null,error:null,isSuccess:false});try{let d=await i(n);return a$1.set({loading:!1,data:d,error:null,isSuccess:!0}),T.length>0&&await Promise.all(T.map(s=>s.reload())),b&&b(d,n),E&&E(d,null,n),{data:d,error:null}}catch(d){let s=d;return a$1.set({loading:false,data:null,error:s,isSuccess:false}),h&&h(s,n),E&&E(null,s,n),{data:null,error:s}}},get:()=>a$1.get(),subscribe:c=>a$1.subscribe(c),reset:()=>a$1.set(p)}}export{L as asyncChunk,te as combineAsyncChunks,Y as configureQuery,R as getGlobalQueryConfig,ae as infiniteAsyncChunk,re as mutation,Z as resetQueryConfig};
|
package/dist/use-react/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var react=require('react');
|
|
1
|
+
'use strict';var react=require('react');function _(e,t){if(e===void 0)throw new Error("Value cannot be undefined.");if(t.length===0)return e;let r=e;for(let o=0;o<t.length;o++){let i=t[o],c=typeof i=="function"?i:i.fn,a=typeof i=="function"?`index ${o}`:i.name||`index ${o}`;try{let n=c(r);if(n===void 0)break;if(n===null)throw new Error(`Middleware "${a}" returned null value.`);r=n;}catch(n){let u=n instanceof Error?n.message:String(n);throw new Error(`Middleware "${a}" threw an error: ${u}`)}}return r}function I(e,t){if(e===t)return true;if(!e||!t||typeof e!=typeof t)return false;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return false;for(let r=0;r<e.length;r++)if(e[r]!==t[r])return false;return true}if(typeof e=="object"&&typeof t=="object"){let r=Object.keys(e),o=Object.keys(t);if(r.length!==o.length)return false;for(let i of r)if(!Object.prototype.hasOwnProperty.call(t,i)||e[i]!==t[i])return false;return true}return false}function R(e,t,r="",o={}){let{checkMissing:i=true,checkTypes:c=true}=o;if(e===null||t===null||e===void 0||t===void 0)return;if(typeof e!=typeof t){console.error(`\u{1F6A8} Stunk: Type mismatch at '${r||"root"}'. Expected ${typeof e}, got ${typeof t}.`);return}if(typeof e!="object"||typeof t!="object")return;if(Array.isArray(e)!==Array.isArray(t)){console.error(`\u{1F6A8} Stunk: Type mismatch at '${r||"root"}'. Expected ${Array.isArray(e)?"array":"object"}, got ${Array.isArray(t)?"array":"object"}.`);return}if(Array.isArray(e)&&Array.isArray(t)){if(e.length>0&&typeof e[0]=="object")for(let s=0;s<t.length;s++)R(e[0],t[s],`${r}[${s}]`,o);return}let a=Object.keys(e),n=Object.keys(t),u=n.filter(s=>!a.includes(s));if(u.length>0&&(console.error(`\u{1F6A8} Stunk: Unknown properties at '${r||"root"}': ${u.join(", ")}`),console.error("Expected keys:",a),console.error("Received keys:",n)),i){let s=a.filter(d=>!n.includes(d));s.length>0&&console.error(`\u{1F6A8} Stunk: Missing properties at '${r||"root"}': ${s.join(", ")}`);}for(let s of a){let d=e[s],y=t[s];d===void 0||y===void 0||y===null||(c&&typeof d!="object"&&typeof d!=typeof y&&console.error(`\u{1F6A8} Stunk: Type mismatch at '${r?r+".":""}${s}'. Expected ${typeof d}, got ${typeof y}.`),R(d,y,r?`${r}.${s}`:s,o));}}var q=new Set,w=new Map,z=0;function M(e,t={}){let r=z++,o=t.name||`chunk_${r}`,i=t.middleware||[],c=t.strict??false;if(e===void 0)throw new Error(`[${o}] Initial value cannot be undefined.`);let a=e!==null&&typeof e=="object"&&!Array.isArray(e)?new Set(Object.keys(e)):null,n=e,u=new Set,s=()=>{u.forEach(l=>l(n));};w.set(r,{notify:s});let d=()=>{if(u.size===0){w.delete(r);return}s();},y=()=>(n),k=()=>n,T=l=>{let P;if(typeof l=="function"?P=l(n):P=l,R(n,P),a&&P!==null&&typeof P=="object"&&!Array.isArray(P)){let x=Object.keys(P).filter(m=>!a.has(m));if(x.length>0){let m=`[${o}] Unexpected keys in set(): ${x.join(", ")}. These keys were not present in the initial shape.`;if(c)throw new Error(`\u{1F6A8} Stunk: ${m}`);console.error(`\u{1F6A8} Stunk: ${m}`);}}let h=_(P,i);h!==n&&(n=h,d());},g=l=>{if(typeof l!="function")throw new Error("Callback must be a function.");return u.add(l),()=>u.delete(l)},b={get:y,peek:k,set:T,subscribe:g,derive:l=>{if(typeof l!="function")throw new Error("Derive function must be a function.");let P=l(n),h=M(P),x=g(()=>{let f=l(n);h.set(f);}),m=h.destroy;return h.destroy=()=>{x(),m();},h},reset:()=>{n=e,d();},destroy:()=>{u.clear(),n=e,q.delete(r),w.delete(r);},[Symbol.for("stunk.meta")]:{name:o,id:r}};return b}function O(e,t,r={}){let{useShallowEqual:o=false}=r,i=e.get(),c=t(i),a=M(c),n=()=>{let k=e.get(),T=t(k);(o?!I(T,c):T!==c)&&(c=T,a.set(T));},u=e.subscribe(n),{set:s,reset:d,...y}=a;return {...y,derive:k=>O(a,k,r),destroy:()=>{u(),a.destroy();}}}function U(e,t){let r=t?O(e,t):e,[o,i]=react.useState(()=>r.get());react.useEffect(()=>{let u=r.subscribe(s=>{i(()=>s);});return ()=>u()},[r]);let c=react.useCallback(u=>{e.set(u);},[e]),a=react.useCallback(()=>{e.reset();},[e]),n=react.useCallback(()=>{e.destroy();},[e]);return [o,c,a,n]}function J(e,t){let[r]=U(e,t);return r}function v(e){return "nextPage"in e}function $(e){return "setParams"in e}function Z(e){return "clearParams"in e}function j(e,t={}){let{initialParams:r,fetchOnMount:o=false}=t,[i,c]=react.useState(()=>e.get()),a=react.useRef({initialParams:r,fetchOnMount:o});a.current={initialParams:r,fetchOnMount:o},react.useEffect(()=>{c(e.get());let f=e.subscribe(N=>{c(N);}),{initialParams:V,fetchOnMount:K}=a.current;return V&&$(e)?e.setParams(V):K&&e.reload(),()=>{f(),e.cleanup();}},[e]);let n=react.useCallback(f=>e.reload(f),[e]),u=react.useCallback(f=>e.refresh(f),[e]),s=react.useCallback(f=>e.mutate(f),[e]),d=react.useCallback(()=>e.reset(),[e]),y=react.useCallback(f=>{$(e)&&e.setParams(f);},[e]),k=react.useCallback(()=>{Z(e)&&e.clearParams();},[e]),T=react.useCallback(()=>v(e)?e.nextPage():Promise.resolve(),[e]),g=react.useCallback(()=>v(e)?e.prevPage():Promise.resolve(),[e]),E=react.useCallback(f=>v(e)?e.goToPage(f):Promise.resolve(),[e]),A=react.useCallback(()=>v(e)?e.resetPagination():Promise.resolve(),[e]),{data:C,loading:b,error:l,lastFetched:P,isPlaceholderData:h=false,pagination:x}=i,m={data:C,loading:b,error:l,lastFetched:P,isPlaceholderData:h,reload:n,refresh:u,mutate:s,reset:d};if($(e)&&(m.setParams=y,m.clearParams=k),v(e)){let f=m;f.pagination=x,f.nextPage=T,f.prevPage=g,f.goToPage=E,f.resetPagination=A;}return m}function re(e,t={}){let{initialParams:r,autoLoad:o=true,threshold:i=1,fetchOnMount:c}=t,a=j(e,{...r&&{initialParams:r},fetchOnMount:c}),{loading:n,pagination:u,nextPage:s,data:d,error:y,isPlaceholderData:k}=a,T=react.useRef(n),g=react.useRef(u?.hasMore??false),E=react.useRef(s);T.current=n,g.current=u?.hasMore??false,E.current=s;let A=react.useRef(null);react.useEffect(()=>{if(!o||typeof window>"u"||!("IntersectionObserver"in window))return;let l=new IntersectionObserver(h=>{h[0].isIntersecting&&!T.current&&g.current&&E.current();},{threshold:i}),P=A.current;return P&&l.observe(P),()=>{P&&l.unobserve(P),l.disconnect();}},[o,i]);let C=react.useCallback(()=>{!T.current&&g.current&&E.current();},[]),b=n&&d!==null&&d.length>0&&(u?.page??1)>1;return {...a,data:d,error:y,isPlaceholderData:k??false,isFetchingMore:b,hasMore:u?.hasMore??false,loadMore:C,observerTarget:A}}function oe(e){let[t,r]=react.useState(()=>e.get());react.useEffect(()=>(r(e.get()),e.subscribe(a=>{r(a);})),[e]);let o=react.useCallback((...c)=>e.mutate(...c),[e]),i=react.useCallback(()=>e.reset(),[e]);return {loading:t.loading,data:t.data,error:t.error,isSuccess:t.isSuccess,mutate:o,reset:i}}exports.useAsyncChunk=j;exports.useChunk=U;exports.useChunkValue=J;exports.useInfiniteAsyncChunk=re;exports.useMutation=oe;
|