@recats/cdeebee 3.0.0-beta.12 → 3.0.0-beta.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -40,14 +40,14 @@ After fetching data from the API (which returns data in the format `{ data: [...
40
40
 
41
41
  ```typescript
42
42
  {
43
- forumList: {
44
- 1: { id: 1, title: 'Milky Way Galaxy' }
43
+ forumList: {
44
+ 1: { id: 1, title: 'Milky Way Galaxy' }
45
45
  },
46
- threadList: {
47
- 10001: { id: 10001, title: 'Solar system', forumID: 1 }
46
+ threadList: {
47
+ 10001: { id: 10001, title: 'Solar system', forumID: 1 }
48
48
  },
49
- postList: {
50
- 2: { id: 2, title: 'Earth', threadID: 10001 }
49
+ postList: {
50
+ 2: { id: 2, title: 'Earth', threadID: 10001 }
51
51
  }
52
52
  }
53
53
  ```
@@ -171,6 +171,7 @@ function ForumsList() {
171
171
  - `useStorage()` - Get the entire storage
172
172
  - `useRequestHistory(api)` - Get successful request history for an API
173
173
  - `useRequestErrors(api)` - Get error history for an API
174
+ - `useLastResultIdList(api, listName)` - Get the IDs returned by the last request for a specific list (for filtering storage)
174
175
 
175
176
  See the [React Hooks](#react-hooks) section for detailed documentation.
176
177
 
@@ -186,8 +187,8 @@ interface CdeebeeSettings<T> {
186
187
  fileKey: string; // Key name for file uploads in FormData
187
188
  bodyKey: string; // Key name for request body in FormData
188
189
  listStrategy?: CdeebeeListStrategy<T>; // Merge strategy per list: 'merge' | 'replace' | 'skip'
189
- mergeWithData?: unknown; // Data to merge with every request body
190
- mergeWithHeaders?: Record<string, string>; // Headers to merge with every request
190
+ mergeWithData?: Record<string, unknown> | (() => Record<string, unknown>); // Data to merge with every request body (static or dynamic)
191
+ mergeWithHeaders?: Record<string, string> | (() => Record<string, string>); // Headers to merge with every request (static or dynamic)
191
192
  normalize?: (storage, result, strategyList) => T; // Custom normalization function
192
193
  }
193
194
  ```
@@ -228,6 +229,32 @@ listStrategy: {
228
229
  }
229
230
  ```
230
231
 
232
+ ## Dynamic Headers and Data
233
+
234
+ `mergeWithHeaders` and `mergeWithData` support both static objects and dynamic functions. Functions are called on each request, making them ideal for auth tokens:
235
+
236
+ ```typescript
237
+ const cdeebeeSlice = factory<Storage>({
238
+ modules: ['storage', 'history', 'listener'],
239
+
240
+ // Static headers (evaluated once at factory creation)
241
+ mergeWithHeaders: { 'X-App': 'myapp' },
242
+
243
+ // OR Dynamic headers (evaluated on each request)
244
+ mergeWithHeaders: () => ({
245
+ 'Authorization': `Bearer ${getSessionToken()}`,
246
+ }),
247
+
248
+ // Same for mergeWithData
249
+ mergeWithData: () => ({
250
+ timestamp: Date.now(),
251
+ clientVersion: APP_VERSION,
252
+ }),
253
+ });
254
+ ```
255
+
256
+ **Note**: When using functions, Redux will warn about non-serializable values in state. Configure your store's `serializableCheck.ignoredPaths` to include `cdeebee.settings.mergeWithHeaders` and `cdeebee.settings.mergeWithData`.
257
+
231
258
  ## API Response Format
232
259
 
233
260
  cdeebee expects API responses in a format where list data is provided as arrays with a `primaryKey` field. The library automatically normalizes this data into the storage structure.
@@ -621,6 +648,46 @@ function ErrorDisplay({ api }: { api: string }) {
621
648
  }
622
649
  ```
623
650
 
651
+ ### Result ID List Hook
652
+
653
+ #### `useLastResultIdList(api: string, listName: string)`
654
+
655
+ Get the list of IDs returned by the last successful request to an API for a specific list. This is useful for filtering storage data when using `merge` strategy, so you can display only the results from the current search/request.
656
+
657
+ ```typescript
658
+ import { useStorageList, useLastResultIdList } from '@recats/cdeebee';
659
+
660
+ interface MyStorage {
661
+ productList: Record<string, { id: string; name: string; price: number }>;
662
+ }
663
+
664
+ function SearchResults() {
665
+ // Get all products from storage (accumulated via merge strategy)
666
+ const products = useStorageList<MyStorage, 'productList'>('productList');
667
+
668
+ // Get only the IDs from the last search request for productList
669
+ const lastSearchIDList = useLastResultIdList('/api/search', 'productList');
670
+
671
+ // Filter to show only results from current search
672
+ const displayResults = lastSearchIDList
673
+ .map(id => products[id])
674
+ .filter(Boolean);
675
+
676
+ return (
677
+ <div>
678
+ {displayResults.map(product => (
679
+ <div key={product.id}>{product.name} - ${product.price}</div>
680
+ ))}
681
+ </div>
682
+ );
683
+ }
684
+ ```
685
+
686
+ **Why use this?** When using `replace` strategy with search/filter pages, navigating away and using browser back loses the previous results. With `merge` strategy + `useLastResultIdList`:
687
+ - Data accumulates in storage (never lost on navigation)
688
+ - `lastResultIdList[api][listName]` tracks which IDs belong to the current request per list
689
+ - Filter storage by those IDs to display the correct results
690
+
624
691
  ### Advanced: Custom State Path
625
692
 
626
693
  If you're **not** using `combineSlices` or have cdeebee at a custom path in your state (not `state.cdeebee`), use `createCdeebeeHooks`:
@@ -638,6 +705,7 @@ export const {
638
705
  useRequestHistory,
639
706
  useRequestErrors,
640
707
  useIsLoading,
708
+ useLastResultIdList,
641
709
  } = createCdeebeeHooks<RootState, MyStorage>(
642
710
  state => state.myCustomPath // Your custom path
643
711
  );
@@ -669,6 +737,7 @@ const users = useSelector(state => state.cdeebee.storage.userList);
669
737
  export { factory } from '@recats/cdeebee'; // Create cdeebee slice
670
738
  export { request } from '@recats/cdeebee'; // Request thunk
671
739
  export { batchingUpdate } from '@recats/cdeebee'; // Batch update helper
740
+ export { defaultNormalize } from '@recats/cdeebee'; // Default normalization function
672
741
 
673
742
  // React hooks
674
743
  export {
@@ -679,6 +748,7 @@ export {
679
748
  useStorage, // Get entire storage
680
749
  useRequestHistory, // Get successful request history
681
750
  useRequestErrors, // Get error history
751
+ useLastResultIdList, // Get IDs from last request for a list (for filtering storage)
682
752
  } from '@recats/cdeebee';
683
753
 
684
754
  // Types
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("@reduxjs/toolkit"),d=require("react-redux");function f(e,r,s){e.modules.includes(r)&&s()}function y(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function p(e,r){if(!y(e)||!y(r))return r;const s={...e},o=r;for(const t in o)if(Object.prototype.hasOwnProperty.call(o,t)){const u=s[t],i=o[t];y(u)&&y(i)&&!Array.isArray(u)&&!Array.isArray(i)?s[t]=p(u,i):s[t]=i}return s}function C(e,r){const s={...r};for(const o of e)delete s[o];return s}function D(e,r){for(let s=0;s<r.length;s++){const o=r[s],t=o.key,u=o.value;if(t.length===0)continue;let i=e;for(let n=0;n<t.length-1;n++){const c=t[n];if(Array.isArray(i)){const a=typeof c=="number"?c:Number(c);(!(a in i)||!y(i[a]))&&(i[a]={}),i=i[a]}else{const a=String(c);if(!(a in i)){const g=typeof t[n+1]=="number"||!isNaN(Number(t[n+1]))&&String(Number(t[n+1]))===String(t[n+1]);i[a]=g?[]:{}}const l=i[a];i=Array.isArray(l)||y(l)?l:{}}}Array.isArray(i)||(i[String(t[t.length-1])]=u)}}class E{constructor(){this.byRequestId=new Map,this.byApi=new Map}add(r,s,o){const t={requestId:s,controller:o,api:r};this.byRequestId.set(s,t),this.byApi.has(r)||this.byApi.set(r,new Set),this.byApi.get(r).add(s)}delete(r){const s=this.byRequestId.get(r);if(!s)return;this.byRequestId.delete(r);const o=this.byApi.get(s.api);o&&(o.delete(r),o.size===0&&this.byApi.delete(s.api))}abortAllForApi(r,s){const o=this.byApi.get(r);o&&o.forEach(t=>{if(t!==s){const u=this.byRequestId.get(t);u&&(u.controller.abort(),this.delete(t))}})}}const k=new E;function H(e,r){k.abortAllForApi(e,r)}function T(e,r,s){const o=new AbortController,t=()=>{k.delete(s)};return e.addEventListener("abort",()=>{o.abort(),t()}),{controller:o,init:()=>k.add(r,s,o),drop:t}}class x{constructor(){this.currentPromise=Promise.resolve(),this.queueLength=0}async enqueue(r){this.queueLength++;const s=this.currentPromise;return this.currentPromise=s.then(()=>r(),()=>r()).finally(()=>{this.queueLength--}),this.currentPromise}getQueueLength(){return this.queueLength}clear(){this.queueLength=0}}const N=new x,m=R.createAsyncThunk("cdeebee/request",async(e,{rejectWithValue:r,getState:s,requestId:o,signal:t})=>{const u=new Date().toUTCString(),{cdeebee:{settings:i}}=s(),n=T(t,e.api,o),c=e.onResult&&typeof e.onResult=="function";f(i,"cancelation",n.init);const a=async()=>{try{const{method:l="POST",body:g,headers:I={}}=e,P={...i.mergeWithHeaders??{},...I},z={...i.mergeWithData??{},...g??{}};let q=JSON.stringify(z);if(e.files){const S=new FormData,w=e.fileKey||i.fileKey,v=e.bodyKey||i.bodyKey;for(let A=0;A<e.files.length;A+=1)w&&S.append(w,e.files[A]);v&&S.append(v,q),q=S}const h=await fetch(e.api,{method:l,headers:{"ui-request-id":o,"Content-Type":"application/json",...P},signal:n.controller.signal,body:q});f(i,"cancelation",n.drop);let b;const L=e.responseType||"json";return L==="text"?b=await h.text():L==="blob"?b=await h.blob():b=await h.json(),h.ok?(c&&e.onResult(b),{result:b,startedAt:u,endedAt:new Date().toUTCString()}):(c&&e.onResult(b),r(h))}catch(l){return f(i,"cancelation",n.drop),c&&e.onResult(l),l instanceof Error&&l.name==="AbortError"?r({message:"Request was cancelled",cancelled:!0}):r({message:l instanceof Error?l.message:"Unknown error occurred"})}};return i.modules.includes("queryQueue")?N.enqueue(a):a()});function j(e){return y(e)&&Array.isArray(e.data)&&typeof e.primaryKey=="string"}function O(e,r){const s={};for(const o of e)if(y(o)&&r in o){const t=String(o[r]);s[t]=o}return s}function K(e,r,s,o){return s==="replace"?r:s==="merge"?p(e,r):s==="skip"?e:(console.warn(`Cdeebee: Unknown strategy "${s}" for key "${o}". Skipping normalization.`),p(e,r))}function Q(e,r,s){const o=Object.keys(r),t=y(e.storage)?e.storage:{},u={...t},i=new Set;for(const n of o){const c=r[n];if(c==null||typeof c=="string"){i.add(n);continue}const a=s[n]??"merge";if(a==="skip"&&!(n in t))continue;const l=n in t?t[n]:{};if(j(c)){const g=O(c.data,c.primaryKey);u[n]=K(l,g,a,n);continue}y(c)?u[n]=K(l,c,a,n):u[n]=c}return i.size>0?C(Array.from(i),u):u}const U={settings:{modules:["history","listener","storage","cancelation"],fileKey:"file",bodyKey:"value",listStrategy:{},mergeWithData:{},mergeWithHeaders:{}},storage:{},request:{active:[],errors:{},done:{}}},M=(e,r)=>R.createSlice({name:"cdeebee",initialState:p(U,{settings:e,storage:r??{}}),reducers:{set(o,t){D(o.storage,t.payload)},historyClear(o,t){const u=t.payload;u?(delete o.request.done[u],delete o.request.errors[u]):(o.request.done={},o.request.errors={})}},extraReducers:o=>{o.addCase(m.pending,(t,u)=>{const i=u.meta.arg.api,n=u.meta.requestId;u.meta.arg.historyClear&&f(t.settings,"history",()=>{delete t.request.done[i],delete t.request.errors[i]}),f(t.settings,"cancelation",()=>{H(i,n)}),f(t.settings,"listener",()=>{t.request.active.push({api:i,requestId:n})})}).addCase(m.fulfilled,(t,u)=>{const i=u.meta.requestId,n=u.meta.arg.api;f(t.settings,"listener",()=>{t.request.active=t.request.active.filter(c=>!(c.api===n&&c.requestId===i))}),f(t.settings,"history",()=>{t.request.done[n]||(t.request.done[n]=[]),t.request.done[n].push({api:n,request:u.payload,requestId:i})}),f(t.settings,"storage",()=>{if(u.meta.arg.ignore)return;const c=u.meta.arg.listStrategy??t.settings.listStrategy??{},a=u.meta.arg.normalize??t.settings.normalize??Q,l=R.current(t),g=a(l,u.payload.result,c);t.storage=g})}).addCase(m.rejected,(t,u)=>{const i=u.meta.requestId,n=u.meta.arg.api;f(t.settings,"listener",()=>{t.request.active=t.request.active.filter(c=>!(c.api===n&&c.requestId===i))}),f(t.settings,"history",()=>{t.request.errors[n]||(t.request.errors[n]=[]),t.request.errors[n].push({requestId:i,api:n,request:u.error})})})}});function W(e){function r(n){return d.useSelector(c=>e(c).request.active.some(l=>n.includes(l.api)))}function s(n){return d.useSelector(c=>e(c).request.done[n]??[])}function o(n){return d.useSelector(c=>e(c).request.errors[n]??[])}function t(n){return d.useSelector(c=>e(c).storage[n])}function u(){return d.useSelector(n=>e(n).storage)}function i(){return d.useSelector(n=>e(n).request.active.length>0)}return{useLoading:r,useRequestHistory:s,useRequestErrors:o,useStorageList:t,useStorage:u,useIsLoading:i}}function F(e){return d.useSelector(r=>r.cdeebee.request.active.some(s=>e.includes(s.api)))}function $(e){return d.useSelector(r=>r.cdeebee.request.done[e]??[])}function J(e){return d.useSelector(r=>r.cdeebee.request.errors[e]??[])}function B(e){return d.useSelector(r=>r.cdeebee.storage[e])}function G(){return d.useSelector(e=>e.cdeebee.storage)}function X(){return d.useSelector(e=>e.cdeebee.request.active.length>0)}exports.batchingUpdate=D;exports.createCdeebeeHooks=W;exports.factory=M;exports.request=m;exports.useIsLoading=X;exports.useLoading=F;exports.useRequestErrors=J;exports.useRequestHistory=$;exports.useStorage=G;exports.useStorageList=B;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("@reduxjs/toolkit"),d=require("react-redux");function y(e,r,o){e.modules.includes(r)&&o()}function f(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function q(e,r){if(!f(e)||!f(r))return r;const o={...e},s=r;for(const t in s)if(Object.prototype.hasOwnProperty.call(s,t)){const i=o[t],n=s[t];f(i)&&f(n)&&!Array.isArray(i)&&!Array.isArray(n)?o[t]=q(i,n):o[t]=n}return o}function N(e,r){const o={...r};for(const s of e)delete o[s];return o}function x(e){if(!f(e))return{};const r={};for(const o of Object.keys(e)){const s=e[o];if(f(s)&&Array.isArray(s.data)&&typeof s.primaryKey=="string"){const t=s.primaryKey,i=[];for(const n of s.data)f(n)&&t in n&&i.push(String(n[t]));r[o]=i}}return r}function v(e,r){for(let o=0;o<r.length;o++){const s=r[o],t=s.key,i=s.value;if(t.length===0)continue;let n=e;for(let u=0;u<t.length-1;u++){const a=t[u];if(Array.isArray(n)){const c=typeof a=="number"?a:Number(a);(!(c in n)||!f(n[c]))&&(n[c]={}),n=n[c]}else{const c=String(a);if(!(c in n)){const g=typeof t[u+1]=="number"||!isNaN(Number(t[u+1]))&&String(Number(t[u+1]))===String(t[u+1]);n[c]=g?[]:{}}const l=n[c];n=Array.isArray(l)||f(l)?l:{}}}Array.isArray(n)||(n[String(t[t.length-1])]=i)}}class T{constructor(){this.byRequestId=new Map,this.byApi=new Map}add(r,o,s){const t={requestId:o,controller:s,api:r};this.byRequestId.set(o,t),this.byApi.has(r)||this.byApi.set(r,new Set),this.byApi.get(r).add(o)}delete(r){const o=this.byRequestId.get(r);if(!o)return;this.byRequestId.delete(r);const s=this.byApi.get(o.api);s&&(s.delete(r),s.size===0&&this.byApi.delete(o.api))}abortAllForApi(r,o){const s=this.byApi.get(r);s&&s.forEach(t=>{if(t!==o){const i=this.byRequestId.get(t);i&&(i.controller.abort(),this.delete(t))}})}}const k=new T;function j(e,r){k.abortAllForApi(e,r)}function C(e,r,o){const s=new AbortController,t=()=>{k.delete(o)};return e.addEventListener("abort",()=>{s.abort(),t()}),{controller:s,init:()=>k.add(r,o,s),drop:t}}class E{constructor(){this.currentPromise=Promise.resolve(),this.queueLength=0}async enqueue(r){this.queueLength++;const o=this.currentPromise;return this.currentPromise=o.then(()=>r(),()=>r()).finally(()=>{this.queueLength--}),this.currentPromise}getQueueLength(){return this.queueLength}clear(){this.queueLength=0}}const O=new E,p=R.createAsyncThunk("cdeebee/request",async(e,{rejectWithValue:r,getState:o,requestId:s,signal:t})=>{const i=new Date().toUTCString(),{cdeebee:{settings:n}}=o(),u=C(t,e.api,s),a=e.onResult&&typeof e.onResult=="function";y(n,"cancelation",u.init);const c=async()=>{try{const{method:l="POST",body:g,headers:h={}}=e,z={...typeof n.mergeWithHeaders=="function"?n.mergeWithHeaders():n.mergeWithHeaders??{},...h},P={...typeof n.mergeWithData=="function"?n.mergeWithData():n.mergeWithData??{},...g??{}};let S=JSON.stringify(P);if(e.files){const A=new FormData,I=e.fileKey||n.fileKey,D=e.bodyKey||n.bodyKey;for(let L=0;L<e.files.length;L+=1)I&&A.append(I,e.files[L]);D&&A.append(D,S),S=A}const m=await fetch(e.api,{method:l,headers:{"ui-request-id":s,"Content-Type":"application/json",...z},signal:u.controller.signal,body:S});y(n,"cancelation",u.drop);let b;const w=e.responseType||"json";return w==="text"?b=await m.text():w==="blob"?b=await m.blob():b=await m.json(),m.ok?(a&&e.onResult(b),{result:b,startedAt:i,endedAt:new Date().toUTCString()}):(a&&e.onResult(b),r(m))}catch(l){return y(n,"cancelation",u.drop),a&&e.onResult(l),l instanceof Error&&l.name==="AbortError"?r({message:"Request was cancelled",cancelled:!0}):r({message:l instanceof Error?l.message:"Unknown error occurred"})}};return n.modules.includes("queryQueue")?O.enqueue(c):c()});function W(e){return f(e)&&Array.isArray(e.data)&&typeof e.primaryKey=="string"}function Q(e,r){const o={};for(const s of e)if(f(s)&&r in s){const t=String(s[r]);o[t]=s}return o}function K(e,r,o,s){return o==="replace"?r:o==="merge"?q(e,r):o==="skip"?e:(console.warn(`Cdeebee: Unknown strategy "${o}" for key "${s}". Skipping normalization.`),q(e,r))}function H(e,r,o){const s=Object.keys(r),t=f(e.storage)?e.storage:{},i={...t},n=new Set;for(const u of s){const a=r[u];if(a==null||typeof a=="string"){n.add(u);continue}const c=o[u]??"merge";if(c==="skip"&&!(u in t))continue;const l=u in t?t[u]:{};if(W(a)){const g=Q(a.data,a.primaryKey);i[u]=K(l,g,c,u);continue}f(a)?i[u]=K(l,a,c,u):i[u]=a}return n.size>0?N(Array.from(n),i):i}const U={settings:{modules:["history","listener","storage","cancelation"],fileKey:"file",bodyKey:"value",listStrategy:{},mergeWithData:{},mergeWithHeaders:{}},storage:{},request:{active:[],errors:{},done:{},lastResultIdList:{}}},M=(e,r)=>R.createSlice({name:"cdeebee",initialState:q(U,{settings:e,storage:r??{}}),reducers:{set(s,t){v(s.storage,t.payload)},historyClear(s,t){const i=t.payload;i?(delete s.request.done[i],delete s.request.errors[i]):(s.request.done={},s.request.errors={})}},extraReducers:s=>{s.addCase(p.pending,(t,i)=>{const n=i.meta.arg.api,u=i.meta.requestId;i.meta.arg.historyClear&&y(t.settings,"history",()=>{delete t.request.done[n],delete t.request.errors[n]}),y(t.settings,"cancelation",()=>{j(n,u)}),y(t.settings,"listener",()=>{t.request.active.push({api:n,requestId:u})})}).addCase(p.fulfilled,(t,i)=>{const n=i.meta.requestId,u=i.meta.arg.api;y(t.settings,"listener",()=>{t.request.active=t.request.active.filter(a=>!(a.api===u&&a.requestId===n))}),y(t.settings,"history",()=>{t.request.done[u]||(t.request.done[u]=[]),t.request.done[u].push({api:u,request:i.payload,requestId:n})}),y(t.settings,"storage",()=>{if(i.meta.arg.ignore)return;const a=i.meta.arg.listStrategy??t.settings.listStrategy??{},c=i.meta.arg.normalize??t.settings.normalize??H,l=R.current(t),g=c(l,i.payload.result,a);t.storage=g,t.request.lastResultIdList[u]=x(i.payload.result)})}).addCase(p.rejected,(t,i)=>{const n=i.meta.requestId,u=i.meta.arg.api;y(t.settings,"listener",()=>{t.request.active=t.request.active.filter(a=>!(a.api===u&&a.requestId===n))}),y(t.settings,"history",()=>{t.request.errors[u]||(t.request.errors[u]=[]),t.request.errors[u].push({requestId:n,api:u,request:i.error})})})}});function F(e){function r(a){return d.useSelector(c=>e(c).request.active.some(g=>a.includes(g.api)))}function o(a){return d.useSelector(c=>e(c).request.done[a]??[])}function s(a){return d.useSelector(c=>e(c).request.errors[a]??[])}function t(a){return d.useSelector(c=>e(c).storage[a])}function i(){return d.useSelector(a=>e(a).storage)}function n(){return d.useSelector(a=>e(a).request.active.length>0)}function u(a,c){return d.useSelector(l=>{var h;return((h=e(l).request.lastResultIdList[a])==null?void 0:h[c])??[]})}return{useLoading:r,useRequestHistory:o,useRequestErrors:s,useStorageList:t,useStorage:i,useIsLoading:n,useLastResultIdList:u}}function $(e){return d.useSelector(r=>r.cdeebee.request.active.some(o=>e.includes(o.api)))}function J(e){return d.useSelector(r=>r.cdeebee.request.done[e]??[])}function B(e){return d.useSelector(r=>r.cdeebee.request.errors[e]??[])}function G(e){return d.useSelector(r=>r.cdeebee.storage[e])}function X(){return d.useSelector(e=>e.cdeebee.storage)}function Y(){return d.useSelector(e=>e.cdeebee.request.active.length>0)}function Z(e,r){return d.useSelector(o=>{var s;return((s=o.cdeebee.request.lastResultIdList[e])==null?void 0:s[r])??[]})}exports.batchingUpdate=v;exports.createCdeebeeHooks=F;exports.defaultNormalize=H;exports.factory=M;exports.request=p;exports.useIsLoading=Y;exports.useLastResultIdList=Z;exports.useLoading=$;exports.useRequestErrors=B;exports.useRequestHistory=J;exports.useStorage=X;exports.useStorageList=G;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../lib/reducer/helpers.ts","../lib/reducer/abortController.ts","../lib/reducer/queryQueue.ts","../lib/reducer/request.ts","../lib/reducer/storage.ts","../lib/reducer/index.ts","../lib/hooks.ts"],"sourcesContent":["import { type WritableDraft } from '@reduxjs/toolkit';\nimport { type CdeebeeSettings, type CdeebeeModule, CdeebeeValueList } from './types';\n\nexport function checkModule(settings: CdeebeeSettings<unknown> | WritableDraft<CdeebeeSettings<unknown>>, module: CdeebeeModule, result: () => void) {\n if (settings.modules.includes(module)) {\n result();\n }\n}\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function hasDataProperty(value: unknown): value is Record<string, unknown> & { data: unknown[] } {\n return isRecord(value) && Array.isArray(value.data);\n}\n\nexport function hasProperty(value: unknown, prop: string): boolean {\n return isRecord(value) && Object.prototype.hasOwnProperty.call(value, prop);\n}\n\nexport function mergeDeepRight<T>(\n left: T,\n right: Partial<T> | Record<string, unknown>\n): T {\n if (!isRecord(left) || !isRecord(right)) {\n return right as T;\n }\n\n const result = { ...left } as Record<string, unknown>;\n const rightRecord = right as Record<string, unknown>;\n\n for (const key in rightRecord) {\n if (Object.prototype.hasOwnProperty.call(rightRecord, key)) {\n const leftValue = result[key];\n const rightValue = rightRecord[key];\n\n if (\n isRecord(leftValue) &&\n isRecord(rightValue) &&\n !Array.isArray(leftValue) &&\n !Array.isArray(rightValue)\n ) {\n result[key] = mergeDeepRight(leftValue, rightValue);\n } else {\n result[key] = rightValue;\n }\n }\n }\n\n return result as T;\n}\n\nexport function omit<T extends Record<string, unknown>>(keys: string[], obj: T): Omit<T, keyof T> {\n const result = { ...obj };\n for (const key of keys) {\n delete result[key];\n }\n return result as Omit<T, keyof T>;\n}\n\nexport function assocPath<T>(path: (string | number)[], value: unknown, obj: T): T {\n if (path.length === 0) {\n return value as T;\n }\n\n const [first, ...rest] = path;\n const firstKey = String(first);\n const result = Array.isArray(obj) ? [...obj] : { ...obj } as Record<string, unknown>;\n\n if (rest.length === 0) {\n (result as Record<string, unknown>)[firstKey] = value;\n } else {\n const currentValue = (result as Record<string, unknown>)[firstKey];\n (result as Record<string, unknown>)[firstKey] = assocPath(rest, value, currentValue ?? {});\n }\n\n return result as T;\n}\n\nexport function batchingUpdate<T extends Record<string, unknown>>(\n state: T,\n valueList: CdeebeeValueList<T>\n): void {\n for (let i = 0; i < valueList.length; i++) {\n const item = valueList[i] as { key: readonly (string | number)[]; value: unknown };\n const path = item.key;\n const value = item.value;\n \n if (path.length === 0) {\n continue;\n }\n\n let current: Record<string, unknown> | unknown[] = state as Record<string, unknown>;\n \n for (let j = 0; j < path.length - 1; j++) {\n const pathKey = path[j];\n \n if (Array.isArray(current)) {\n const index = typeof pathKey === 'number' ? pathKey : Number(pathKey);\n if (!(index in current) || !isRecord(current[index])) {\n current[index] = {};\n }\n current = current[index] as Record<string, unknown>;\n } else {\n const key = String(pathKey);\n if (!(key in current)) {\n const nextIsNumeric = typeof path[j + 1] === 'number' || (!isNaN(Number(path[j + 1])) && String(Number(path[j + 1])) === String(path[j + 1]));\n current[key] = nextIsNumeric ? [] : {};\n }\n const next = current[key];\n current = (Array.isArray(next) ? next : (isRecord(next) ? next : {})) as Record<string, unknown> | unknown[];\n }\n }\n \n if (Array.isArray(current)) {\n continue; // Can't update array element directly\n }\n current[String(path[path.length - 1])] = value;\n }\n}\n","interface RequestController {\n requestId: string;\n controller: AbortController;\n api: string;\n}\n\nclass AbortControllerStore {\n private byRequestId = new Map<string, RequestController>();\n private byApi = new Map<string, Set<string>>();\n\n add(api: string, requestId: string, controller: AbortController): void {\n const item: RequestController = { requestId, controller, api };\n this.byRequestId.set(requestId, item);\n\n if (!this.byApi.has(api)) {\n this.byApi.set(api, new Set());\n }\n this.byApi.get(api)!.add(requestId);\n }\n\n delete(requestId: string): void {\n const item = this.byRequestId.get(requestId);\n if (!item) return;\n\n this.byRequestId.delete(requestId);\n const apiSet = this.byApi.get(item.api);\n if (apiSet) {\n apiSet.delete(requestId);\n if (apiSet.size === 0) {\n this.byApi.delete(item.api);\n }\n }\n }\n\n abortAllForApi(api: string, excludeRequestId: string): void {\n const requestIds = this.byApi.get(api);\n if (!requestIds) return;\n\n requestIds.forEach(requestId => {\n if (requestId !== excludeRequestId) {\n const item = this.byRequestId.get(requestId);\n if (item) {\n item.controller.abort();\n this.delete(requestId);\n }\n }\n });\n }\n}\n\nconst abortStore = new AbortControllerStore();\n\nexport function abortQuery(api: string, currentRequestId: string): void {\n abortStore.abortAllForApi(api, currentRequestId);\n}\n\nexport function abortManager(signal: AbortSignal, api: string, requestId: string) {\n const controller = new AbortController();\n\n const cleanup = () => {\n abortStore.delete(requestId);\n };\n\n signal.addEventListener('abort', () => {\n controller.abort();\n cleanup();\n });\n\n return {\n controller,\n init: () => abortStore.add(api, requestId, controller),\n drop: cleanup,\n };\n}\n","class QueryQueue {\n private currentPromise: Promise<unknown> = Promise.resolve();\n private queueLength = 0;\n\n async enqueue<T>(task: () => Promise<T>): Promise<T> {\n this.queueLength++;\n \n const previousPromise = this.currentPromise;\n \n this.currentPromise = previousPromise\n .then(() => task(), () => task())\n .finally(() => {\n this.queueLength--;\n });\n\n return this.currentPromise as Promise<T>;\n }\n\n getQueueLength(): number {\n return this.queueLength;\n }\n\n clear(): void {\n this.queueLength = 0;\n }\n}\n\nexport const queryQueue = new QueryQueue();\n\n","import { createAsyncThunk } from '@reduxjs/toolkit';\nimport { checkModule } from './helpers';\nimport { abortManager } from './abortController';\nimport { queryQueue } from './queryQueue';\nimport { type CdeebeeState, type CdeebeeRequestOptions } from './types';\n\nexport const request = createAsyncThunk(\n 'cdeebee/request',\n async (options: CdeebeeRequestOptions<unknown>, { rejectWithValue, getState, requestId, signal }) => {\n const startedAt = new Date().toUTCString();\n const { cdeebee: { settings } } = getState() as { cdeebee: CdeebeeState<unknown> };\n\n const abort = abortManager(signal, options.api, requestId);\n const withCallback = options.onResult && typeof options.onResult === 'function';\n\n checkModule(settings, 'cancelation', abort.init);\n\n const executeRequest = async () => {\n try {\n const { method = 'POST', body, headers = {} } = options;\n const extraHeaders: Record<string, string> = { ...(settings.mergeWithHeaders ?? {}), ...headers };\n\n const b = { ...(settings.mergeWithData ?? {}), ...(body ?? {}) };\n let requestData: FormData | string = JSON.stringify(b);\n\n // handling files\n if (options.files) {\n const formData = new FormData();\n const fileKey = options.fileKey || settings.fileKey;\n const bodyKey = options.bodyKey || settings.bodyKey;\n\n for (let i = 0; i < options.files.length; i += 1) {\n if (fileKey) {\n formData.append(fileKey, options.files[i]);\n }\n }\n\n if (bodyKey) {\n formData.append(bodyKey, requestData);\n }\n requestData = formData;\n }\n // [end] handling files\n \n const response = await fetch(options.api, {\n method,\n headers: {\n 'ui-request-id': requestId,\n 'Content-Type': 'application/json',\n ...extraHeaders,\n },\n signal: abort.controller.signal,\n body: requestData,\n });\n\n checkModule(settings, 'cancelation', abort.drop);\n\n let result: unknown;\n const responseType = options.responseType || 'json';\n \n if (responseType === 'text') {\n result = await response.text();\n } else if (responseType === 'blob') {\n result = await response.blob();\n } else {\n // default: json\n result = await response.json();\n }\n\n if (!response.ok) {\n if (withCallback) options.onResult!(result);\n return rejectWithValue(response);\n }\n\n if (withCallback) options.onResult!(result);\n return { result, startedAt, endedAt: new Date().toUTCString() };\n } catch (error) {\n checkModule(settings, 'cancelation', abort.drop);\n\n if (withCallback) options.onResult!(error); \n\n if (error instanceof Error && error.name === 'AbortError') {\n return rejectWithValue({ message: 'Request was cancelled', cancelled: true });\n }\n\n return rejectWithValue({ message: error instanceof Error ? error.message : 'Unknown error occurred' });\n }\n };\n\n if (settings.modules.includes('queryQueue')) {\n return queryQueue.enqueue(executeRequest);\n }\n\n return executeRequest();\n },\n);\n\n","import { type CdeebeeListStrategy, type CdeebeeState } from './types';\nimport { isRecord, mergeDeepRight, omit } from './helpers';\n\ntype ResponseValue = Record<string, unknown>;\n\ntype IResponse = Record<string, ResponseValue>;\n\ntype StorageData = Record<string, unknown>;\n\nfunction isDataWithPrimaryKey(value: unknown): value is { data: unknown[]; primaryKey: string } {\n return (\n isRecord(value) &&\n Array.isArray(value.data) &&\n typeof value.primaryKey === 'string'\n );\n}\nfunction normalizeDataWithPrimaryKey(data: unknown[], primaryKey: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n \n for (const item of data) {\n if (isRecord(item) && primaryKey in item) {\n const key = String(item[primaryKey]);\n result[key] = item;\n }\n }\n \n return result;\n}\n\nfunction applyStrategy(\n existingValue: StorageData,\n newValue: StorageData | ResponseValue,\n strategy: string,\n key: string\n): ResponseValue {\n if (strategy === 'replace') {\n return newValue as ResponseValue;\n } else if (strategy === 'merge') {\n return mergeDeepRight(existingValue, newValue as StorageData) as ResponseValue;\n } else if (strategy === 'skip') {\n return existingValue as ResponseValue;\n } else {\n console.warn(`Cdeebee: Unknown strategy \"${strategy}\" for key \"${key}\". Skipping normalization.`);\n return mergeDeepRight(existingValue, newValue as StorageData) as ResponseValue;\n }\n}\n\nexport function defaultNormalize<T>(\n cdeebee: CdeebeeState<T>,\n response: IResponse,\n strategyList: CdeebeeListStrategy<T> \n): Record<string, ResponseValue> {\n const keyList = Object.keys(response);\n const currentStorage = isRecord(cdeebee.storage) ? (cdeebee.storage as Record<string, unknown>) : {};\n \n const result = { ...currentStorage } as Record<string, ResponseValue>;\n const keyListToOmit = new Set<string>();\n\n for (const key of keyList) {\n const responseValue = response[key];\n\n if (responseValue === null || responseValue === undefined || typeof responseValue === 'string') {\n keyListToOmit.add(key);\n continue;\n }\n\n const strategy = strategyList[key as keyof T] ?? 'merge';\n \n // For 'skip' strategy, if key doesn't exist in storage, skip it entirely\n if (strategy === 'skip' && !(key in currentStorage)) {\n continue;\n }\n \n const existingValue = key in currentStorage ? (currentStorage[key] as StorageData) : {};\n\n if (isDataWithPrimaryKey(responseValue)) {\n const normalizedValue = normalizeDataWithPrimaryKey(responseValue.data, responseValue.primaryKey);\n result[key] = applyStrategy(existingValue, normalizedValue, strategy, key);\n continue;\n }\n\n if (isRecord(responseValue)) {\n result[key] = applyStrategy(existingValue, responseValue as StorageData, strategy, key);\n } else {\n result[key] = responseValue;\n }\n }\n\n return keyListToOmit.size > 0 ? omit(Array.from(keyListToOmit), result) : result;\n}\n","import { createSlice, current, type PayloadAction } from '@reduxjs/toolkit';\n\nimport { type CdeebeeSettings, type CdeebeeState, type CdeebeeValueList, type CdeebeeListStrategy } from './types';\nimport { checkModule, mergeDeepRight, batchingUpdate } from './helpers';\nimport { abortQuery } from './abortController';\nimport { request } from './request';\nimport { defaultNormalize } from './storage';\n\nconst initialState: CdeebeeState<unknown> = {\n settings: {\n modules: ['history', 'listener', 'storage', 'cancelation'],\n fileKey: 'file',\n bodyKey: 'value',\n listStrategy: {},\n mergeWithData: {},\n mergeWithHeaders: {},\n },\n storage: {},\n request: {\n active: [],\n errors: {},\n done: {}\n },\n};\n\nexport const factory = <T>(settings: CdeebeeSettings<T>, storage?: T) => {\n const slice = createSlice({\n name: 'cdeebee',\n initialState: mergeDeepRight(initialState, { settings, storage: storage ?? {} }) as CdeebeeState<T>,\n reducers: {\n set(state, action: { payload: CdeebeeValueList<T> }) {\n // Directly mutate state.storage using Immer Draft\n // This is more performant than creating a new object\n // Immer will track changes and create minimal updates\n batchingUpdate(state.storage as Record<string, unknown>, action.payload);\n },\n historyClear(state, action: PayloadAction<string | undefined>) {\n const api = action.payload;\n\n if (api) {\n delete state.request.done[api];\n delete state.request.errors[api];\n } else {\n state.request.done = {};\n state.request.errors = {};\n }\n }\n },\n extraReducers: builder => {\n builder\n .addCase(request.pending, (state, action) => {\n const api = action.meta.arg.api;\n const requestId = action.meta.requestId;\n\n if (action.meta.arg.historyClear) {\n checkModule(state.settings, 'history', () => {\n delete state.request.done[api];\n delete state.request.errors[api];\n });\n }\n\n checkModule(state.settings, 'cancelation', () => {\n abortQuery(api, requestId);\n });\n checkModule(state.settings, 'listener', () => {\n state.request.active.push({ api, requestId });\n });\n })\n .addCase(request.fulfilled, (state, action) => {\n const requestId = action.meta.requestId;\n const api = action.meta.arg.api;\n\n checkModule(state.settings, 'listener', () => {\n state.request.active = state.request.active.filter(q => !(q.api === api && q.requestId === requestId));\n });\n checkModule(state.settings, 'history', () => {\n if (!state.request.done[api]) state.request.done[api] = [];\n state.request.done[api].push({ api, request: action.payload, requestId });\n });\n checkModule(state.settings, 'storage', () => {\n if (action.meta.arg.ignore) {\n return;\n }\n \n const strategyList = (action.meta.arg.listStrategy ?? state.settings.listStrategy ?? {}) as CdeebeeListStrategy<T>;\n const normalize = action.meta.arg.normalize ?? state.settings.normalize ?? defaultNormalize;\n\n const currentState = current(state) as CdeebeeState<T>;\n // Type assertion is safe here because we've already checked isRecord\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const normalizedData = normalize(currentState, action.payload.result as any, strategyList);\n\n // Normalize already handles merge/replace/skip and preserves keys not in response\n // Simply apply the result\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (state.storage as any) = normalizedData;\n });\n })\n .addCase(request.rejected, (state, action) => {\n const requestId = action.meta.requestId;\n const api = action.meta.arg.api;\n\n checkModule(state.settings, 'listener', () => {\n state.request.active = state.request.active.filter(q => !(q.api === api && q.requestId === requestId));\n });\n checkModule(state.settings, 'history', () => {\n if (!state.request.errors[api]) state.request.errors[api] = [];\n state.request.errors[api].push({ requestId: requestId, api, request: action.error });\n });\n });\n },\n });\n\n return slice;\n};\n","import { useSelector } from 'react-redux';\nimport { type CdeebeeState } from './reducer/types';\n\n/**\n * Generic hook factory that creates a selector hook for cdeebee state.\n * This allows the hooks to work with any Redux root state structure.\n *\n * @template RootState - The shape of the Redux root state\n * @template Storage - The shape of the cdeebee storage\n * @param selectCdeebee - Function to select the cdeebee slice from root state\n * @returns An object containing all cdeebee hooks\n */\nexport function createCdeebeeHooks<RootState, Storage>(\n selectCdeebee: (state: RootState) => CdeebeeState<Storage>\n) {\n /**\n * Check if any of the specified APIs are currently loading.\n *\n * @param apiList - Array of API endpoints to check\n * @returns true if any of the APIs are currently active/loading\n *\n * @example\n * const isLoading = useLoading(['/api/forums', '/api/threads']);\n * if (isLoading) return <Spinner />;\n */\n function useLoading(apiList: string[]): boolean {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.active.some(q => apiList.includes(q.api));\n });\n }\n\n /**\n * Get the successful request history for a specific API endpoint.\n *\n * @param api - The API endpoint\n * @returns Array of successful request history entries\n *\n * @example\n * const history = useRequestHistory('/api/forums');\n * console.log(`Made ${history.length} successful requests`);\n */\n function useRequestHistory(api: string) {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.done[api] ?? [];\n });\n }\n\n /**\n * Get the error history for a specific API endpoint.\n *\n * @param api - The API endpoint\n * @returns Array of error history entries\n *\n * @example\n * const errors = useRequestErrors('/api/forums');\n * if (errors.length > 0) {\n * console.error('Last error:', errors[errors.length - 1]);\n * }\n */\n function useRequestErrors(api: string) {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.errors[api] ?? [];\n });\n }\n\n /**\n * Get a specific list from storage with full type safety.\n *\n * @param listName - The name of the list in storage\n * @returns The list data\n *\n * @example\n * const forums = useStorageList('forumList');\n * const forumArray = Object.values(forums);\n */\n function useStorageList<K extends keyof Storage>(listName: K): Storage[K] {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.storage[listName];\n });\n }\n\n /**\n * Get the entire cdeebee storage.\n *\n * @returns The complete storage object\n *\n * @example\n * const storage = useStorage();\n * console.log(Object.keys(storage)); // ['forumList', 'threadList', ...]\n */\n function useStorage(): Storage {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.storage;\n });\n }\n\n /**\n * Check if any request is currently loading (across all APIs).\n *\n * @returns true if any request is active\n *\n * @example\n * const isAnythingLoading = useIsLoading();\n * if (isAnythingLoading) return <GlobalSpinner />;\n */\n function useIsLoading(): boolean {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.active.length > 0;\n });\n }\n\n return {\n useLoading,\n useRequestHistory,\n useRequestErrors,\n useStorageList,\n useStorage,\n useIsLoading,\n };\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param apiList - Array of API endpoints to check\n * @returns true if any of the APIs are currently active/loading\n *\n * @example\n * const isLoading = useLoading(['/api/forums', '/api/threads']);\n */\nexport function useLoading<Storage = unknown>(apiList: string[]): boolean {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.active.some(q => apiList.includes(q.api));\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param api - The API endpoint\n * @returns Array of successful request history entries\n */\nexport function useRequestHistory<Storage = unknown>(api: string) {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.done[api] ?? [];\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param api - The API endpoint\n * @returns Array of error history entries\n */\nexport function useRequestErrors<Storage = unknown>(api: string) {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.errors[api] ?? [];\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param listName - The name of the list in storage\n * @returns The list data\n */\nexport function useStorageList<Storage, K extends keyof Storage>(listName: K): Storage[K] {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.storage[listName];\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @returns The complete storage object\n */\nexport function useStorage<Storage>(): Storage {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.storage;\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @returns true if any request is active\n */\nexport function useIsLoading<Storage = unknown>(): boolean {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.active.length > 0;\n });\n}\n"],"names":["checkModule","settings","module","result","isRecord","value","mergeDeepRight","left","right","rightRecord","key","leftValue","rightValue","omit","keys","obj","batchingUpdate","state","valueList","i","item","path","current","j","pathKey","index","nextIsNumeric","next","AbortControllerStore","api","requestId","controller","apiSet","excludeRequestId","requestIds","abortStore","abortQuery","currentRequestId","abortManager","signal","cleanup","QueryQueue","task","previousPromise","queryQueue","request","createAsyncThunk","options","rejectWithValue","getState","startedAt","abort","withCallback","executeRequest","method","body","headers","extraHeaders","b","requestData","formData","fileKey","bodyKey","response","responseType","error","isDataWithPrimaryKey","normalizeDataWithPrimaryKey","data","primaryKey","applyStrategy","existingValue","newValue","strategy","defaultNormalize","cdeebee","strategyList","keyList","currentStorage","keyListToOmit","responseValue","normalizedValue","initialState","factory","storage","createSlice","action","builder","q","normalize","currentState","normalizedData","createCdeebeeHooks","selectCdeebee","useLoading","apiList","useSelector","useRequestHistory","useRequestErrors","useStorageList","listName","useStorage","useIsLoading"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../lib/reducer/helpers.ts","../lib/reducer/abortController.ts","../lib/reducer/queryQueue.ts","../lib/reducer/request.ts","../lib/reducer/storage.ts","../lib/reducer/index.ts","../lib/hooks/createCdeebeeHooks.ts","../lib/hooks/selectors.ts"],"sourcesContent":["import { type WritableDraft } from '@reduxjs/toolkit';\nimport { type CdeebeeSettings, type CdeebeeModule, CdeebeeValueList } from './types';\n\nexport function checkModule(settings: CdeebeeSettings<unknown> | WritableDraft<CdeebeeSettings<unknown>>, module: CdeebeeModule, result: () => void) {\n if (settings.modules.includes(module)) {\n result();\n }\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function mergeDeepRight<T>(\n left: T,\n right: Partial<T> | Record<string, unknown>\n): T {\n if (!isRecord(left) || !isRecord(right)) {\n return right as T;\n }\n\n const result = { ...left } as Record<string, unknown>;\n const rightRecord = right as Record<string, unknown>;\n\n for (const key in rightRecord) {\n if (Object.prototype.hasOwnProperty.call(rightRecord, key)) {\n const leftValue = result[key];\n const rightValue = rightRecord[key];\n\n if (\n isRecord(leftValue) &&\n isRecord(rightValue) &&\n !Array.isArray(leftValue) &&\n !Array.isArray(rightValue)\n ) {\n result[key] = mergeDeepRight(leftValue, rightValue);\n } else {\n result[key] = rightValue;\n }\n }\n }\n\n return result as T;\n}\n\nexport function omit<T extends Record<string, unknown>>(keys: string[], obj: T): Omit<T, keyof T> {\n const result = { ...obj };\n for (const key of keys) {\n delete result[key];\n }\n return result as Omit<T, keyof T>;\n}\n\n/**\n * Extract primary key values from API response data per list.\n * Handles responses with format: { listName: { data: [...], primaryKey: 'id' } }\n * Returns a map of listName -> array of IDs.\n */\nexport function extractLastResultIdList(response: unknown): Record<string, string[]> {\n if (!isRecord(response)) {\n return {};\n }\n\n const result: Record<string, string[]> = {};\n\n for (const listName of Object.keys(response)) {\n const value = response[listName];\n\n if (\n isRecord(value) &&\n Array.isArray(value.data) &&\n typeof value.primaryKey === 'string'\n ) {\n const primaryKey = value.primaryKey;\n const idList: string[] = [];\n\n for (const item of value.data) {\n if (isRecord(item) && primaryKey in item) {\n idList.push(String(item[primaryKey]));\n }\n }\n\n result[listName] = idList;\n }\n }\n\n return result;\n}\n\nexport function batchingUpdate<T extends Record<string, unknown>>(\n state: T,\n valueList: CdeebeeValueList<T>\n): void {\n for (let i = 0; i < valueList.length; i++) {\n const item = valueList[i] as { key: readonly (string | number)[]; value: unknown };\n const path = item.key;\n const value = item.value;\n\n if (path.length === 0) {\n continue;\n }\n\n let current: Record<string, unknown> | unknown[] = state as Record<string, unknown>;\n\n for (let j = 0; j < path.length - 1; j++) {\n const pathKey = path[j];\n\n if (Array.isArray(current)) {\n const index = typeof pathKey === 'number' ? pathKey : Number(pathKey);\n if (!(index in current) || !isRecord(current[index])) {\n current[index] = {};\n }\n current = current[index] as Record<string, unknown>;\n } else {\n const key = String(pathKey);\n if (!(key in current)) {\n const nextIsNumeric = typeof path[j + 1] === 'number' || (!isNaN(Number(path[j + 1])) && String(Number(path[j + 1])) === String(path[j + 1]));\n current[key] = nextIsNumeric ? [] : {};\n }\n const next = current[key];\n current = (Array.isArray(next) ? next : (isRecord(next) ? next : {})) as Record<string, unknown> | unknown[];\n }\n }\n\n if (Array.isArray(current)) {\n continue; // Can't update array element directly\n }\n current[String(path[path.length - 1])] = value;\n }\n}\n","interface RequestController {\n requestId: string;\n controller: AbortController;\n api: string;\n}\n\nclass AbortControllerStore {\n private byRequestId = new Map<string, RequestController>();\n private byApi = new Map<string, Set<string>>();\n\n add(api: string, requestId: string, controller: AbortController): void {\n const item: RequestController = { requestId, controller, api };\n this.byRequestId.set(requestId, item);\n\n if (!this.byApi.has(api)) {\n this.byApi.set(api, new Set());\n }\n this.byApi.get(api)!.add(requestId);\n }\n\n delete(requestId: string): void {\n const item = this.byRequestId.get(requestId);\n if (!item) return;\n\n this.byRequestId.delete(requestId);\n const apiSet = this.byApi.get(item.api);\n if (apiSet) {\n apiSet.delete(requestId);\n if (apiSet.size === 0) {\n this.byApi.delete(item.api);\n }\n }\n }\n\n abortAllForApi(api: string, excludeRequestId: string): void {\n const requestIDList = this.byApi.get(api);\n if (!requestIDList) return;\n\n requestIDList.forEach(requestId => {\n if (requestId !== excludeRequestId) {\n const item = this.byRequestId.get(requestId);\n if (item) {\n item.controller.abort();\n this.delete(requestId);\n }\n }\n });\n }\n}\n\nconst abortStore = new AbortControllerStore();\n\nexport function abortQuery(api: string, currentRequestId: string): void {\n abortStore.abortAllForApi(api, currentRequestId);\n}\n\nexport function abortManager(signal: AbortSignal, api: string, requestId: string) {\n const controller = new AbortController();\n\n const cleanup = () => {\n abortStore.delete(requestId);\n };\n\n signal.addEventListener('abort', () => {\n controller.abort();\n cleanup();\n });\n\n return {\n controller,\n init: () => abortStore.add(api, requestId, controller),\n drop: cleanup,\n };\n}\n","class QueryQueue {\n private currentPromise: Promise<unknown> = Promise.resolve();\n private queueLength = 0;\n\n async enqueue<T>(task: () => Promise<T>): Promise<T> {\n this.queueLength++;\n\n const previousPromise = this.currentPromise;\n\n this.currentPromise = previousPromise\n .then(() => task(), () => task())\n .finally(() => {\n this.queueLength--;\n });\n\n return this.currentPromise as Promise<T>;\n }\n\n getQueueLength(): number {\n return this.queueLength;\n }\n\n clear(): void {\n this.queueLength = 0;\n }\n}\n\nexport const queryQueue = new QueryQueue();\n\n","import { createAsyncThunk } from '@reduxjs/toolkit';\nimport { checkModule } from './helpers';\nimport { abortManager } from './abortController';\nimport { queryQueue } from './queryQueue';\nimport { type CdeebeeState, type CdeebeeRequestOptions } from './types';\n\nexport const request = createAsyncThunk(\n 'cdeebee/request',\n async (options: CdeebeeRequestOptions<unknown>, { rejectWithValue, getState, requestId, signal }) => {\n const startedAt = new Date().toUTCString();\n const { cdeebee: { settings } } = getState() as { cdeebee: CdeebeeState<unknown> };\n\n const abort = abortManager(signal, options.api, requestId);\n const withCallback = options.onResult && typeof options.onResult === 'function';\n\n checkModule(settings, 'cancelation', abort.init);\n\n const executeRequest = async () => {\n try {\n const { method = 'POST', body, headers = {} } = options;\n const baseHeaders = typeof settings.mergeWithHeaders === 'function'\n ? settings.mergeWithHeaders()\n : (settings.mergeWithHeaders ?? {});\n\n const extraHeaders: Record<string, string> = { ...baseHeaders, ...headers };\n\n const baseData = typeof settings.mergeWithData === 'function'\n ? settings.mergeWithData()\n : (settings.mergeWithData ?? {});\n\n const b = { ...baseData, ...(body ?? {}) };\n let requestData: FormData | string = JSON.stringify(b);\n\n // handling files\n if (options.files) {\n const formData = new FormData();\n const fileKey = options.fileKey || settings.fileKey;\n const bodyKey = options.bodyKey || settings.bodyKey;\n\n for (let i = 0; i < options.files.length; i += 1) {\n if (fileKey) {\n formData.append(fileKey, options.files[i]);\n }\n }\n\n if (bodyKey) {\n formData.append(bodyKey, requestData);\n }\n requestData = formData;\n }\n // [end] handling files\n\n const response = await fetch(options.api, {\n method,\n headers: {\n 'ui-request-id': requestId,\n 'Content-Type': 'application/json',\n ...extraHeaders,\n },\n signal: abort.controller.signal,\n body: requestData,\n });\n\n checkModule(settings, 'cancelation', abort.drop);\n\n let result: unknown;\n const responseType = options.responseType || 'json';\n\n if (responseType === 'text') {\n result = await response.text();\n } else if (responseType === 'blob') {\n result = await response.blob();\n } else {\n // default: json\n result = await response.json();\n }\n\n if (!response.ok) {\n if (withCallback) options.onResult!(result);\n return rejectWithValue(response);\n }\n\n if (withCallback) options.onResult!(result);\n return { result, startedAt, endedAt: new Date().toUTCString() };\n } catch (error) {\n checkModule(settings, 'cancelation', abort.drop);\n\n if (withCallback) options.onResult!(error);\n\n if (error instanceof Error && error.name === 'AbortError') {\n return rejectWithValue({ message: 'Request was cancelled', cancelled: true });\n }\n\n return rejectWithValue({ message: error instanceof Error ? error.message : 'Unknown error occurred' });\n }\n };\n\n if (settings.modules.includes('queryQueue')) {\n return queryQueue.enqueue(executeRequest);\n }\n\n return executeRequest();\n },\n);\n\n","import { type CdeebeeListStrategy, type CdeebeeState } from './types';\nimport { isRecord, mergeDeepRight, omit } from './helpers';\n\ntype ResponseValue = Record<string, unknown>;\n\ntype IResponse = Record<string, ResponseValue>;\n\ntype StorageData = Record<string, unknown>;\n\nfunction isDataWithPrimaryKey(value: unknown): value is { data: unknown[]; primaryKey: string } {\n return (\n isRecord(value) &&\n Array.isArray(value.data) &&\n typeof value.primaryKey === 'string'\n );\n}\nfunction normalizeDataWithPrimaryKey(data: unknown[], primaryKey: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const item of data) {\n if (isRecord(item) && primaryKey in item) {\n const key = String(item[primaryKey]);\n result[key] = item;\n }\n }\n\n return result;\n}\n\nfunction applyStrategy(\n existingValue: StorageData,\n newValue: StorageData | ResponseValue,\n strategy: string,\n key: string\n): ResponseValue {\n if (strategy === 'replace') {\n return newValue as ResponseValue;\n } else if (strategy === 'merge') {\n return mergeDeepRight(existingValue, newValue as StorageData) as ResponseValue;\n } else if (strategy === 'skip') {\n return existingValue as ResponseValue;\n } else {\n console.warn(`Cdeebee: Unknown strategy \"${strategy}\" for key \"${key}\". Skipping normalization.`);\n return mergeDeepRight(existingValue, newValue as StorageData) as ResponseValue;\n }\n}\n\nexport function defaultNormalize<T>(\n cdeebee: CdeebeeState<T>,\n response: IResponse,\n strategyList: CdeebeeListStrategy<T>\n): Record<string, ResponseValue> {\n const keyList = Object.keys(response);\n const currentStorage = isRecord(cdeebee.storage) ? (cdeebee.storage as Record<string, unknown>) : {};\n\n const result = { ...currentStorage } as Record<string, ResponseValue>;\n const keyListToOmit = new Set<string>();\n\n for (const key of keyList) {\n const responseValue = response[key];\n\n if (responseValue === null || responseValue === undefined || typeof responseValue === 'string') {\n keyListToOmit.add(key);\n continue;\n }\n\n const strategy = strategyList[key as keyof T] ?? 'merge';\n\n // For 'skip' strategy, if key doesn't exist in storage, skip it entirely\n if (strategy === 'skip' && !(key in currentStorage)) {\n continue;\n }\n\n const existingValue = key in currentStorage ? (currentStorage[key] as StorageData) : {};\n\n if (isDataWithPrimaryKey(responseValue)) {\n const normalizedValue = normalizeDataWithPrimaryKey(responseValue.data, responseValue.primaryKey);\n result[key] = applyStrategy(existingValue, normalizedValue, strategy, key);\n continue;\n }\n\n if (isRecord(responseValue)) {\n result[key] = applyStrategy(existingValue, responseValue as StorageData, strategy, key);\n } else {\n result[key] = responseValue;\n }\n }\n\n return keyListToOmit.size > 0 ? omit(Array.from(keyListToOmit), result) : result;\n}\n","import { createSlice, current, type PayloadAction } from '@reduxjs/toolkit';\n\nimport { type CdeebeeSettings, type CdeebeeState, type CdeebeeValueList, type CdeebeeListStrategy } from './types';\nimport { checkModule, mergeDeepRight, batchingUpdate, extractLastResultIdList } from './helpers';\nimport { abortQuery } from './abortController';\nimport { request } from './request';\nimport { defaultNormalize } from './storage';\n\nconst initialState: CdeebeeState<unknown> = {\n settings: {\n modules: ['history', 'listener', 'storage', 'cancelation'],\n fileKey: 'file',\n bodyKey: 'value',\n listStrategy: {},\n mergeWithData: {},\n mergeWithHeaders: {},\n },\n storage: {},\n request: {\n active: [],\n errors: {},\n done: {},\n lastResultIdList: {},\n },\n};\n\nexport const factory = <T>(settings: CdeebeeSettings<T>, storage?: T) => {\n const slice = createSlice({\n name: 'cdeebee',\n initialState: mergeDeepRight(initialState, { settings, storage: storage ?? {} }) as CdeebeeState<T>,\n reducers: {\n set(state, action: { payload: CdeebeeValueList<T> }) {\n // Directly mutate state.storage using Immer Draft\n // This is more performant than creating a new object\n // Immer will track changes and create minimal updates\n batchingUpdate(state.storage as Record<string, unknown>, action.payload);\n },\n historyClear(state, action: PayloadAction<string | undefined>) {\n const api = action.payload;\n\n if (api) {\n delete state.request.done[api];\n delete state.request.errors[api];\n } else {\n state.request.done = {};\n state.request.errors = {};\n }\n }\n },\n extraReducers: builder => {\n builder\n .addCase(request.pending, (state, action) => {\n const api = action.meta.arg.api;\n const requestId = action.meta.requestId;\n\n if (action.meta.arg.historyClear) {\n checkModule(state.settings, 'history', () => {\n delete state.request.done[api];\n delete state.request.errors[api];\n });\n }\n\n checkModule(state.settings, 'cancelation', () => {\n abortQuery(api, requestId);\n });\n checkModule(state.settings, 'listener', () => {\n state.request.active.push({ api, requestId });\n });\n })\n .addCase(request.fulfilled, (state, action) => {\n const requestId = action.meta.requestId;\n const api = action.meta.arg.api;\n\n checkModule(state.settings, 'listener', () => {\n state.request.active = state.request.active.filter(q => !(q.api === api && q.requestId === requestId));\n });\n checkModule(state.settings, 'history', () => {\n if (!state.request.done[api]) state.request.done[api] = [];\n state.request.done[api].push({ api, request: action.payload, requestId });\n });\n checkModule(state.settings, 'storage', () => {\n if (action.meta.arg.ignore) {\n return;\n }\n\n const strategyList = (action.meta.arg.listStrategy ?? state.settings.listStrategy ?? {}) as CdeebeeListStrategy<T>;\n const normalize = action.meta.arg.normalize ?? state.settings.normalize ?? defaultNormalize;\n\n const currentState = current(state) as CdeebeeState<T>;\n // Type assertion is safe here because we've already checked isRecord\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const normalizedData = normalize(currentState, action.payload.result as any, strategyList);\n\n // Normalize already handles merge/replace/skip and preserves keys not in response\n // Simply apply the result\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (state.storage as any) = normalizedData;\n\n // Extract and store result IDs for filtering per list\n state.request.lastResultIdList[api] = extractLastResultIdList(action.payload.result);\n });\n })\n .addCase(request.rejected, (state, action) => {\n const requestId = action.meta.requestId;\n const api = action.meta.arg.api;\n\n checkModule(state.settings, 'listener', () => {\n state.request.active = state.request.active.filter(q => !(q.api === api && q.requestId === requestId));\n });\n checkModule(state.settings, 'history', () => {\n if (!state.request.errors[api]) state.request.errors[api] = [];\n state.request.errors[api].push({ requestId: requestId, api, request: action.error });\n });\n });\n },\n });\n\n return slice;\n};\n","import { useSelector } from 'react-redux';\nimport { type CdeebeeState } from '../reducer/types';\n\n/**\n * Generic hook factory that creates a selector hook for cdeebee state.\n * This allows the hooks to work with any Redux root state structure.\n *\n * @template RootState - The shape of the Redux root state\n * @template Storage - The shape of the cdeebee storage\n * @param selectCdeebee - Function to select the cdeebee slice from root state\n * @returns An object containing all cdeebee hooks\n */\nexport function createCdeebeeHooks<RootState, Storage>(\n selectCdeebee: (state: RootState) => CdeebeeState<Storage>\n) {\n /**\n * Check if any of the specified APIs are currently loading.\n *\n * @param apiList - Array of API endpoints to check\n * @returns true if any of the APIs are currently active/loading\n *\n * @example\n * const isLoading = useLoading(['/api/forums', '/api/threads']);\n * if (isLoading) return <Spinner />;\n */\n function useLoading(apiList: string[]): boolean {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.active.some(q => apiList.includes(q.api));\n });\n }\n\n /**\n * Get the successful request history for a specific API endpoint.\n *\n * @param api - The API endpoint\n * @returns Array of successful request history entries\n *\n * @example\n * const history = useRequestHistory('/api/forums');\n * console.log(`Made ${history.length} successful requests`);\n */\n function useRequestHistory(api: string) {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.done[api] ?? [];\n });\n }\n\n /**\n * Get the error history for a specific API endpoint.\n *\n * @param api - The API endpoint\n * @returns Array of error history entries\n *\n * @example\n * const errors = useRequestErrors('/api/forums');\n * if (errors.length > 0) {\n * console.error('Last error:', errors[errors.length - 1]);\n * }\n */\n function useRequestErrors(api: string) {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.errors[api] ?? [];\n });\n }\n\n /**\n * Get a specific list from storage with full type safety.\n *\n * @param listName - The name of the list in storage\n * @returns The list data\n *\n * @example\n * const forums = useStorageList('forumList');\n * const forumArray = Object.values(forums);\n */\n function useStorageList<K extends keyof Storage>(listName: K): Storage[K] {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.storage[listName];\n });\n }\n\n /**\n * Get the entire cdeebee storage.\n *\n * @returns The complete storage object\n *\n * @example\n * const storage = useStorage();\n * console.log(Object.keys(storage)); // ['forumList', 'threadList', ...]\n */\n function useStorage(): Storage {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.storage;\n });\n }\n\n /**\n * Check if any request is currently loading (across all APIs).\n *\n * @returns true if any request is active\n *\n * @example\n * const isAnythingLoading = useIsLoading();\n * if (isAnythingLoading) return <GlobalSpinner />;\n */\n function useIsLoading(): boolean {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.active.length > 0;\n });\n }\n\n /**\n * Get the list of IDs returned by the last successful request to an API for a specific list.\n * Useful for filtering storage data to show only results from a specific request.\n *\n * @param api - The API endpoint\n * @param listName - The name of the list in storage (typed from Storage)\n * @returns Array of primary key IDs from the last response for that list\n *\n * @example\n * const productList = useStorageList('productList');\n * const lastIDList = useLastResultIdList('/api/search', 'productList');\n * const displayResults = lastIDList.map(id => productList[id]).filter(Boolean);\n */\n function useLastResultIdList<K extends keyof Storage>(api: string, listName: K): string[] {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.lastResultIdList[api]?.[listName as string] ?? [];\n });\n }\n\n return {\n useLoading,\n useRequestHistory,\n useRequestErrors,\n useStorageList,\n useStorage,\n useIsLoading,\n useLastResultIdList,\n };\n}\n","import { useSelector } from 'react-redux';\nimport { type CdeebeeState } from '../reducer/types';\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param apiList - Array of API endpoints to check\n * @returns true if any of the APIs are currently active/loading\n *\n * @example\n * const isLoading = useLoading(['/api/forums', '/api/threads']);\n */\nexport function useLoading<Storage = unknown>(apiList: string[]): boolean {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.active.some(q => apiList.includes(q.api));\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param api - The API endpoint\n * @returns Array of successful request history entries\n */\nexport function useRequestHistory<Storage = unknown>(api: string) {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.done[api] ?? [];\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param api - The API endpoint\n * @returns Array of error history entries\n */\nexport function useRequestErrors<Storage = unknown>(api: string) {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.errors[api] ?? [];\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param listName - The name of the list in storage\n * @returns The list data\n */\nexport function useStorageList<Storage, K extends keyof Storage>(listName: K): Storage[K] {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.storage[listName];\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @returns The complete storage object\n */\nexport function useStorage<Storage>(): Storage {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.storage;\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @returns true if any request is active\n */\nexport function useIsLoading<Storage = unknown>(): boolean {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.active.length > 0;\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * Get the list of IDs returned by the last successful request to an API for a specific list.\n * Useful for filtering storage data to show only results from a specific request.\n *\n * @param api - The API endpoint\n * @param listName - The name of the list in storage (typed from Storage)\n * @returns Array of primary key IDs from the last response for that list\n *\n * @example\n * const productList = useStorageList('productList');\n * const lastIDList = useLastResultIdList('/api/search', 'productList');\n * const displayResults = lastIDList.map(id => productList[id]).filter(Boolean);\n */\nexport function useLastResultIdList<Storage, K extends keyof Storage>(api: string, listName: K): string[] {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.lastResultIdList[api]?.[listName as string] ?? [];\n });\n}\n"],"names":["checkModule","settings","module","result","isRecord","value","mergeDeepRight","left","right","rightRecord","key","leftValue","rightValue","omit","keys","obj","extractLastResultIdList","response","listName","primaryKey","idList","item","batchingUpdate","state","valueList","i","path","current","j","pathKey","index","nextIsNumeric","next","AbortControllerStore","api","requestId","controller","apiSet","excludeRequestId","requestIDList","abortStore","abortQuery","currentRequestId","abortManager","signal","cleanup","QueryQueue","task","previousPromise","queryQueue","request","createAsyncThunk","options","rejectWithValue","getState","startedAt","abort","withCallback","executeRequest","method","body","headers","extraHeaders","b","requestData","formData","fileKey","bodyKey","responseType","error","isDataWithPrimaryKey","normalizeDataWithPrimaryKey","data","applyStrategy","existingValue","newValue","strategy","defaultNormalize","cdeebee","strategyList","keyList","currentStorage","keyListToOmit","responseValue","normalizedValue","initialState","factory","storage","createSlice","action","builder","q","normalize","currentState","normalizedData","createCdeebeeHooks","selectCdeebee","useLoading","apiList","useSelector","useRequestHistory","useRequestErrors","useStorageList","useStorage","useIsLoading","useLastResultIdList","_a"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -43,14 +43,15 @@ declare interface CdeebeeRequestState {
43
43
  active: CdeebeeActiveRequest[];
44
44
  errors: Record<string, CdeebeeHistoryState[]>;
45
45
  done: Record<string, CdeebeeHistoryState[]>;
46
+ lastResultIdList: Record<string, Record<string, string[]>>;
46
47
  }
47
48
 
48
49
  declare interface CdeebeeSettings<T> {
49
50
  modules: CdeebeeModule[];
50
51
  fileKey: string;
51
52
  bodyKey: string;
52
- mergeWithData: unknown;
53
- mergeWithHeaders: unknown;
53
+ mergeWithData: Record<string, unknown> | (() => Record<string, unknown>);
54
+ mergeWithHeaders: Record<string, string> | (() => Record<string, string>);
54
55
  listStrategy?: CdeebeeListStrategy<T>;
55
56
  normalize?: <T>(storage: CdeebeeState<T>, result: T, strategyList: CdeebeeListStrategy<T>) => T;
56
57
  }
@@ -86,16 +87,23 @@ export declare function createCdeebeeHooks<RootState, Storage>(selectCdeebee: (s
86
87
  useStorageList: <K extends keyof Storage>(listName: K) => Storage[K];
87
88
  useStorage: () => Storage;
88
89
  useIsLoading: () => boolean;
90
+ useLastResultIdList: <K extends keyof Storage>(api: string, listName: K) => string[];
89
91
  };
90
92
 
93
+ export declare function defaultNormalize<T>(cdeebee: CdeebeeState<T>, response: IResponse, strategyList: CdeebeeListStrategy<T>): Record<string, ResponseValue>;
94
+
91
95
  export declare const factory: <T>(settings: CdeebeeSettings<T>, storage?: T) => Slice<CdeebeeState<T>, {
92
96
  set(state: {
93
97
  settings: {
94
98
  modules: CdeebeeModule[];
95
99
  fileKey: string;
96
100
  bodyKey: string;
97
- mergeWithData: unknown;
98
- mergeWithHeaders: unknown;
101
+ mergeWithData: (() => Record<string, unknown>) | {
102
+ [x: string]: unknown;
103
+ };
104
+ mergeWithHeaders: (() => Record<string, string>) | {
105
+ [x: string]: string;
106
+ };
99
107
  listStrategy?: (CdeebeeListStrategy<T> | undefined extends infer V ? V extends object ? Draft<V> : V : never) | undefined;
100
108
  normalize?: (<T_1>(storage: CdeebeeState<T_1>, result: T_1, strategyList: CdeebeeListStrategy<T_1>) => T_1) | undefined;
101
109
  };
@@ -119,6 +127,11 @@ api: string;
119
127
  request: unknown;
120
128
  }[];
121
129
  };
130
+ lastResultIdList: {
131
+ [x: string]: {
132
+ [x: string]: string[];
133
+ };
134
+ };
122
135
  };
123
136
  }, action: {
124
137
  payload: CdeebeeValueList<T>;
@@ -128,8 +141,12 @@ settings: {
128
141
  modules: CdeebeeModule[];
129
142
  fileKey: string;
130
143
  bodyKey: string;
131
- mergeWithData: unknown;
132
- mergeWithHeaders: unknown;
144
+ mergeWithData: (() => Record<string, unknown>) | {
145
+ [x: string]: unknown;
146
+ };
147
+ mergeWithHeaders: (() => Record<string, string>) | {
148
+ [x: string]: string;
149
+ };
133
150
  listStrategy?: (CdeebeeListStrategy<T> | undefined extends infer V ? V extends object ? Draft<V> : V : never) | undefined;
134
151
  normalize?: (<T_1>(storage: CdeebeeState<T_1>, result: T_1, strategyList: CdeebeeListStrategy<T_1>) => T_1) | undefined;
135
152
  };
@@ -153,10 +170,17 @@ api: string;
153
170
  request: unknown;
154
171
  }[];
155
172
  };
173
+ lastResultIdList: {
174
+ [x: string]: {
175
+ [x: string]: string[];
176
+ };
177
+ };
156
178
  };
157
179
  }, action: PayloadAction<string | undefined>): void;
158
180
  }, "cdeebee", "cdeebee", SliceSelectors<CdeebeeState<T>>>;
159
181
 
182
+ declare type IResponse = Record<string, ResponseValue>;
183
+
160
184
  declare type IsArray<T> = T extends readonly unknown[] ? true : T extends unknown[] ? true : false;
161
185
 
162
186
  declare type KeyOf<T> = Extract<keyof T, string | number>;
@@ -173,6 +197,8 @@ startedAt: string;
173
197
  endedAt: string;
174
198
  }, CdeebeeRequestOptions<unknown>, AsyncThunkConfig>;
175
199
 
200
+ declare type ResponseValue = Record<string, unknown>;
201
+
176
202
  /**
177
203
  * Standalone hook that can be used without createCdeebeeHooks.
178
204
  * Assumes the cdeebee slice is at state.cdeebee.
@@ -181,6 +207,24 @@ endedAt: string;
181
207
  */
182
208
  export declare function useIsLoading<Storage = unknown>(): boolean;
183
209
 
210
+ /**
211
+ * Standalone hook that can be used without createCdeebeeHooks.
212
+ * Assumes the cdeebee slice is at state.cdeebee.
213
+ *
214
+ * Get the list of IDs returned by the last successful request to an API for a specific list.
215
+ * Useful for filtering storage data to show only results from a specific request.
216
+ *
217
+ * @param api - The API endpoint
218
+ * @param listName - The name of the list in storage (typed from Storage)
219
+ * @returns Array of primary key IDs from the last response for that list
220
+ *
221
+ * @example
222
+ * const productList = useStorageList('productList');
223
+ * const lastIDList = useLastResultIdList('/api/search', 'productList');
224
+ * const displayResults = lastIDList.map(id => productList[id]).filter(Boolean);
225
+ */
226
+ export declare function useLastResultIdList<Storage, K extends keyof Storage>(api: string, listName: K): string[];
227
+
184
228
  /**
185
229
  * Standalone hook that can be used without createCdeebeeHooks.
186
230
  * Assumes the cdeebee slice is at state.cdeebee.
package/dist/index.js CHANGED
@@ -1,101 +1,116 @@
1
- import { createAsyncThunk as I, createSlice as P, current as x } from "@reduxjs/toolkit";
1
+ import { createAsyncThunk as z, createSlice as H, current as P } from "@reduxjs/toolkit";
2
2
  import { useSelector as d } from "react-redux";
3
- function f(e, r, s) {
4
- e.modules.includes(r) && s();
3
+ function y(e, r, i) {
4
+ e.modules.includes(r) && i();
5
5
  }
6
- function y(e) {
6
+ function f(e) {
7
7
  return e !== null && typeof e == "object" && !Array.isArray(e);
8
8
  }
9
- function b(e, r) {
10
- if (!y(e) || !y(r))
9
+ function p(e, r) {
10
+ if (!f(e) || !f(r))
11
11
  return r;
12
- const s = { ...e }, o = r;
13
- for (const t in o)
14
- if (Object.prototype.hasOwnProperty.call(o, t)) {
15
- const u = s[t], i = o[t];
16
- y(u) && y(i) && !Array.isArray(u) && !Array.isArray(i) ? s[t] = b(u, i) : s[t] = i;
12
+ const i = { ...e }, n = r;
13
+ for (const t in n)
14
+ if (Object.prototype.hasOwnProperty.call(n, t)) {
15
+ const o = i[t], s = n[t];
16
+ f(o) && f(s) && !Array.isArray(o) && !Array.isArray(s) ? i[t] = p(o, s) : i[t] = s;
17
17
  }
18
- return s;
18
+ return i;
19
19
  }
20
- function C(e, r) {
21
- const s = { ...r };
22
- for (const o of e)
23
- delete s[o];
24
- return s;
20
+ function x(e, r) {
21
+ const i = { ...r };
22
+ for (const n of e)
23
+ delete i[n];
24
+ return i;
25
25
  }
26
- function E(e, r) {
27
- for (let s = 0; s < r.length; s++) {
28
- const o = r[s], t = o.key, u = o.value;
26
+ function N(e) {
27
+ if (!f(e))
28
+ return {};
29
+ const r = {};
30
+ for (const i of Object.keys(e)) {
31
+ const n = e[i];
32
+ if (f(n) && Array.isArray(n.data) && typeof n.primaryKey == "string") {
33
+ const t = n.primaryKey, o = [];
34
+ for (const s of n.data)
35
+ f(s) && t in s && o.push(String(s[t]));
36
+ r[i] = o;
37
+ }
38
+ }
39
+ return r;
40
+ }
41
+ function T(e, r) {
42
+ for (let i = 0; i < r.length; i++) {
43
+ const n = r[i], t = n.key, o = n.value;
29
44
  if (t.length === 0)
30
45
  continue;
31
- let i = e;
32
- for (let n = 0; n < t.length - 1; n++) {
33
- const c = t[n];
34
- if (Array.isArray(i)) {
35
- const a = typeof c == "number" ? c : Number(c);
36
- (!(a in i) || !y(i[a])) && (i[a] = {}), i = i[a];
46
+ let s = e;
47
+ for (let u = 0; u < t.length - 1; u++) {
48
+ const a = t[u];
49
+ if (Array.isArray(s)) {
50
+ const c = typeof a == "number" ? a : Number(a);
51
+ (!(c in s) || !f(s[c])) && (s[c] = {}), s = s[c];
37
52
  } else {
38
- const a = String(c);
39
- if (!(a in i)) {
40
- const g = typeof t[n + 1] == "number" || !isNaN(Number(t[n + 1])) && String(Number(t[n + 1])) === String(t[n + 1]);
41
- i[a] = g ? [] : {};
53
+ const c = String(a);
54
+ if (!(c in s)) {
55
+ const g = typeof t[u + 1] == "number" || !isNaN(Number(t[u + 1])) && String(Number(t[u + 1])) === String(t[u + 1]);
56
+ s[c] = g ? [] : {};
42
57
  }
43
- const l = i[a];
44
- i = Array.isArray(l) || y(l) ? l : {};
58
+ const l = s[c];
59
+ s = Array.isArray(l) || f(l) ? l : {};
45
60
  }
46
61
  }
47
- Array.isArray(i) || (i[String(t[t.length - 1])] = u);
62
+ Array.isArray(s) || (s[String(t[t.length - 1])] = o);
48
63
  }
49
64
  }
50
- class N {
65
+ class W {
51
66
  constructor() {
52
67
  this.byRequestId = /* @__PURE__ */ new Map(), this.byApi = /* @__PURE__ */ new Map();
53
68
  }
54
- add(r, s, o) {
55
- const t = { requestId: s, controller: o, api: r };
56
- this.byRequestId.set(s, t), this.byApi.has(r) || this.byApi.set(r, /* @__PURE__ */ new Set()), this.byApi.get(r).add(s);
69
+ add(r, i, n) {
70
+ const t = { requestId: i, controller: n, api: r };
71
+ this.byRequestId.set(i, t), this.byApi.has(r) || this.byApi.set(r, /* @__PURE__ */ new Set()), this.byApi.get(r).add(i);
57
72
  }
58
73
  delete(r) {
59
- const s = this.byRequestId.get(r);
60
- if (!s) return;
74
+ const i = this.byRequestId.get(r);
75
+ if (!i) return;
61
76
  this.byRequestId.delete(r);
62
- const o = this.byApi.get(s.api);
63
- o && (o.delete(r), o.size === 0 && this.byApi.delete(s.api));
77
+ const n = this.byApi.get(i.api);
78
+ n && (n.delete(r), n.size === 0 && this.byApi.delete(i.api));
64
79
  }
65
- abortAllForApi(r, s) {
66
- const o = this.byApi.get(r);
67
- o && o.forEach((t) => {
68
- if (t !== s) {
69
- const u = this.byRequestId.get(t);
70
- u && (u.controller.abort(), this.delete(t));
80
+ abortAllForApi(r, i) {
81
+ const n = this.byApi.get(r);
82
+ n && n.forEach((t) => {
83
+ if (t !== i) {
84
+ const o = this.byRequestId.get(t);
85
+ o && (o.controller.abort(), this.delete(t));
71
86
  }
72
87
  });
73
88
  }
74
89
  }
75
- const R = new N();
76
- function T(e, r) {
90
+ const R = new W();
91
+ function j(e, r) {
77
92
  R.abortAllForApi(e, r);
78
93
  }
79
- function H(e, r, s) {
80
- const o = new AbortController(), t = () => {
81
- R.delete(s);
94
+ function C(e, r, i) {
95
+ const n = new AbortController(), t = () => {
96
+ R.delete(i);
82
97
  };
83
98
  return e.addEventListener("abort", () => {
84
- o.abort(), t();
99
+ n.abort(), t();
85
100
  }), {
86
- controller: o,
87
- init: () => R.add(r, s, o),
101
+ controller: n,
102
+ init: () => R.add(r, i, n),
88
103
  drop: t
89
104
  };
90
105
  }
91
- class j {
106
+ class E {
92
107
  constructor() {
93
108
  this.currentPromise = Promise.resolve(), this.queueLength = 0;
94
109
  }
95
110
  async enqueue(r) {
96
111
  this.queueLength++;
97
- const s = this.currentPromise;
98
- return this.currentPromise = s.then(() => r(), () => r()).finally(() => {
112
+ const i = this.currentPromise;
113
+ return this.currentPromise = i.then(() => r(), () => r()).finally(() => {
99
114
  this.queueLength--;
100
115
  }), this.currentPromise;
101
116
  }
@@ -106,79 +121,79 @@ class j {
106
121
  this.queueLength = 0;
107
122
  }
108
123
  }
109
- const O = new j(), S = I(
124
+ const O = new E(), L = z(
110
125
  "cdeebee/request",
111
- async (e, { rejectWithValue: r, getState: s, requestId: o, signal: t }) => {
112
- const u = (/* @__PURE__ */ new Date()).toUTCString(), { cdeebee: { settings: i } } = s(), n = H(t, e.api, o), c = e.onResult && typeof e.onResult == "function";
113
- f(i, "cancelation", n.init);
114
- const a = async () => {
126
+ async (e, { rejectWithValue: r, getState: i, requestId: n, signal: t }) => {
127
+ const o = (/* @__PURE__ */ new Date()).toUTCString(), { cdeebee: { settings: s } } = i(), u = C(t, e.api, n), a = e.onResult && typeof e.onResult == "function";
128
+ y(s, "cancelation", u.init);
129
+ const c = async () => {
115
130
  try {
116
- const { method: l = "POST", body: g, headers: K = {} } = e, D = { ...i.mergeWithHeaders ?? {}, ...K }, z = { ...i.mergeWithData ?? {}, ...g ?? {} };
117
- let p = JSON.stringify(z);
131
+ const { method: l = "POST", body: g, headers: h = {} } = e, K = { ...typeof s.mergeWithHeaders == "function" ? s.mergeWithHeaders() : s.mergeWithHeaders ?? {}, ...h }, v = { ...typeof s.mergeWithData == "function" ? s.mergeWithData() : s.mergeWithData ?? {}, ...g ?? {} };
132
+ let q = JSON.stringify(v);
118
133
  if (e.files) {
119
- const q = new FormData(), w = e.fileKey || i.fileKey, L = e.bodyKey || i.bodyKey;
120
- for (let A = 0; A < e.files.length; A += 1)
121
- w && q.append(w, e.files[A]);
122
- L && q.append(L, p), p = q;
134
+ const A = new FormData(), w = e.fileKey || s.fileKey, D = e.bodyKey || s.bodyKey;
135
+ for (let S = 0; S < e.files.length; S += 1)
136
+ w && A.append(w, e.files[S]);
137
+ D && A.append(D, q), q = A;
123
138
  }
124
- const h = await fetch(e.api, {
139
+ const b = await fetch(e.api, {
125
140
  method: l,
126
141
  headers: {
127
- "ui-request-id": o,
142
+ "ui-request-id": n,
128
143
  "Content-Type": "application/json",
129
- ...D
144
+ ...K
130
145
  },
131
- signal: n.controller.signal,
132
- body: p
146
+ signal: u.controller.signal,
147
+ body: q
133
148
  });
134
- f(i, "cancelation", n.drop);
149
+ y(s, "cancelation", u.drop);
135
150
  let m;
136
151
  const k = e.responseType || "json";
137
- return k === "text" ? m = await h.text() : k === "blob" ? m = await h.blob() : m = await h.json(), h.ok ? (c && e.onResult(m), { result: m, startedAt: u, endedAt: (/* @__PURE__ */ new Date()).toUTCString() }) : (c && e.onResult(m), r(h));
152
+ return k === "text" ? m = await b.text() : k === "blob" ? m = await b.blob() : m = await b.json(), b.ok ? (a && e.onResult(m), { result: m, startedAt: o, endedAt: (/* @__PURE__ */ new Date()).toUTCString() }) : (a && e.onResult(m), r(b));
138
153
  } catch (l) {
139
- return f(i, "cancelation", n.drop), c && e.onResult(l), l instanceof Error && l.name === "AbortError" ? r({ message: "Request was cancelled", cancelled: !0 }) : r({ message: l instanceof Error ? l.message : "Unknown error occurred" });
154
+ return y(s, "cancelation", u.drop), a && e.onResult(l), l instanceof Error && l.name === "AbortError" ? r({ message: "Request was cancelled", cancelled: !0 }) : r({ message: l instanceof Error ? l.message : "Unknown error occurred" });
140
155
  }
141
156
  };
142
- return i.modules.includes("queryQueue") ? O.enqueue(a) : a();
157
+ return s.modules.includes("queryQueue") ? O.enqueue(c) : c();
143
158
  }
144
159
  );
145
160
  function Q(e) {
146
- return y(e) && Array.isArray(e.data) && typeof e.primaryKey == "string";
161
+ return f(e) && Array.isArray(e.data) && typeof e.primaryKey == "string";
147
162
  }
148
163
  function U(e, r) {
149
- const s = {};
150
- for (const o of e)
151
- if (y(o) && r in o) {
152
- const t = String(o[r]);
153
- s[t] = o;
164
+ const i = {};
165
+ for (const n of e)
166
+ if (f(n) && r in n) {
167
+ const t = String(n[r]);
168
+ i[t] = n;
154
169
  }
155
- return s;
170
+ return i;
156
171
  }
157
- function v(e, r, s, o) {
158
- return s === "replace" ? r : s === "merge" ? b(e, r) : s === "skip" ? e : (console.warn(`Cdeebee: Unknown strategy "${s}" for key "${o}". Skipping normalization.`), b(e, r));
172
+ function I(e, r, i, n) {
173
+ return i === "replace" ? r : i === "merge" ? p(e, r) : i === "skip" ? e : (console.warn(`Cdeebee: Unknown strategy "${i}" for key "${n}". Skipping normalization.`), p(e, r));
159
174
  }
160
- function M(e, r, s) {
161
- const o = Object.keys(r), t = y(e.storage) ? e.storage : {}, u = { ...t }, i = /* @__PURE__ */ new Set();
162
- for (const n of o) {
163
- const c = r[n];
164
- if (c == null || typeof c == "string") {
165
- i.add(n);
175
+ function M(e, r, i) {
176
+ const n = Object.keys(r), t = f(e.storage) ? e.storage : {}, o = { ...t }, s = /* @__PURE__ */ new Set();
177
+ for (const u of n) {
178
+ const a = r[u];
179
+ if (a == null || typeof a == "string") {
180
+ s.add(u);
166
181
  continue;
167
182
  }
168
- const a = s[n] ?? "merge";
169
- if (a === "skip" && !(n in t))
183
+ const c = i[u] ?? "merge";
184
+ if (c === "skip" && !(u in t))
170
185
  continue;
171
- const l = n in t ? t[n] : {};
172
- if (Q(c)) {
173
- const g = U(c.data, c.primaryKey);
174
- u[n] = v(l, g, a, n);
186
+ const l = u in t ? t[u] : {};
187
+ if (Q(a)) {
188
+ const g = U(a.data, a.primaryKey);
189
+ o[u] = I(l, g, c, u);
175
190
  continue;
176
191
  }
177
- y(c) ? u[n] = v(l, c, a, n) : u[n] = c;
192
+ f(a) ? o[u] = I(l, a, c, u) : o[u] = a;
178
193
  }
179
- return i.size > 0 ? C(Array.from(i), u) : u;
194
+ return s.size > 0 ? x(Array.from(s), o) : o;
180
195
  }
181
- const W = {
196
+ const F = {
182
197
  settings: {
183
198
  modules: ["history", "listener", "storage", "cancelation"],
184
199
  fileKey: "file",
@@ -191,108 +206,124 @@ const W = {
191
206
  request: {
192
207
  active: [],
193
208
  errors: {},
194
- done: {}
209
+ done: {},
210
+ lastResultIdList: {}
195
211
  }
196
- }, J = (e, r) => P({
212
+ }, X = (e, r) => H({
197
213
  name: "cdeebee",
198
- initialState: b(W, { settings: e, storage: r ?? {} }),
214
+ initialState: p(F, { settings: e, storage: r ?? {} }),
199
215
  reducers: {
200
- set(o, t) {
201
- E(o.storage, t.payload);
216
+ set(n, t) {
217
+ T(n.storage, t.payload);
202
218
  },
203
- historyClear(o, t) {
204
- const u = t.payload;
205
- u ? (delete o.request.done[u], delete o.request.errors[u]) : (o.request.done = {}, o.request.errors = {});
219
+ historyClear(n, t) {
220
+ const o = t.payload;
221
+ o ? (delete n.request.done[o], delete n.request.errors[o]) : (n.request.done = {}, n.request.errors = {});
206
222
  }
207
223
  },
208
- extraReducers: (o) => {
209
- o.addCase(S.pending, (t, u) => {
210
- const i = u.meta.arg.api, n = u.meta.requestId;
211
- u.meta.arg.historyClear && f(t.settings, "history", () => {
212
- delete t.request.done[i], delete t.request.errors[i];
213
- }), f(t.settings, "cancelation", () => {
214
- T(i, n);
215
- }), f(t.settings, "listener", () => {
216
- t.request.active.push({ api: i, requestId: n });
224
+ extraReducers: (n) => {
225
+ n.addCase(L.pending, (t, o) => {
226
+ const s = o.meta.arg.api, u = o.meta.requestId;
227
+ o.meta.arg.historyClear && y(t.settings, "history", () => {
228
+ delete t.request.done[s], delete t.request.errors[s];
229
+ }), y(t.settings, "cancelation", () => {
230
+ j(s, u);
231
+ }), y(t.settings, "listener", () => {
232
+ t.request.active.push({ api: s, requestId: u });
217
233
  });
218
- }).addCase(S.fulfilled, (t, u) => {
219
- const i = u.meta.requestId, n = u.meta.arg.api;
220
- f(t.settings, "listener", () => {
221
- t.request.active = t.request.active.filter((c) => !(c.api === n && c.requestId === i));
222
- }), f(t.settings, "history", () => {
223
- t.request.done[n] || (t.request.done[n] = []), t.request.done[n].push({ api: n, request: u.payload, requestId: i });
224
- }), f(t.settings, "storage", () => {
225
- if (u.meta.arg.ignore)
234
+ }).addCase(L.fulfilled, (t, o) => {
235
+ const s = o.meta.requestId, u = o.meta.arg.api;
236
+ y(t.settings, "listener", () => {
237
+ t.request.active = t.request.active.filter((a) => !(a.api === u && a.requestId === s));
238
+ }), y(t.settings, "history", () => {
239
+ t.request.done[u] || (t.request.done[u] = []), t.request.done[u].push({ api: u, request: o.payload, requestId: s });
240
+ }), y(t.settings, "storage", () => {
241
+ if (o.meta.arg.ignore)
226
242
  return;
227
- const c = u.meta.arg.listStrategy ?? t.settings.listStrategy ?? {}, a = u.meta.arg.normalize ?? t.settings.normalize ?? M, l = x(t), g = a(l, u.payload.result, c);
228
- t.storage = g;
243
+ const a = o.meta.arg.listStrategy ?? t.settings.listStrategy ?? {}, c = o.meta.arg.normalize ?? t.settings.normalize ?? M, l = P(t), g = c(l, o.payload.result, a);
244
+ t.storage = g, t.request.lastResultIdList[u] = N(o.payload.result);
229
245
  });
230
- }).addCase(S.rejected, (t, u) => {
231
- const i = u.meta.requestId, n = u.meta.arg.api;
232
- f(t.settings, "listener", () => {
233
- t.request.active = t.request.active.filter((c) => !(c.api === n && c.requestId === i));
234
- }), f(t.settings, "history", () => {
235
- t.request.errors[n] || (t.request.errors[n] = []), t.request.errors[n].push({ requestId: i, api: n, request: u.error });
246
+ }).addCase(L.rejected, (t, o) => {
247
+ const s = o.meta.requestId, u = o.meta.arg.api;
248
+ y(t.settings, "listener", () => {
249
+ t.request.active = t.request.active.filter((a) => !(a.api === u && a.requestId === s));
250
+ }), y(t.settings, "history", () => {
251
+ t.request.errors[u] || (t.request.errors[u] = []), t.request.errors[u].push({ requestId: s, api: u, request: o.error });
236
252
  });
237
253
  });
238
254
  }
239
255
  });
240
- function B(e) {
241
- function r(n) {
242
- return d((c) => e(c).request.active.some((l) => n.includes(l.api)));
256
+ function Y(e) {
257
+ function r(a) {
258
+ return d((c) => e(c).request.active.some((g) => a.includes(g.api)));
243
259
  }
244
- function s(n) {
245
- return d((c) => e(c).request.done[n] ?? []);
260
+ function i(a) {
261
+ return d((c) => e(c).request.done[a] ?? []);
246
262
  }
247
- function o(n) {
248
- return d((c) => e(c).request.errors[n] ?? []);
263
+ function n(a) {
264
+ return d((c) => e(c).request.errors[a] ?? []);
249
265
  }
250
- function t(n) {
251
- return d((c) => e(c).storage[n]);
266
+ function t(a) {
267
+ return d((c) => e(c).storage[a]);
252
268
  }
253
- function u() {
254
- return d((n) => e(n).storage);
269
+ function o() {
270
+ return d((a) => e(a).storage);
255
271
  }
256
- function i() {
257
- return d((n) => e(n).request.active.length > 0);
272
+ function s() {
273
+ return d((a) => e(a).request.active.length > 0);
274
+ }
275
+ function u(a, c) {
276
+ return d((l) => {
277
+ var h;
278
+ return ((h = e(l).request.lastResultIdList[a]) == null ? void 0 : h[c]) ?? [];
279
+ });
258
280
  }
259
281
  return {
260
282
  useLoading: r,
261
- useRequestHistory: s,
262
- useRequestErrors: o,
283
+ useRequestHistory: i,
284
+ useRequestErrors: n,
263
285
  useStorageList: t,
264
- useStorage: u,
265
- useIsLoading: i
286
+ useStorage: o,
287
+ useIsLoading: s,
288
+ useLastResultIdList: u
266
289
  };
267
290
  }
268
- function G(e) {
269
- return d((r) => r.cdeebee.request.active.some((s) => e.includes(s.api)));
291
+ function Z(e) {
292
+ return d((r) => r.cdeebee.request.active.some((i) => e.includes(i.api)));
270
293
  }
271
- function X(e) {
294
+ function _(e) {
272
295
  return d((r) => r.cdeebee.request.done[e] ?? []);
273
296
  }
274
- function Y(e) {
297
+ function V(e) {
275
298
  return d((r) => r.cdeebee.request.errors[e] ?? []);
276
299
  }
277
- function Z(e) {
300
+ function ee(e) {
278
301
  return d((r) => r.cdeebee.storage[e]);
279
302
  }
280
- function _() {
303
+ function te() {
281
304
  return d((e) => e.cdeebee.storage);
282
305
  }
283
- function V() {
306
+ function re() {
284
307
  return d((e) => e.cdeebee.request.active.length > 0);
285
308
  }
309
+ function ne(e, r) {
310
+ return d((i) => {
311
+ var n;
312
+ return ((n = i.cdeebee.request.lastResultIdList[e]) == null ? void 0 : n[r]) ?? [];
313
+ });
314
+ }
286
315
  export {
287
- E as batchingUpdate,
288
- B as createCdeebeeHooks,
289
- J as factory,
290
- S as request,
291
- V as useIsLoading,
292
- G as useLoading,
293
- Y as useRequestErrors,
294
- X as useRequestHistory,
295
- _ as useStorage,
296
- Z as useStorageList
316
+ T as batchingUpdate,
317
+ Y as createCdeebeeHooks,
318
+ M as defaultNormalize,
319
+ X as factory,
320
+ L as request,
321
+ re as useIsLoading,
322
+ ne as useLastResultIdList,
323
+ Z as useLoading,
324
+ V as useRequestErrors,
325
+ _ as useRequestHistory,
326
+ te as useStorage,
327
+ ee as useStorageList
297
328
  };
298
329
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../lib/reducer/helpers.ts","../lib/reducer/abortController.ts","../lib/reducer/queryQueue.ts","../lib/reducer/request.ts","../lib/reducer/storage.ts","../lib/reducer/index.ts","../lib/hooks.ts"],"sourcesContent":["import { type WritableDraft } from '@reduxjs/toolkit';\nimport { type CdeebeeSettings, type CdeebeeModule, CdeebeeValueList } from './types';\n\nexport function checkModule(settings: CdeebeeSettings<unknown> | WritableDraft<CdeebeeSettings<unknown>>, module: CdeebeeModule, result: () => void) {\n if (settings.modules.includes(module)) {\n result();\n }\n}\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function hasDataProperty(value: unknown): value is Record<string, unknown> & { data: unknown[] } {\n return isRecord(value) && Array.isArray(value.data);\n}\n\nexport function hasProperty(value: unknown, prop: string): boolean {\n return isRecord(value) && Object.prototype.hasOwnProperty.call(value, prop);\n}\n\nexport function mergeDeepRight<T>(\n left: T,\n right: Partial<T> | Record<string, unknown>\n): T {\n if (!isRecord(left) || !isRecord(right)) {\n return right as T;\n }\n\n const result = { ...left } as Record<string, unknown>;\n const rightRecord = right as Record<string, unknown>;\n\n for (const key in rightRecord) {\n if (Object.prototype.hasOwnProperty.call(rightRecord, key)) {\n const leftValue = result[key];\n const rightValue = rightRecord[key];\n\n if (\n isRecord(leftValue) &&\n isRecord(rightValue) &&\n !Array.isArray(leftValue) &&\n !Array.isArray(rightValue)\n ) {\n result[key] = mergeDeepRight(leftValue, rightValue);\n } else {\n result[key] = rightValue;\n }\n }\n }\n\n return result as T;\n}\n\nexport function omit<T extends Record<string, unknown>>(keys: string[], obj: T): Omit<T, keyof T> {\n const result = { ...obj };\n for (const key of keys) {\n delete result[key];\n }\n return result as Omit<T, keyof T>;\n}\n\nexport function assocPath<T>(path: (string | number)[], value: unknown, obj: T): T {\n if (path.length === 0) {\n return value as T;\n }\n\n const [first, ...rest] = path;\n const firstKey = String(first);\n const result = Array.isArray(obj) ? [...obj] : { ...obj } as Record<string, unknown>;\n\n if (rest.length === 0) {\n (result as Record<string, unknown>)[firstKey] = value;\n } else {\n const currentValue = (result as Record<string, unknown>)[firstKey];\n (result as Record<string, unknown>)[firstKey] = assocPath(rest, value, currentValue ?? {});\n }\n\n return result as T;\n}\n\nexport function batchingUpdate<T extends Record<string, unknown>>(\n state: T,\n valueList: CdeebeeValueList<T>\n): void {\n for (let i = 0; i < valueList.length; i++) {\n const item = valueList[i] as { key: readonly (string | number)[]; value: unknown };\n const path = item.key;\n const value = item.value;\n \n if (path.length === 0) {\n continue;\n }\n\n let current: Record<string, unknown> | unknown[] = state as Record<string, unknown>;\n \n for (let j = 0; j < path.length - 1; j++) {\n const pathKey = path[j];\n \n if (Array.isArray(current)) {\n const index = typeof pathKey === 'number' ? pathKey : Number(pathKey);\n if (!(index in current) || !isRecord(current[index])) {\n current[index] = {};\n }\n current = current[index] as Record<string, unknown>;\n } else {\n const key = String(pathKey);\n if (!(key in current)) {\n const nextIsNumeric = typeof path[j + 1] === 'number' || (!isNaN(Number(path[j + 1])) && String(Number(path[j + 1])) === String(path[j + 1]));\n current[key] = nextIsNumeric ? [] : {};\n }\n const next = current[key];\n current = (Array.isArray(next) ? next : (isRecord(next) ? next : {})) as Record<string, unknown> | unknown[];\n }\n }\n \n if (Array.isArray(current)) {\n continue; // Can't update array element directly\n }\n current[String(path[path.length - 1])] = value;\n }\n}\n","interface RequestController {\n requestId: string;\n controller: AbortController;\n api: string;\n}\n\nclass AbortControllerStore {\n private byRequestId = new Map<string, RequestController>();\n private byApi = new Map<string, Set<string>>();\n\n add(api: string, requestId: string, controller: AbortController): void {\n const item: RequestController = { requestId, controller, api };\n this.byRequestId.set(requestId, item);\n\n if (!this.byApi.has(api)) {\n this.byApi.set(api, new Set());\n }\n this.byApi.get(api)!.add(requestId);\n }\n\n delete(requestId: string): void {\n const item = this.byRequestId.get(requestId);\n if (!item) return;\n\n this.byRequestId.delete(requestId);\n const apiSet = this.byApi.get(item.api);\n if (apiSet) {\n apiSet.delete(requestId);\n if (apiSet.size === 0) {\n this.byApi.delete(item.api);\n }\n }\n }\n\n abortAllForApi(api: string, excludeRequestId: string): void {\n const requestIds = this.byApi.get(api);\n if (!requestIds) return;\n\n requestIds.forEach(requestId => {\n if (requestId !== excludeRequestId) {\n const item = this.byRequestId.get(requestId);\n if (item) {\n item.controller.abort();\n this.delete(requestId);\n }\n }\n });\n }\n}\n\nconst abortStore = new AbortControllerStore();\n\nexport function abortQuery(api: string, currentRequestId: string): void {\n abortStore.abortAllForApi(api, currentRequestId);\n}\n\nexport function abortManager(signal: AbortSignal, api: string, requestId: string) {\n const controller = new AbortController();\n\n const cleanup = () => {\n abortStore.delete(requestId);\n };\n\n signal.addEventListener('abort', () => {\n controller.abort();\n cleanup();\n });\n\n return {\n controller,\n init: () => abortStore.add(api, requestId, controller),\n drop: cleanup,\n };\n}\n","class QueryQueue {\n private currentPromise: Promise<unknown> = Promise.resolve();\n private queueLength = 0;\n\n async enqueue<T>(task: () => Promise<T>): Promise<T> {\n this.queueLength++;\n \n const previousPromise = this.currentPromise;\n \n this.currentPromise = previousPromise\n .then(() => task(), () => task())\n .finally(() => {\n this.queueLength--;\n });\n\n return this.currentPromise as Promise<T>;\n }\n\n getQueueLength(): number {\n return this.queueLength;\n }\n\n clear(): void {\n this.queueLength = 0;\n }\n}\n\nexport const queryQueue = new QueryQueue();\n\n","import { createAsyncThunk } from '@reduxjs/toolkit';\nimport { checkModule } from './helpers';\nimport { abortManager } from './abortController';\nimport { queryQueue } from './queryQueue';\nimport { type CdeebeeState, type CdeebeeRequestOptions } from './types';\n\nexport const request = createAsyncThunk(\n 'cdeebee/request',\n async (options: CdeebeeRequestOptions<unknown>, { rejectWithValue, getState, requestId, signal }) => {\n const startedAt = new Date().toUTCString();\n const { cdeebee: { settings } } = getState() as { cdeebee: CdeebeeState<unknown> };\n\n const abort = abortManager(signal, options.api, requestId);\n const withCallback = options.onResult && typeof options.onResult === 'function';\n\n checkModule(settings, 'cancelation', abort.init);\n\n const executeRequest = async () => {\n try {\n const { method = 'POST', body, headers = {} } = options;\n const extraHeaders: Record<string, string> = { ...(settings.mergeWithHeaders ?? {}), ...headers };\n\n const b = { ...(settings.mergeWithData ?? {}), ...(body ?? {}) };\n let requestData: FormData | string = JSON.stringify(b);\n\n // handling files\n if (options.files) {\n const formData = new FormData();\n const fileKey = options.fileKey || settings.fileKey;\n const bodyKey = options.bodyKey || settings.bodyKey;\n\n for (let i = 0; i < options.files.length; i += 1) {\n if (fileKey) {\n formData.append(fileKey, options.files[i]);\n }\n }\n\n if (bodyKey) {\n formData.append(bodyKey, requestData);\n }\n requestData = formData;\n }\n // [end] handling files\n \n const response = await fetch(options.api, {\n method,\n headers: {\n 'ui-request-id': requestId,\n 'Content-Type': 'application/json',\n ...extraHeaders,\n },\n signal: abort.controller.signal,\n body: requestData,\n });\n\n checkModule(settings, 'cancelation', abort.drop);\n\n let result: unknown;\n const responseType = options.responseType || 'json';\n \n if (responseType === 'text') {\n result = await response.text();\n } else if (responseType === 'blob') {\n result = await response.blob();\n } else {\n // default: json\n result = await response.json();\n }\n\n if (!response.ok) {\n if (withCallback) options.onResult!(result);\n return rejectWithValue(response);\n }\n\n if (withCallback) options.onResult!(result);\n return { result, startedAt, endedAt: new Date().toUTCString() };\n } catch (error) {\n checkModule(settings, 'cancelation', abort.drop);\n\n if (withCallback) options.onResult!(error); \n\n if (error instanceof Error && error.name === 'AbortError') {\n return rejectWithValue({ message: 'Request was cancelled', cancelled: true });\n }\n\n return rejectWithValue({ message: error instanceof Error ? error.message : 'Unknown error occurred' });\n }\n };\n\n if (settings.modules.includes('queryQueue')) {\n return queryQueue.enqueue(executeRequest);\n }\n\n return executeRequest();\n },\n);\n\n","import { type CdeebeeListStrategy, type CdeebeeState } from './types';\nimport { isRecord, mergeDeepRight, omit } from './helpers';\n\ntype ResponseValue = Record<string, unknown>;\n\ntype IResponse = Record<string, ResponseValue>;\n\ntype StorageData = Record<string, unknown>;\n\nfunction isDataWithPrimaryKey(value: unknown): value is { data: unknown[]; primaryKey: string } {\n return (\n isRecord(value) &&\n Array.isArray(value.data) &&\n typeof value.primaryKey === 'string'\n );\n}\nfunction normalizeDataWithPrimaryKey(data: unknown[], primaryKey: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n \n for (const item of data) {\n if (isRecord(item) && primaryKey in item) {\n const key = String(item[primaryKey]);\n result[key] = item;\n }\n }\n \n return result;\n}\n\nfunction applyStrategy(\n existingValue: StorageData,\n newValue: StorageData | ResponseValue,\n strategy: string,\n key: string\n): ResponseValue {\n if (strategy === 'replace') {\n return newValue as ResponseValue;\n } else if (strategy === 'merge') {\n return mergeDeepRight(existingValue, newValue as StorageData) as ResponseValue;\n } else if (strategy === 'skip') {\n return existingValue as ResponseValue;\n } else {\n console.warn(`Cdeebee: Unknown strategy \"${strategy}\" for key \"${key}\". Skipping normalization.`);\n return mergeDeepRight(existingValue, newValue as StorageData) as ResponseValue;\n }\n}\n\nexport function defaultNormalize<T>(\n cdeebee: CdeebeeState<T>,\n response: IResponse,\n strategyList: CdeebeeListStrategy<T> \n): Record<string, ResponseValue> {\n const keyList = Object.keys(response);\n const currentStorage = isRecord(cdeebee.storage) ? (cdeebee.storage as Record<string, unknown>) : {};\n \n const result = { ...currentStorage } as Record<string, ResponseValue>;\n const keyListToOmit = new Set<string>();\n\n for (const key of keyList) {\n const responseValue = response[key];\n\n if (responseValue === null || responseValue === undefined || typeof responseValue === 'string') {\n keyListToOmit.add(key);\n continue;\n }\n\n const strategy = strategyList[key as keyof T] ?? 'merge';\n \n // For 'skip' strategy, if key doesn't exist in storage, skip it entirely\n if (strategy === 'skip' && !(key in currentStorage)) {\n continue;\n }\n \n const existingValue = key in currentStorage ? (currentStorage[key] as StorageData) : {};\n\n if (isDataWithPrimaryKey(responseValue)) {\n const normalizedValue = normalizeDataWithPrimaryKey(responseValue.data, responseValue.primaryKey);\n result[key] = applyStrategy(existingValue, normalizedValue, strategy, key);\n continue;\n }\n\n if (isRecord(responseValue)) {\n result[key] = applyStrategy(existingValue, responseValue as StorageData, strategy, key);\n } else {\n result[key] = responseValue;\n }\n }\n\n return keyListToOmit.size > 0 ? omit(Array.from(keyListToOmit), result) : result;\n}\n","import { createSlice, current, type PayloadAction } from '@reduxjs/toolkit';\n\nimport { type CdeebeeSettings, type CdeebeeState, type CdeebeeValueList, type CdeebeeListStrategy } from './types';\nimport { checkModule, mergeDeepRight, batchingUpdate } from './helpers';\nimport { abortQuery } from './abortController';\nimport { request } from './request';\nimport { defaultNormalize } from './storage';\n\nconst initialState: CdeebeeState<unknown> = {\n settings: {\n modules: ['history', 'listener', 'storage', 'cancelation'],\n fileKey: 'file',\n bodyKey: 'value',\n listStrategy: {},\n mergeWithData: {},\n mergeWithHeaders: {},\n },\n storage: {},\n request: {\n active: [],\n errors: {},\n done: {}\n },\n};\n\nexport const factory = <T>(settings: CdeebeeSettings<T>, storage?: T) => {\n const slice = createSlice({\n name: 'cdeebee',\n initialState: mergeDeepRight(initialState, { settings, storage: storage ?? {} }) as CdeebeeState<T>,\n reducers: {\n set(state, action: { payload: CdeebeeValueList<T> }) {\n // Directly mutate state.storage using Immer Draft\n // This is more performant than creating a new object\n // Immer will track changes and create minimal updates\n batchingUpdate(state.storage as Record<string, unknown>, action.payload);\n },\n historyClear(state, action: PayloadAction<string | undefined>) {\n const api = action.payload;\n\n if (api) {\n delete state.request.done[api];\n delete state.request.errors[api];\n } else {\n state.request.done = {};\n state.request.errors = {};\n }\n }\n },\n extraReducers: builder => {\n builder\n .addCase(request.pending, (state, action) => {\n const api = action.meta.arg.api;\n const requestId = action.meta.requestId;\n\n if (action.meta.arg.historyClear) {\n checkModule(state.settings, 'history', () => {\n delete state.request.done[api];\n delete state.request.errors[api];\n });\n }\n\n checkModule(state.settings, 'cancelation', () => {\n abortQuery(api, requestId);\n });\n checkModule(state.settings, 'listener', () => {\n state.request.active.push({ api, requestId });\n });\n })\n .addCase(request.fulfilled, (state, action) => {\n const requestId = action.meta.requestId;\n const api = action.meta.arg.api;\n\n checkModule(state.settings, 'listener', () => {\n state.request.active = state.request.active.filter(q => !(q.api === api && q.requestId === requestId));\n });\n checkModule(state.settings, 'history', () => {\n if (!state.request.done[api]) state.request.done[api] = [];\n state.request.done[api].push({ api, request: action.payload, requestId });\n });\n checkModule(state.settings, 'storage', () => {\n if (action.meta.arg.ignore) {\n return;\n }\n \n const strategyList = (action.meta.arg.listStrategy ?? state.settings.listStrategy ?? {}) as CdeebeeListStrategy<T>;\n const normalize = action.meta.arg.normalize ?? state.settings.normalize ?? defaultNormalize;\n\n const currentState = current(state) as CdeebeeState<T>;\n // Type assertion is safe here because we've already checked isRecord\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const normalizedData = normalize(currentState, action.payload.result as any, strategyList);\n\n // Normalize already handles merge/replace/skip and preserves keys not in response\n // Simply apply the result\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (state.storage as any) = normalizedData;\n });\n })\n .addCase(request.rejected, (state, action) => {\n const requestId = action.meta.requestId;\n const api = action.meta.arg.api;\n\n checkModule(state.settings, 'listener', () => {\n state.request.active = state.request.active.filter(q => !(q.api === api && q.requestId === requestId));\n });\n checkModule(state.settings, 'history', () => {\n if (!state.request.errors[api]) state.request.errors[api] = [];\n state.request.errors[api].push({ requestId: requestId, api, request: action.error });\n });\n });\n },\n });\n\n return slice;\n};\n","import { useSelector } from 'react-redux';\nimport { type CdeebeeState } from './reducer/types';\n\n/**\n * Generic hook factory that creates a selector hook for cdeebee state.\n * This allows the hooks to work with any Redux root state structure.\n *\n * @template RootState - The shape of the Redux root state\n * @template Storage - The shape of the cdeebee storage\n * @param selectCdeebee - Function to select the cdeebee slice from root state\n * @returns An object containing all cdeebee hooks\n */\nexport function createCdeebeeHooks<RootState, Storage>(\n selectCdeebee: (state: RootState) => CdeebeeState<Storage>\n) {\n /**\n * Check if any of the specified APIs are currently loading.\n *\n * @param apiList - Array of API endpoints to check\n * @returns true if any of the APIs are currently active/loading\n *\n * @example\n * const isLoading = useLoading(['/api/forums', '/api/threads']);\n * if (isLoading) return <Spinner />;\n */\n function useLoading(apiList: string[]): boolean {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.active.some(q => apiList.includes(q.api));\n });\n }\n\n /**\n * Get the successful request history for a specific API endpoint.\n *\n * @param api - The API endpoint\n * @returns Array of successful request history entries\n *\n * @example\n * const history = useRequestHistory('/api/forums');\n * console.log(`Made ${history.length} successful requests`);\n */\n function useRequestHistory(api: string) {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.done[api] ?? [];\n });\n }\n\n /**\n * Get the error history for a specific API endpoint.\n *\n * @param api - The API endpoint\n * @returns Array of error history entries\n *\n * @example\n * const errors = useRequestErrors('/api/forums');\n * if (errors.length > 0) {\n * console.error('Last error:', errors[errors.length - 1]);\n * }\n */\n function useRequestErrors(api: string) {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.errors[api] ?? [];\n });\n }\n\n /**\n * Get a specific list from storage with full type safety.\n *\n * @param listName - The name of the list in storage\n * @returns The list data\n *\n * @example\n * const forums = useStorageList('forumList');\n * const forumArray = Object.values(forums);\n */\n function useStorageList<K extends keyof Storage>(listName: K): Storage[K] {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.storage[listName];\n });\n }\n\n /**\n * Get the entire cdeebee storage.\n *\n * @returns The complete storage object\n *\n * @example\n * const storage = useStorage();\n * console.log(Object.keys(storage)); // ['forumList', 'threadList', ...]\n */\n function useStorage(): Storage {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.storage;\n });\n }\n\n /**\n * Check if any request is currently loading (across all APIs).\n *\n * @returns true if any request is active\n *\n * @example\n * const isAnythingLoading = useIsLoading();\n * if (isAnythingLoading) return <GlobalSpinner />;\n */\n function useIsLoading(): boolean {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.active.length > 0;\n });\n }\n\n return {\n useLoading,\n useRequestHistory,\n useRequestErrors,\n useStorageList,\n useStorage,\n useIsLoading,\n };\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param apiList - Array of API endpoints to check\n * @returns true if any of the APIs are currently active/loading\n *\n * @example\n * const isLoading = useLoading(['/api/forums', '/api/threads']);\n */\nexport function useLoading<Storage = unknown>(apiList: string[]): boolean {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.active.some(q => apiList.includes(q.api));\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param api - The API endpoint\n * @returns Array of successful request history entries\n */\nexport function useRequestHistory<Storage = unknown>(api: string) {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.done[api] ?? [];\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param api - The API endpoint\n * @returns Array of error history entries\n */\nexport function useRequestErrors<Storage = unknown>(api: string) {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.errors[api] ?? [];\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param listName - The name of the list in storage\n * @returns The list data\n */\nexport function useStorageList<Storage, K extends keyof Storage>(listName: K): Storage[K] {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.storage[listName];\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @returns The complete storage object\n */\nexport function useStorage<Storage>(): Storage {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.storage;\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @returns true if any request is active\n */\nexport function useIsLoading<Storage = unknown>(): boolean {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.active.length > 0;\n });\n}\n"],"names":["checkModule","settings","module","result","isRecord","value","mergeDeepRight","left","right","rightRecord","key","leftValue","rightValue","omit","keys","obj","batchingUpdate","state","valueList","i","item","path","current","j","pathKey","index","nextIsNumeric","next","AbortControllerStore","api","requestId","controller","apiSet","excludeRequestId","requestIds","abortStore","abortQuery","currentRequestId","abortManager","signal","cleanup","QueryQueue","task","previousPromise","queryQueue","request","createAsyncThunk","options","rejectWithValue","getState","startedAt","abort","withCallback","executeRequest","method","body","headers","extraHeaders","b","requestData","formData","fileKey","bodyKey","response","responseType","error","isDataWithPrimaryKey","normalizeDataWithPrimaryKey","data","primaryKey","applyStrategy","existingValue","newValue","strategy","defaultNormalize","cdeebee","strategyList","keyList","currentStorage","keyListToOmit","responseValue","normalizedValue","initialState","factory","storage","createSlice","action","builder","q","normalize","currentState","normalizedData","createCdeebeeHooks","selectCdeebee","useLoading","apiList","useSelector","useRequestHistory","useRequestErrors","useStorageList","listName","useStorage","useIsLoading"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../lib/reducer/helpers.ts","../lib/reducer/abortController.ts","../lib/reducer/queryQueue.ts","../lib/reducer/request.ts","../lib/reducer/storage.ts","../lib/reducer/index.ts","../lib/hooks/createCdeebeeHooks.ts","../lib/hooks/selectors.ts"],"sourcesContent":["import { type WritableDraft } from '@reduxjs/toolkit';\nimport { type CdeebeeSettings, type CdeebeeModule, CdeebeeValueList } from './types';\n\nexport function checkModule(settings: CdeebeeSettings<unknown> | WritableDraft<CdeebeeSettings<unknown>>, module: CdeebeeModule, result: () => void) {\n if (settings.modules.includes(module)) {\n result();\n }\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function mergeDeepRight<T>(\n left: T,\n right: Partial<T> | Record<string, unknown>\n): T {\n if (!isRecord(left) || !isRecord(right)) {\n return right as T;\n }\n\n const result = { ...left } as Record<string, unknown>;\n const rightRecord = right as Record<string, unknown>;\n\n for (const key in rightRecord) {\n if (Object.prototype.hasOwnProperty.call(rightRecord, key)) {\n const leftValue = result[key];\n const rightValue = rightRecord[key];\n\n if (\n isRecord(leftValue) &&\n isRecord(rightValue) &&\n !Array.isArray(leftValue) &&\n !Array.isArray(rightValue)\n ) {\n result[key] = mergeDeepRight(leftValue, rightValue);\n } else {\n result[key] = rightValue;\n }\n }\n }\n\n return result as T;\n}\n\nexport function omit<T extends Record<string, unknown>>(keys: string[], obj: T): Omit<T, keyof T> {\n const result = { ...obj };\n for (const key of keys) {\n delete result[key];\n }\n return result as Omit<T, keyof T>;\n}\n\n/**\n * Extract primary key values from API response data per list.\n * Handles responses with format: { listName: { data: [...], primaryKey: 'id' } }\n * Returns a map of listName -> array of IDs.\n */\nexport function extractLastResultIdList(response: unknown): Record<string, string[]> {\n if (!isRecord(response)) {\n return {};\n }\n\n const result: Record<string, string[]> = {};\n\n for (const listName of Object.keys(response)) {\n const value = response[listName];\n\n if (\n isRecord(value) &&\n Array.isArray(value.data) &&\n typeof value.primaryKey === 'string'\n ) {\n const primaryKey = value.primaryKey;\n const idList: string[] = [];\n\n for (const item of value.data) {\n if (isRecord(item) && primaryKey in item) {\n idList.push(String(item[primaryKey]));\n }\n }\n\n result[listName] = idList;\n }\n }\n\n return result;\n}\n\nexport function batchingUpdate<T extends Record<string, unknown>>(\n state: T,\n valueList: CdeebeeValueList<T>\n): void {\n for (let i = 0; i < valueList.length; i++) {\n const item = valueList[i] as { key: readonly (string | number)[]; value: unknown };\n const path = item.key;\n const value = item.value;\n\n if (path.length === 0) {\n continue;\n }\n\n let current: Record<string, unknown> | unknown[] = state as Record<string, unknown>;\n\n for (let j = 0; j < path.length - 1; j++) {\n const pathKey = path[j];\n\n if (Array.isArray(current)) {\n const index = typeof pathKey === 'number' ? pathKey : Number(pathKey);\n if (!(index in current) || !isRecord(current[index])) {\n current[index] = {};\n }\n current = current[index] as Record<string, unknown>;\n } else {\n const key = String(pathKey);\n if (!(key in current)) {\n const nextIsNumeric = typeof path[j + 1] === 'number' || (!isNaN(Number(path[j + 1])) && String(Number(path[j + 1])) === String(path[j + 1]));\n current[key] = nextIsNumeric ? [] : {};\n }\n const next = current[key];\n current = (Array.isArray(next) ? next : (isRecord(next) ? next : {})) as Record<string, unknown> | unknown[];\n }\n }\n\n if (Array.isArray(current)) {\n continue; // Can't update array element directly\n }\n current[String(path[path.length - 1])] = value;\n }\n}\n","interface RequestController {\n requestId: string;\n controller: AbortController;\n api: string;\n}\n\nclass AbortControllerStore {\n private byRequestId = new Map<string, RequestController>();\n private byApi = new Map<string, Set<string>>();\n\n add(api: string, requestId: string, controller: AbortController): void {\n const item: RequestController = { requestId, controller, api };\n this.byRequestId.set(requestId, item);\n\n if (!this.byApi.has(api)) {\n this.byApi.set(api, new Set());\n }\n this.byApi.get(api)!.add(requestId);\n }\n\n delete(requestId: string): void {\n const item = this.byRequestId.get(requestId);\n if (!item) return;\n\n this.byRequestId.delete(requestId);\n const apiSet = this.byApi.get(item.api);\n if (apiSet) {\n apiSet.delete(requestId);\n if (apiSet.size === 0) {\n this.byApi.delete(item.api);\n }\n }\n }\n\n abortAllForApi(api: string, excludeRequestId: string): void {\n const requestIDList = this.byApi.get(api);\n if (!requestIDList) return;\n\n requestIDList.forEach(requestId => {\n if (requestId !== excludeRequestId) {\n const item = this.byRequestId.get(requestId);\n if (item) {\n item.controller.abort();\n this.delete(requestId);\n }\n }\n });\n }\n}\n\nconst abortStore = new AbortControllerStore();\n\nexport function abortQuery(api: string, currentRequestId: string): void {\n abortStore.abortAllForApi(api, currentRequestId);\n}\n\nexport function abortManager(signal: AbortSignal, api: string, requestId: string) {\n const controller = new AbortController();\n\n const cleanup = () => {\n abortStore.delete(requestId);\n };\n\n signal.addEventListener('abort', () => {\n controller.abort();\n cleanup();\n });\n\n return {\n controller,\n init: () => abortStore.add(api, requestId, controller),\n drop: cleanup,\n };\n}\n","class QueryQueue {\n private currentPromise: Promise<unknown> = Promise.resolve();\n private queueLength = 0;\n\n async enqueue<T>(task: () => Promise<T>): Promise<T> {\n this.queueLength++;\n\n const previousPromise = this.currentPromise;\n\n this.currentPromise = previousPromise\n .then(() => task(), () => task())\n .finally(() => {\n this.queueLength--;\n });\n\n return this.currentPromise as Promise<T>;\n }\n\n getQueueLength(): number {\n return this.queueLength;\n }\n\n clear(): void {\n this.queueLength = 0;\n }\n}\n\nexport const queryQueue = new QueryQueue();\n\n","import { createAsyncThunk } from '@reduxjs/toolkit';\nimport { checkModule } from './helpers';\nimport { abortManager } from './abortController';\nimport { queryQueue } from './queryQueue';\nimport { type CdeebeeState, type CdeebeeRequestOptions } from './types';\n\nexport const request = createAsyncThunk(\n 'cdeebee/request',\n async (options: CdeebeeRequestOptions<unknown>, { rejectWithValue, getState, requestId, signal }) => {\n const startedAt = new Date().toUTCString();\n const { cdeebee: { settings } } = getState() as { cdeebee: CdeebeeState<unknown> };\n\n const abort = abortManager(signal, options.api, requestId);\n const withCallback = options.onResult && typeof options.onResult === 'function';\n\n checkModule(settings, 'cancelation', abort.init);\n\n const executeRequest = async () => {\n try {\n const { method = 'POST', body, headers = {} } = options;\n const baseHeaders = typeof settings.mergeWithHeaders === 'function'\n ? settings.mergeWithHeaders()\n : (settings.mergeWithHeaders ?? {});\n\n const extraHeaders: Record<string, string> = { ...baseHeaders, ...headers };\n\n const baseData = typeof settings.mergeWithData === 'function'\n ? settings.mergeWithData()\n : (settings.mergeWithData ?? {});\n\n const b = { ...baseData, ...(body ?? {}) };\n let requestData: FormData | string = JSON.stringify(b);\n\n // handling files\n if (options.files) {\n const formData = new FormData();\n const fileKey = options.fileKey || settings.fileKey;\n const bodyKey = options.bodyKey || settings.bodyKey;\n\n for (let i = 0; i < options.files.length; i += 1) {\n if (fileKey) {\n formData.append(fileKey, options.files[i]);\n }\n }\n\n if (bodyKey) {\n formData.append(bodyKey, requestData);\n }\n requestData = formData;\n }\n // [end] handling files\n\n const response = await fetch(options.api, {\n method,\n headers: {\n 'ui-request-id': requestId,\n 'Content-Type': 'application/json',\n ...extraHeaders,\n },\n signal: abort.controller.signal,\n body: requestData,\n });\n\n checkModule(settings, 'cancelation', abort.drop);\n\n let result: unknown;\n const responseType = options.responseType || 'json';\n\n if (responseType === 'text') {\n result = await response.text();\n } else if (responseType === 'blob') {\n result = await response.blob();\n } else {\n // default: json\n result = await response.json();\n }\n\n if (!response.ok) {\n if (withCallback) options.onResult!(result);\n return rejectWithValue(response);\n }\n\n if (withCallback) options.onResult!(result);\n return { result, startedAt, endedAt: new Date().toUTCString() };\n } catch (error) {\n checkModule(settings, 'cancelation', abort.drop);\n\n if (withCallback) options.onResult!(error);\n\n if (error instanceof Error && error.name === 'AbortError') {\n return rejectWithValue({ message: 'Request was cancelled', cancelled: true });\n }\n\n return rejectWithValue({ message: error instanceof Error ? error.message : 'Unknown error occurred' });\n }\n };\n\n if (settings.modules.includes('queryQueue')) {\n return queryQueue.enqueue(executeRequest);\n }\n\n return executeRequest();\n },\n);\n\n","import { type CdeebeeListStrategy, type CdeebeeState } from './types';\nimport { isRecord, mergeDeepRight, omit } from './helpers';\n\ntype ResponseValue = Record<string, unknown>;\n\ntype IResponse = Record<string, ResponseValue>;\n\ntype StorageData = Record<string, unknown>;\n\nfunction isDataWithPrimaryKey(value: unknown): value is { data: unknown[]; primaryKey: string } {\n return (\n isRecord(value) &&\n Array.isArray(value.data) &&\n typeof value.primaryKey === 'string'\n );\n}\nfunction normalizeDataWithPrimaryKey(data: unknown[], primaryKey: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const item of data) {\n if (isRecord(item) && primaryKey in item) {\n const key = String(item[primaryKey]);\n result[key] = item;\n }\n }\n\n return result;\n}\n\nfunction applyStrategy(\n existingValue: StorageData,\n newValue: StorageData | ResponseValue,\n strategy: string,\n key: string\n): ResponseValue {\n if (strategy === 'replace') {\n return newValue as ResponseValue;\n } else if (strategy === 'merge') {\n return mergeDeepRight(existingValue, newValue as StorageData) as ResponseValue;\n } else if (strategy === 'skip') {\n return existingValue as ResponseValue;\n } else {\n console.warn(`Cdeebee: Unknown strategy \"${strategy}\" for key \"${key}\". Skipping normalization.`);\n return mergeDeepRight(existingValue, newValue as StorageData) as ResponseValue;\n }\n}\n\nexport function defaultNormalize<T>(\n cdeebee: CdeebeeState<T>,\n response: IResponse,\n strategyList: CdeebeeListStrategy<T>\n): Record<string, ResponseValue> {\n const keyList = Object.keys(response);\n const currentStorage = isRecord(cdeebee.storage) ? (cdeebee.storage as Record<string, unknown>) : {};\n\n const result = { ...currentStorage } as Record<string, ResponseValue>;\n const keyListToOmit = new Set<string>();\n\n for (const key of keyList) {\n const responseValue = response[key];\n\n if (responseValue === null || responseValue === undefined || typeof responseValue === 'string') {\n keyListToOmit.add(key);\n continue;\n }\n\n const strategy = strategyList[key as keyof T] ?? 'merge';\n\n // For 'skip' strategy, if key doesn't exist in storage, skip it entirely\n if (strategy === 'skip' && !(key in currentStorage)) {\n continue;\n }\n\n const existingValue = key in currentStorage ? (currentStorage[key] as StorageData) : {};\n\n if (isDataWithPrimaryKey(responseValue)) {\n const normalizedValue = normalizeDataWithPrimaryKey(responseValue.data, responseValue.primaryKey);\n result[key] = applyStrategy(existingValue, normalizedValue, strategy, key);\n continue;\n }\n\n if (isRecord(responseValue)) {\n result[key] = applyStrategy(existingValue, responseValue as StorageData, strategy, key);\n } else {\n result[key] = responseValue;\n }\n }\n\n return keyListToOmit.size > 0 ? omit(Array.from(keyListToOmit), result) : result;\n}\n","import { createSlice, current, type PayloadAction } from '@reduxjs/toolkit';\n\nimport { type CdeebeeSettings, type CdeebeeState, type CdeebeeValueList, type CdeebeeListStrategy } from './types';\nimport { checkModule, mergeDeepRight, batchingUpdate, extractLastResultIdList } from './helpers';\nimport { abortQuery } from './abortController';\nimport { request } from './request';\nimport { defaultNormalize } from './storage';\n\nconst initialState: CdeebeeState<unknown> = {\n settings: {\n modules: ['history', 'listener', 'storage', 'cancelation'],\n fileKey: 'file',\n bodyKey: 'value',\n listStrategy: {},\n mergeWithData: {},\n mergeWithHeaders: {},\n },\n storage: {},\n request: {\n active: [],\n errors: {},\n done: {},\n lastResultIdList: {},\n },\n};\n\nexport const factory = <T>(settings: CdeebeeSettings<T>, storage?: T) => {\n const slice = createSlice({\n name: 'cdeebee',\n initialState: mergeDeepRight(initialState, { settings, storage: storage ?? {} }) as CdeebeeState<T>,\n reducers: {\n set(state, action: { payload: CdeebeeValueList<T> }) {\n // Directly mutate state.storage using Immer Draft\n // This is more performant than creating a new object\n // Immer will track changes and create minimal updates\n batchingUpdate(state.storage as Record<string, unknown>, action.payload);\n },\n historyClear(state, action: PayloadAction<string | undefined>) {\n const api = action.payload;\n\n if (api) {\n delete state.request.done[api];\n delete state.request.errors[api];\n } else {\n state.request.done = {};\n state.request.errors = {};\n }\n }\n },\n extraReducers: builder => {\n builder\n .addCase(request.pending, (state, action) => {\n const api = action.meta.arg.api;\n const requestId = action.meta.requestId;\n\n if (action.meta.arg.historyClear) {\n checkModule(state.settings, 'history', () => {\n delete state.request.done[api];\n delete state.request.errors[api];\n });\n }\n\n checkModule(state.settings, 'cancelation', () => {\n abortQuery(api, requestId);\n });\n checkModule(state.settings, 'listener', () => {\n state.request.active.push({ api, requestId });\n });\n })\n .addCase(request.fulfilled, (state, action) => {\n const requestId = action.meta.requestId;\n const api = action.meta.arg.api;\n\n checkModule(state.settings, 'listener', () => {\n state.request.active = state.request.active.filter(q => !(q.api === api && q.requestId === requestId));\n });\n checkModule(state.settings, 'history', () => {\n if (!state.request.done[api]) state.request.done[api] = [];\n state.request.done[api].push({ api, request: action.payload, requestId });\n });\n checkModule(state.settings, 'storage', () => {\n if (action.meta.arg.ignore) {\n return;\n }\n\n const strategyList = (action.meta.arg.listStrategy ?? state.settings.listStrategy ?? {}) as CdeebeeListStrategy<T>;\n const normalize = action.meta.arg.normalize ?? state.settings.normalize ?? defaultNormalize;\n\n const currentState = current(state) as CdeebeeState<T>;\n // Type assertion is safe here because we've already checked isRecord\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const normalizedData = normalize(currentState, action.payload.result as any, strategyList);\n\n // Normalize already handles merge/replace/skip and preserves keys not in response\n // Simply apply the result\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (state.storage as any) = normalizedData;\n\n // Extract and store result IDs for filtering per list\n state.request.lastResultIdList[api] = extractLastResultIdList(action.payload.result);\n });\n })\n .addCase(request.rejected, (state, action) => {\n const requestId = action.meta.requestId;\n const api = action.meta.arg.api;\n\n checkModule(state.settings, 'listener', () => {\n state.request.active = state.request.active.filter(q => !(q.api === api && q.requestId === requestId));\n });\n checkModule(state.settings, 'history', () => {\n if (!state.request.errors[api]) state.request.errors[api] = [];\n state.request.errors[api].push({ requestId: requestId, api, request: action.error });\n });\n });\n },\n });\n\n return slice;\n};\n","import { useSelector } from 'react-redux';\nimport { type CdeebeeState } from '../reducer/types';\n\n/**\n * Generic hook factory that creates a selector hook for cdeebee state.\n * This allows the hooks to work with any Redux root state structure.\n *\n * @template RootState - The shape of the Redux root state\n * @template Storage - The shape of the cdeebee storage\n * @param selectCdeebee - Function to select the cdeebee slice from root state\n * @returns An object containing all cdeebee hooks\n */\nexport function createCdeebeeHooks<RootState, Storage>(\n selectCdeebee: (state: RootState) => CdeebeeState<Storage>\n) {\n /**\n * Check if any of the specified APIs are currently loading.\n *\n * @param apiList - Array of API endpoints to check\n * @returns true if any of the APIs are currently active/loading\n *\n * @example\n * const isLoading = useLoading(['/api/forums', '/api/threads']);\n * if (isLoading) return <Spinner />;\n */\n function useLoading(apiList: string[]): boolean {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.active.some(q => apiList.includes(q.api));\n });\n }\n\n /**\n * Get the successful request history for a specific API endpoint.\n *\n * @param api - The API endpoint\n * @returns Array of successful request history entries\n *\n * @example\n * const history = useRequestHistory('/api/forums');\n * console.log(`Made ${history.length} successful requests`);\n */\n function useRequestHistory(api: string) {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.done[api] ?? [];\n });\n }\n\n /**\n * Get the error history for a specific API endpoint.\n *\n * @param api - The API endpoint\n * @returns Array of error history entries\n *\n * @example\n * const errors = useRequestErrors('/api/forums');\n * if (errors.length > 0) {\n * console.error('Last error:', errors[errors.length - 1]);\n * }\n */\n function useRequestErrors(api: string) {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.errors[api] ?? [];\n });\n }\n\n /**\n * Get a specific list from storage with full type safety.\n *\n * @param listName - The name of the list in storage\n * @returns The list data\n *\n * @example\n * const forums = useStorageList('forumList');\n * const forumArray = Object.values(forums);\n */\n function useStorageList<K extends keyof Storage>(listName: K): Storage[K] {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.storage[listName];\n });\n }\n\n /**\n * Get the entire cdeebee storage.\n *\n * @returns The complete storage object\n *\n * @example\n * const storage = useStorage();\n * console.log(Object.keys(storage)); // ['forumList', 'threadList', ...]\n */\n function useStorage(): Storage {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.storage;\n });\n }\n\n /**\n * Check if any request is currently loading (across all APIs).\n *\n * @returns true if any request is active\n *\n * @example\n * const isAnythingLoading = useIsLoading();\n * if (isAnythingLoading) return <GlobalSpinner />;\n */\n function useIsLoading(): boolean {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.active.length > 0;\n });\n }\n\n /**\n * Get the list of IDs returned by the last successful request to an API for a specific list.\n * Useful for filtering storage data to show only results from a specific request.\n *\n * @param api - The API endpoint\n * @param listName - The name of the list in storage (typed from Storage)\n * @returns Array of primary key IDs from the last response for that list\n *\n * @example\n * const productList = useStorageList('productList');\n * const lastIDList = useLastResultIdList('/api/search', 'productList');\n * const displayResults = lastIDList.map(id => productList[id]).filter(Boolean);\n */\n function useLastResultIdList<K extends keyof Storage>(api: string, listName: K): string[] {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.lastResultIdList[api]?.[listName as string] ?? [];\n });\n }\n\n return {\n useLoading,\n useRequestHistory,\n useRequestErrors,\n useStorageList,\n useStorage,\n useIsLoading,\n useLastResultIdList,\n };\n}\n","import { useSelector } from 'react-redux';\nimport { type CdeebeeState } from '../reducer/types';\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param apiList - Array of API endpoints to check\n * @returns true if any of the APIs are currently active/loading\n *\n * @example\n * const isLoading = useLoading(['/api/forums', '/api/threads']);\n */\nexport function useLoading<Storage = unknown>(apiList: string[]): boolean {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.active.some(q => apiList.includes(q.api));\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param api - The API endpoint\n * @returns Array of successful request history entries\n */\nexport function useRequestHistory<Storage = unknown>(api: string) {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.done[api] ?? [];\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param api - The API endpoint\n * @returns Array of error history entries\n */\nexport function useRequestErrors<Storage = unknown>(api: string) {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.errors[api] ?? [];\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param listName - The name of the list in storage\n * @returns The list data\n */\nexport function useStorageList<Storage, K extends keyof Storage>(listName: K): Storage[K] {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.storage[listName];\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @returns The complete storage object\n */\nexport function useStorage<Storage>(): Storage {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.storage;\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @returns true if any request is active\n */\nexport function useIsLoading<Storage = unknown>(): boolean {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.active.length > 0;\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * Get the list of IDs returned by the last successful request to an API for a specific list.\n * Useful for filtering storage data to show only results from a specific request.\n *\n * @param api - The API endpoint\n * @param listName - The name of the list in storage (typed from Storage)\n * @returns Array of primary key IDs from the last response for that list\n *\n * @example\n * const productList = useStorageList('productList');\n * const lastIDList = useLastResultIdList('/api/search', 'productList');\n * const displayResults = lastIDList.map(id => productList[id]).filter(Boolean);\n */\nexport function useLastResultIdList<Storage, K extends keyof Storage>(api: string, listName: K): string[] {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.lastResultIdList[api]?.[listName as string] ?? [];\n });\n}\n"],"names":["checkModule","settings","module","result","isRecord","value","mergeDeepRight","left","right","rightRecord","key","leftValue","rightValue","omit","keys","obj","extractLastResultIdList","response","listName","primaryKey","idList","item","batchingUpdate","state","valueList","path","current","j","pathKey","index","nextIsNumeric","next","AbortControllerStore","api","requestId","controller","apiSet","excludeRequestId","requestIDList","abortStore","abortQuery","currentRequestId","abortManager","signal","cleanup","QueryQueue","task","previousPromise","queryQueue","request","createAsyncThunk","options","rejectWithValue","getState","startedAt","abort","withCallback","executeRequest","method","body","headers","extraHeaders","b","requestData","formData","fileKey","bodyKey","i","responseType","error","isDataWithPrimaryKey","normalizeDataWithPrimaryKey","data","applyStrategy","existingValue","newValue","strategy","defaultNormalize","cdeebee","strategyList","keyList","currentStorage","keyListToOmit","responseValue","normalizedValue","initialState","factory","storage","createSlice","action","builder","q","normalize","currentState","normalizedData","createCdeebeeHooks","selectCdeebee","useLoading","apiList","useSelector","useRequestHistory","useRequestErrors","useStorageList","useStorage","useIsLoading","useLastResultIdList","_a"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@recats/cdeebee",
3
- "version": "3.0.0-beta.12",
3
+ "version": "3.0.0-beta.14",
4
4
  "description": "React Redux data-logic library",
5
5
  "repository": "git@github.com:recats/cdeebee.git",
6
6
  "author": "recats",