@recats/cdeebee 3.0.0-beta.7 → 3.0.0-beta.8
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 +113 -4
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +131 -115
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ For example, a forum application might have this structure:
|
|
|
36
36
|
}
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
After fetching data, the storage might look like:
|
|
39
|
+
After fetching data from the API (which returns data in the format `{ data: [...], primaryKey: 'id' }`), cdeebee automatically normalizes it and the storage might look like:
|
|
40
40
|
|
|
41
41
|
```typescript
|
|
42
42
|
{
|
|
@@ -52,6 +52,8 @@ After fetching data, the storage might look like:
|
|
|
52
52
|
}
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
**Note:** The API should return list data in the format `{ data: [...], primaryKey: 'fieldName' }`. cdeebee automatically converts this format into the normalized storage structure shown above. See the [API Response Format](#api-response-format) section for details.
|
|
56
|
+
|
|
55
57
|
### Modules
|
|
56
58
|
|
|
57
59
|
cdeebee uses a modular architecture with the following modules:
|
|
@@ -60,6 +62,7 @@ cdeebee uses a modular architecture with the following modules:
|
|
|
60
62
|
- **`history`**: Tracks request history (successful and failed requests)
|
|
61
63
|
- **`listener`**: Tracks active requests for loading states
|
|
62
64
|
- **`cancelation`**: Manages request cancellation (automatically cancels previous requests to the same API)
|
|
65
|
+
- **`queryQueue`**: Processes requests sequentially in the order they were sent, ensuring they complete and are stored in the correct sequence
|
|
63
66
|
|
|
64
67
|
## Quick Start
|
|
65
68
|
|
|
@@ -79,7 +82,7 @@ interface Storage {
|
|
|
79
82
|
// Create cdeebee slice
|
|
80
83
|
export const cdeebeeSlice = factory<Storage>(
|
|
81
84
|
{
|
|
82
|
-
modules: ['history', 'listener', 'cancelation', 'storage'],
|
|
85
|
+
modules: ['history', 'listener', 'cancelation', 'storage', 'queryQueue'],
|
|
83
86
|
fileKey: 'file',
|
|
84
87
|
bodyKey: 'value',
|
|
85
88
|
listStrategy: {
|
|
@@ -164,7 +167,7 @@ The `factory` function accepts a settings object with the following options:
|
|
|
164
167
|
|
|
165
168
|
```typescript
|
|
166
169
|
interface CdeebeeSettings<T> {
|
|
167
|
-
modules: CdeebeeModule[]; // Active modules: 'history' | 'listener' | 'storage' | 'cancelation'
|
|
170
|
+
modules: CdeebeeModule[]; // Active modules: 'history' | 'listener' | 'storage' | 'cancelation' | 'queryQueue'
|
|
168
171
|
fileKey: string; // Key name for file uploads in FormData
|
|
169
172
|
bodyKey: string; // Key name for request body in FormData
|
|
170
173
|
listStrategy?: CdeebeeListStrategy<T>; // Merge strategy per list: 'merge' | 'replace'
|
|
@@ -209,7 +212,32 @@ listStrategy: {
|
|
|
209
212
|
|
|
210
213
|
## API Response Format
|
|
211
214
|
|
|
212
|
-
cdeebee expects API responses in a
|
|
215
|
+
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.
|
|
216
|
+
|
|
217
|
+
### List Format
|
|
218
|
+
|
|
219
|
+
For lists (collections of entities), the API should return data in the following format:
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
{
|
|
223
|
+
forumList: {
|
|
224
|
+
data: [
|
|
225
|
+
{ id: 1, title: 'Forum 1' },
|
|
226
|
+
{ id: 2, title: 'Forum 2' },
|
|
227
|
+
],
|
|
228
|
+
primaryKey: 'id',
|
|
229
|
+
},
|
|
230
|
+
threadList: {
|
|
231
|
+
data: [
|
|
232
|
+
{ id: 101, title: 'Thread 1', forumID: 1 },
|
|
233
|
+
{ id: 102, title: 'Thread 2', forumID: 1 },
|
|
234
|
+
],
|
|
235
|
+
primaryKey: 'id',
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
cdeebee automatically converts this format into normalized storage:
|
|
213
241
|
|
|
214
242
|
```typescript
|
|
215
243
|
{
|
|
@@ -219,10 +247,62 @@ cdeebee expects API responses in a normalized format where data is already organ
|
|
|
219
247
|
},
|
|
220
248
|
threadList: {
|
|
221
249
|
101: { id: 101, title: 'Thread 1', forumID: 1 },
|
|
250
|
+
102: { id: 102, title: 'Thread 2', forumID: 1 },
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
The `primaryKey` field specifies which property of each item should be used as the key in the normalized structure. The `primaryKey` value is converted to a string to ensure consistent key types.
|
|
256
|
+
|
|
257
|
+
**Example:**
|
|
258
|
+
|
|
259
|
+
If your API returns:
|
|
260
|
+
```typescript
|
|
261
|
+
{
|
|
262
|
+
sessionList: {
|
|
263
|
+
data: [
|
|
264
|
+
{
|
|
265
|
+
sessionID: 1,
|
|
266
|
+
token: 'da6ec385bc7e4f84a510c3ecca07f3',
|
|
267
|
+
expiresAt: '2034-03-28T22:36:09'
|
|
268
|
+
}
|
|
269
|
+
],
|
|
270
|
+
primaryKey: 'sessionID',
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
It will be automatically normalized to:
|
|
276
|
+
```typescript
|
|
277
|
+
{
|
|
278
|
+
sessionList: {
|
|
279
|
+
'1': {
|
|
280
|
+
sessionID: 1,
|
|
281
|
+
token: 'da6ec385bc7e4f84a510c3ecca07f3',
|
|
282
|
+
expiresAt: '2034-03-28T22:36:09'
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Non-List Data
|
|
289
|
+
|
|
290
|
+
For non-list data (configuration objects, simple values, etc.), you can return them as regular objects:
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
{
|
|
294
|
+
config: {
|
|
295
|
+
theme: 'dark',
|
|
296
|
+
language: 'en',
|
|
297
|
+
},
|
|
298
|
+
userPreferences: {
|
|
299
|
+
notifications: true,
|
|
222
300
|
}
|
|
223
301
|
}
|
|
224
302
|
```
|
|
225
303
|
|
|
304
|
+
These will be stored as-is in the storage.
|
|
305
|
+
|
|
226
306
|
## Advanced Usage
|
|
227
307
|
|
|
228
308
|
### File Uploads
|
|
@@ -326,6 +406,34 @@ dispatch(request({ api: '/api/data', body: { query: 'slow' } }));
|
|
|
326
406
|
dispatch(request({ api: '/api/data', body: { query: 'fast' } }));
|
|
327
407
|
```
|
|
328
408
|
|
|
409
|
+
### Sequential Request Processing (queryQueue)
|
|
410
|
+
|
|
411
|
+
When the `queryQueue` module is enabled, all requests are processed sequentially in the order they were sent. This ensures that:
|
|
412
|
+
|
|
413
|
+
- Requests complete in the exact order they were dispatched
|
|
414
|
+
- Data is stored in the store in the correct sequence
|
|
415
|
+
- Even if a faster request is sent after a slower one, it will wait for the previous request to complete
|
|
416
|
+
|
|
417
|
+
This is particularly useful when you need to maintain data consistency and ensure that updates happen in the correct order.
|
|
418
|
+
|
|
419
|
+
```typescript
|
|
420
|
+
// Enable queryQueue module
|
|
421
|
+
const cdeebeeSlice = factory<Storage>({
|
|
422
|
+
modules: ['history', 'listener', 'storage', 'queryQueue'],
|
|
423
|
+
// ... other settings
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
// Send multiple requests - they will be processed sequentially
|
|
427
|
+
dispatch(request({ api: '/api/data', body: { id: 1 } })); // Completes first
|
|
428
|
+
dispatch(request({ api: '/api/data', body: { id: 2 } })); // Waits for #1, then completes
|
|
429
|
+
dispatch(request({ api: '/api/data', body: { id: 3 } })); // Waits for #2, then completes
|
|
430
|
+
|
|
431
|
+
// Even if request #3 is faster, it will still complete last
|
|
432
|
+
// All requests are stored in the store in order: 1 → 2 → 3
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
**Note:** The `queryQueue` module processes requests sequentially across all APIs. If you need parallel processing for different APIs, you would need separate cdeebee instances or disable the module for those specific requests.
|
|
436
|
+
|
|
329
437
|
### Manual State Updates
|
|
330
438
|
|
|
331
439
|
You can manually update the storage using the `set` action:
|
|
@@ -386,6 +494,7 @@ export type {
|
|
|
386
494
|
CdeebeeRequestOptions,
|
|
387
495
|
CdeebeeValueList,
|
|
388
496
|
CdeebeeActiveRequest,
|
|
497
|
+
CdeebeeModule,
|
|
389
498
|
} from '@recats/cdeebee';
|
|
390
499
|
```
|
|
391
500
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("@reduxjs/toolkit");function y(r,
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("@reduxjs/toolkit");function y(t,r,n){t.modules.includes(r)&&n()}function f(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function p(t,r){if(!f(t)||!f(r))return r;const n={...t},o=r;for(const e in o)if(Object.prototype.hasOwnProperty.call(o,e)){const a=n[e],s=o[e];f(a)&&f(s)&&!Array.isArray(a)&&!Array.isArray(s)?n[e]=p(a,s):n[e]=s}return n}function L(t,r){const n={...r};for(const o of t)delete n[o];return n}function P(t,r){for(let n=0;n<r.length;n++){const o=r[n],e=o.key,a=o.value;if(e.length===0)continue;let s=t;for(let i=0;i<e.length-1;i++){const c=e[i];if(Array.isArray(s)){const l=typeof c=="number"?c:Number(c);(!(l in s)||!f(s[l]))&&(s[l]={}),s=s[l]}else{const l=String(c);if(!(l in s)){const d=typeof e[i+1]=="number"||!isNaN(Number(e[i+1]))&&String(Number(e[i+1]))===String(e[i+1]);s[l]=d?[]:{}}const u=s[l];s=Array.isArray(u)||f(u)?u:{}}}Array.isArray(s)||(s[String(e[e.length-1])]=a)}}class T{constructor(){this.byRequestId=new Map,this.byApi=new Map}add(r,n,o){const e={requestId:n,controller:o,api:r};this.byRequestId.set(n,e),this.byApi.has(r)||this.byApi.set(r,new Set),this.byApi.get(r).add(n)}delete(r){const n=this.byRequestId.get(r);if(!n)return;this.byRequestId.delete(r);const o=this.byApi.get(n.api);o&&(o.delete(r),o.size===0&&this.byApi.delete(n.api))}abortAllForApi(r,n){const o=this.byApi.get(r);o&&o.forEach(e=>{if(e!==n){const a=this.byRequestId.get(e);a&&(a.controller.abort(),this.delete(e))}})}}const w=new T;function x(t,r){w.abortAllForApi(t,r)}function N(t,r,n){const o=new AbortController,e=()=>{w.delete(n)};return t.addEventListener("abort",()=>{o.abort(),e()}),{controller:o,init:()=>w.add(r,n,o),drop:e}}class j{constructor(){this.currentPromise=Promise.resolve(),this.queueLength=0}async enqueue(r){this.queueLength++;const n=this.currentPromise;return this.currentPromise=n.then(()=>r(),()=>r()).finally(()=>{this.queueLength--}),this.currentPromise}getQueueLength(){return this.queueLength}clear(){this.queueLength=0}}const I=new j,m=S.createAsyncThunk("cdeebee/request",async(t,{rejectWithValue:r,getState:n,requestId:o,signal:e})=>{const a=new Date().toUTCString(),{cdeebee:{settings:s}}=n(),i=N(e,t.api,o),c=t.onResult&&typeof t.onResult=="function";y(s,"cancelation",i.init);const l=async()=>{try{const{method:u="POST",body:d,headers:z={}}=t,C={...s.mergeWithHeaders??{},...z},v={...s.mergeWithData??{},...d??{}};let b=JSON.stringify(v);if(t.files){const q=new FormData,R=t.fileKey||s.fileKey,K=t.bodyKey||s.bodyKey;for(let A=0;A<t.files.length;A+=1)R&&q.append(R,t.files[A]);K&&q.append(K,b),b=q}const h=await fetch(t.api,{method:u,headers:{"ui-request-id":o,"Content-Type":"application/json",...C},signal:i.controller.signal,body:b});y(s,"cancelation",i.drop);let g;const k=t.responseType||"json";return k==="text"?g=await h.text():k==="blob"?g=await h.blob():g=await h.json(),h.ok?(c&&t.onResult(g),{result:g,startedAt:a,endedAt:new Date().toUTCString()}):(c&&t.onResult(g),r(h))}catch(u){return y(s,"cancelation",i.drop),c&&t.onResult(u),u instanceof Error&&u.name==="AbortError"?r({message:"Request was cancelled",cancelled:!0}):r({message:u instanceof Error?u.message:"Unknown error occurred"})}};return s.modules.includes("queryQueue")?I.enqueue(l):l()});function O(t){return f(t)&&Array.isArray(t.data)&&typeof t.primaryKey=="string"}function Q(t,r){const n={};for(const o of t)if(f(o)&&r in o){const e=String(o[r]);n[e]=o}return n}function D(t,r,n,o){return n==="replace"?r:(n==="merge"||console.warn(`Cdeebee: Unknown strategy "${n}" for key "${o}". Skipping normalization.`),p(t,r))}function U(t,r,n){const o=Object.keys(r),e=f(t.storage)?t.storage:{},a={...e},s=new Set;for(const i of o){const c=r[i];if(c==null||typeof c=="string"){s.add(i);continue}const l=n[i]??"merge",u=i in e?e[i]:{};if(O(c)){const d=Q(c.data,c.primaryKey);a[i]=D(u,d,l,i);continue}f(c)?a[i]=D(u,c,l,i):a[i]=c}return s.size>0?L(Array.from(s),a):a}const E={settings:{modules:["history","listener","storage","cancelation"],fileKey:"file",bodyKey:"value",listStrategy:{},mergeWithData:{},mergeWithHeaders:{}},storage:{},request:{active:[],errors:{},done:{}}},M=(t,r)=>S.createSlice({name:"cdeebee",initialState:p(E,{settings:t,storage:r??{}}),reducers:{set(o,e){P(o.storage,e.payload)}},extraReducers:o=>{o.addCase(m.pending,(e,a)=>{const s=a.meta.arg.api,i=a.meta.requestId;y(e.settings,"cancelation",()=>{x(s,i)}),y(e.settings,"listener",()=>{e.request.active.push({api:s,requestId:i})})}).addCase(m.fulfilled,(e,a)=>{const s=a.meta.requestId,i=a.meta.arg.api;y(e.settings,"listener",()=>{e.request.active=e.request.active.filter(c=>!(c.api===i&&c.requestId===s))}),y(e.settings,"history",()=>{e.request.done[i]||(e.request.done[i]=[]),e.request.done[i].push({api:i,request:a.payload,requestId:s})}),y(e.settings,"storage",()=>{if(a.meta.arg.ignore)return;const c=a.meta.arg.listStrategy??e.settings.listStrategy??{},l=a.meta.arg.normalize??e.settings.normalize??U,u=S.current(e),d=l(u,a.payload.result,c);e.storage=d})}).addCase(m.rejected,(e,a)=>{const s=a.meta.requestId,i=a.meta.arg.api;y(e.settings,"listener",()=>{e.request.active=e.request.active.filter(c=>!(c.api===i&&c.requestId===s))}),y(e.settings,"history",()=>{e.request.errors[i]||(e.request.errors[i]=[]),e.request.errors[i].push({requestId:s,api:i,request:a.error})})})}});exports.batchingUpdate=P;exports.factory=M;exports.request=m;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -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"],"sourcesContent":["import { type CdeebeeSettings, type CdeebeeModule, CdeebeeValueList } from './types';\n\nexport function checkModule(settings: 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\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 isNormalized = isRecord(responseValue);\n const strategy = strategyList[key as keyof T] ?? 'merge';\n\n if (isNormalized) {\n const existingValue = key in currentStorage ? (currentStorage[key] as StorageData) : {};\n\n if (strategy === 'replace') {\n result[key] = responseValue as ResponseValue;\n } else if (strategy === 'merge') {\n result[key] = mergeDeepRight(existingValue, responseValue as StorageData) as ResponseValue;\n } else {\n console.warn(`Cdeebee: Unknown strategy \"${strategy}\" for key \"${key}\". Skipping normalization.`);\n result[key] = mergeDeepRight(existingValue, responseValue as StorageData) as ResponseValue;\n }\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 } from '@reduxjs/toolkit';\n\nimport { type CdeebeeSettings, type CdeebeeState, type CdeebeeValueList } 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 },\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 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 ?? {};\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 const normalizedData = normalize(currentState, action.payload.result as Record<string, Record<string, unknown>>, strategyList);\n\n // Normalize already handles merge/replace 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"],"names":["checkModule","settings","module","result","isRecord","value","mergeDeepRight","left","right","rightRecord","key","leftValue","rightValue","omit","keys","obj","batchingUpdate","state","valueList","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","i","response","responseType","error","defaultNormalize","cdeebee","strategyList","keyList","currentStorage","keyListToOmit","responseValue","isNormalized","strategy","existingValue","initialState","factory","storage","createSlice","action","builder","q","normalize","currentState","normalizedData"],"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"],"sourcesContent":["import { type CdeebeeSettings, type CdeebeeModule, CdeebeeValueList } from './types';\n\nexport function checkModule(settings: 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 {\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 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 } from '@reduxjs/toolkit';\n\nimport { type CdeebeeSettings, type CdeebeeState, type CdeebeeValueList } 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 },\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 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 ?? {};\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 const normalizedData = normalize(currentState, action.payload.result as Record<string, Record<string, unknown>>, strategyList);\n\n // Normalize already handles merge/replace 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"],"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"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,100 +1,100 @@
|
|
|
1
|
-
import { createAsyncThunk as
|
|
2
|
-
function y(
|
|
3
|
-
|
|
1
|
+
import { createAsyncThunk as P, createSlice as x, current as L } from "@reduxjs/toolkit";
|
|
2
|
+
function y(t, r, n) {
|
|
3
|
+
t.modules.includes(r) && n();
|
|
4
4
|
}
|
|
5
|
-
function f(
|
|
6
|
-
return
|
|
5
|
+
function f(t) {
|
|
6
|
+
return t !== null && typeof t == "object" && !Array.isArray(t);
|
|
7
7
|
}
|
|
8
|
-
function
|
|
9
|
-
if (!f(
|
|
10
|
-
return
|
|
11
|
-
const
|
|
12
|
-
for (const e in
|
|
13
|
-
if (Object.prototype.hasOwnProperty.call(
|
|
14
|
-
const
|
|
15
|
-
f(
|
|
8
|
+
function h(t, r) {
|
|
9
|
+
if (!f(t) || !f(r))
|
|
10
|
+
return r;
|
|
11
|
+
const n = { ...t }, o = r;
|
|
12
|
+
for (const e in o)
|
|
13
|
+
if (Object.prototype.hasOwnProperty.call(o, e)) {
|
|
14
|
+
const a = n[e], s = o[e];
|
|
15
|
+
f(a) && f(s) && !Array.isArray(a) && !Array.isArray(s) ? n[e] = h(a, s) : n[e] = s;
|
|
16
16
|
}
|
|
17
|
-
return
|
|
17
|
+
return n;
|
|
18
18
|
}
|
|
19
|
-
function
|
|
20
|
-
const
|
|
21
|
-
for (const
|
|
22
|
-
delete
|
|
23
|
-
return
|
|
19
|
+
function v(t, r) {
|
|
20
|
+
const n = { ...r };
|
|
21
|
+
for (const o of t)
|
|
22
|
+
delete n[o];
|
|
23
|
+
return n;
|
|
24
24
|
}
|
|
25
|
-
function N(
|
|
26
|
-
for (let
|
|
27
|
-
const
|
|
25
|
+
function N(t, r) {
|
|
26
|
+
for (let n = 0; n < r.length; n++) {
|
|
27
|
+
const o = r[n], e = o.key, a = o.value;
|
|
28
28
|
if (e.length === 0)
|
|
29
29
|
continue;
|
|
30
|
-
let
|
|
31
|
-
for (let
|
|
32
|
-
const c = e[
|
|
33
|
-
if (Array.isArray(
|
|
30
|
+
let s = t;
|
|
31
|
+
for (let i = 0; i < e.length - 1; i++) {
|
|
32
|
+
const c = e[i];
|
|
33
|
+
if (Array.isArray(s)) {
|
|
34
34
|
const l = typeof c == "number" ? c : Number(c);
|
|
35
|
-
(!(l in
|
|
35
|
+
(!(l in s) || !f(s[l])) && (s[l] = {}), s = s[l];
|
|
36
36
|
} else {
|
|
37
37
|
const l = String(c);
|
|
38
|
-
if (!(l in
|
|
39
|
-
const d = typeof e[
|
|
40
|
-
|
|
38
|
+
if (!(l in s)) {
|
|
39
|
+
const d = typeof e[i + 1] == "number" || !isNaN(Number(e[i + 1])) && String(Number(e[i + 1])) === String(e[i + 1]);
|
|
40
|
+
s[l] = d ? [] : {};
|
|
41
41
|
}
|
|
42
|
-
const u =
|
|
43
|
-
|
|
42
|
+
const u = s[l];
|
|
43
|
+
s = Array.isArray(u) || f(u) ? u : {};
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
Array.isArray(
|
|
46
|
+
Array.isArray(s) || (s[String(e[e.length - 1])] = a);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
class
|
|
49
|
+
class T {
|
|
50
50
|
constructor() {
|
|
51
51
|
this.byRequestId = /* @__PURE__ */ new Map(), this.byApi = /* @__PURE__ */ new Map();
|
|
52
52
|
}
|
|
53
|
-
add(
|
|
54
|
-
const e = { requestId:
|
|
55
|
-
this.byRequestId.set(
|
|
53
|
+
add(r, n, o) {
|
|
54
|
+
const e = { requestId: n, controller: o, api: r };
|
|
55
|
+
this.byRequestId.set(n, e), this.byApi.has(r) || this.byApi.set(r, /* @__PURE__ */ new Set()), this.byApi.get(r).add(n);
|
|
56
56
|
}
|
|
57
|
-
delete(
|
|
58
|
-
const
|
|
59
|
-
if (!
|
|
60
|
-
this.byRequestId.delete(
|
|
61
|
-
const
|
|
62
|
-
|
|
57
|
+
delete(r) {
|
|
58
|
+
const n = this.byRequestId.get(r);
|
|
59
|
+
if (!n) return;
|
|
60
|
+
this.byRequestId.delete(r);
|
|
61
|
+
const o = this.byApi.get(n.api);
|
|
62
|
+
o && (o.delete(r), o.size === 0 && this.byApi.delete(n.api));
|
|
63
63
|
}
|
|
64
|
-
abortAllForApi(
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
if (e !==
|
|
68
|
-
const
|
|
69
|
-
|
|
64
|
+
abortAllForApi(r, n) {
|
|
65
|
+
const o = this.byApi.get(r);
|
|
66
|
+
o && o.forEach((e) => {
|
|
67
|
+
if (e !== n) {
|
|
68
|
+
const a = this.byRequestId.get(e);
|
|
69
|
+
a && (a.controller.abort(), this.delete(e));
|
|
70
70
|
}
|
|
71
71
|
});
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
const S = new
|
|
75
|
-
function
|
|
76
|
-
S.abortAllForApi(
|
|
74
|
+
const S = new T();
|
|
75
|
+
function I(t, r) {
|
|
76
|
+
S.abortAllForApi(t, r);
|
|
77
77
|
}
|
|
78
|
-
function
|
|
79
|
-
const
|
|
80
|
-
S.delete(
|
|
78
|
+
function j(t, r, n) {
|
|
79
|
+
const o = new AbortController(), e = () => {
|
|
80
|
+
S.delete(n);
|
|
81
81
|
};
|
|
82
|
-
return
|
|
83
|
-
|
|
82
|
+
return t.addEventListener("abort", () => {
|
|
83
|
+
o.abort(), e();
|
|
84
84
|
}), {
|
|
85
|
-
controller:
|
|
86
|
-
init: () => S.add(
|
|
85
|
+
controller: o,
|
|
86
|
+
init: () => S.add(r, n, o),
|
|
87
87
|
drop: e
|
|
88
88
|
};
|
|
89
89
|
}
|
|
90
|
-
class
|
|
90
|
+
class O {
|
|
91
91
|
constructor() {
|
|
92
92
|
this.currentPromise = Promise.resolve(), this.queueLength = 0;
|
|
93
93
|
}
|
|
94
|
-
async enqueue(
|
|
94
|
+
async enqueue(r) {
|
|
95
95
|
this.queueLength++;
|
|
96
|
-
const
|
|
97
|
-
return this.currentPromise =
|
|
96
|
+
const n = this.currentPromise;
|
|
97
|
+
return this.currentPromise = n.then(() => r(), () => r()).finally(() => {
|
|
98
98
|
this.queueLength--;
|
|
99
99
|
}), this.currentPromise;
|
|
100
100
|
}
|
|
@@ -105,60 +105,76 @@ class j {
|
|
|
105
105
|
this.queueLength = 0;
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
|
-
const
|
|
108
|
+
const Q = new O(), A = P(
|
|
109
109
|
"cdeebee/request",
|
|
110
|
-
async (
|
|
111
|
-
const
|
|
112
|
-
y(
|
|
110
|
+
async (t, { rejectWithValue: r, getState: n, requestId: o, signal: e }) => {
|
|
111
|
+
const a = (/* @__PURE__ */ new Date()).toUTCString(), { cdeebee: { settings: s } } = n(), i = j(e, t.api, o), c = t.onResult && typeof t.onResult == "function";
|
|
112
|
+
y(s, "cancelation", i.init);
|
|
113
113
|
const l = async () => {
|
|
114
114
|
try {
|
|
115
|
-
const { method: u = "POST", body: d, headers:
|
|
115
|
+
const { method: u = "POST", body: d, headers: D = {} } = t, z = { ...s.mergeWithHeaders ?? {}, ...D }, C = { ...s.mergeWithData ?? {}, ...d ?? {} };
|
|
116
116
|
let p = JSON.stringify(C);
|
|
117
|
-
if (
|
|
118
|
-
const b = new FormData(),
|
|
119
|
-
for (let q = 0; q <
|
|
120
|
-
|
|
121
|
-
|
|
117
|
+
if (t.files) {
|
|
118
|
+
const b = new FormData(), k = t.fileKey || s.fileKey, R = t.bodyKey || s.bodyKey;
|
|
119
|
+
for (let q = 0; q < t.files.length; q += 1)
|
|
120
|
+
k && b.append(k, t.files[q]);
|
|
121
|
+
R && b.append(R, p), p = b;
|
|
122
122
|
}
|
|
123
|
-
const
|
|
123
|
+
const m = await fetch(t.api, {
|
|
124
124
|
method: u,
|
|
125
125
|
headers: {
|
|
126
|
-
"ui-request-id":
|
|
126
|
+
"ui-request-id": o,
|
|
127
127
|
"Content-Type": "application/json",
|
|
128
|
-
...
|
|
128
|
+
...z
|
|
129
129
|
},
|
|
130
|
-
signal:
|
|
130
|
+
signal: i.controller.signal,
|
|
131
131
|
body: p
|
|
132
132
|
});
|
|
133
|
-
y(
|
|
133
|
+
y(s, "cancelation", i.drop);
|
|
134
134
|
let g;
|
|
135
|
-
const w =
|
|
136
|
-
return w === "text" ? g = await
|
|
135
|
+
const w = t.responseType || "json";
|
|
136
|
+
return w === "text" ? g = await m.text() : w === "blob" ? g = await m.blob() : g = await m.json(), m.ok ? (c && t.onResult(g), { result: g, startedAt: a, endedAt: (/* @__PURE__ */ new Date()).toUTCString() }) : (c && t.onResult(g), r(m));
|
|
137
137
|
} catch (u) {
|
|
138
|
-
return y(
|
|
138
|
+
return y(s, "cancelation", i.drop), c && t.onResult(u), u instanceof Error && u.name === "AbortError" ? r({ message: "Request was cancelled", cancelled: !0 }) : r({ message: u instanceof Error ? u.message : "Unknown error occurred" });
|
|
139
139
|
}
|
|
140
140
|
};
|
|
141
|
-
return
|
|
141
|
+
return s.modules.includes("queryQueue") ? Q.enqueue(l) : l();
|
|
142
142
|
}
|
|
143
143
|
);
|
|
144
|
-
function
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
144
|
+
function E(t) {
|
|
145
|
+
return f(t) && Array.isArray(t.data) && typeof t.primaryKey == "string";
|
|
146
|
+
}
|
|
147
|
+
function U(t, r) {
|
|
148
|
+
const n = {};
|
|
149
|
+
for (const o of t)
|
|
150
|
+
if (f(o) && r in o) {
|
|
151
|
+
const e = String(o[r]);
|
|
152
|
+
n[e] = o;
|
|
153
|
+
}
|
|
154
|
+
return n;
|
|
155
|
+
}
|
|
156
|
+
function K(t, r, n, o) {
|
|
157
|
+
return n === "replace" ? r : (n === "merge" || console.warn(`Cdeebee: Unknown strategy "${n}" for key "${o}". Skipping normalization.`), h(t, r));
|
|
158
|
+
}
|
|
159
|
+
function M(t, r, n) {
|
|
160
|
+
const o = Object.keys(r), e = f(t.storage) ? t.storage : {}, a = { ...e }, s = /* @__PURE__ */ new Set();
|
|
161
|
+
for (const i of o) {
|
|
162
|
+
const c = r[i];
|
|
148
163
|
if (c == null || typeof c == "string") {
|
|
149
|
-
|
|
164
|
+
s.add(i);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
const l = n[i] ?? "merge", u = i in e ? e[i] : {};
|
|
168
|
+
if (E(c)) {
|
|
169
|
+
const d = U(c.data, c.primaryKey);
|
|
170
|
+
a[i] = K(u, d, l, i);
|
|
150
171
|
continue;
|
|
151
172
|
}
|
|
152
|
-
|
|
153
|
-
if (l) {
|
|
154
|
-
const d = n in e ? e[n] : {};
|
|
155
|
-
u === "replace" ? o[n] = c : (u === "merge" || console.warn(`Cdeebee: Unknown strategy "${u}" for key "${n}". Skipping normalization.`), o[n] = m(d, c));
|
|
156
|
-
} else
|
|
157
|
-
o[n] = c;
|
|
173
|
+
f(c) ? a[i] = K(u, c, l, i) : a[i] = c;
|
|
158
174
|
}
|
|
159
|
-
return
|
|
175
|
+
return s.size > 0 ? v(Array.from(s), a) : a;
|
|
160
176
|
}
|
|
161
|
-
const
|
|
177
|
+
const W = {
|
|
162
178
|
settings: {
|
|
163
179
|
modules: ["history", "listener", "storage", "cancelation"],
|
|
164
180
|
fileKey: "file",
|
|
@@ -173,47 +189,47 @@ const E = {
|
|
|
173
189
|
errors: {},
|
|
174
190
|
done: {}
|
|
175
191
|
}
|
|
176
|
-
},
|
|
192
|
+
}, H = (t, r) => x({
|
|
177
193
|
name: "cdeebee",
|
|
178
|
-
initialState:
|
|
194
|
+
initialState: h(W, { settings: t, storage: r ?? {} }),
|
|
179
195
|
reducers: {
|
|
180
|
-
set(
|
|
181
|
-
N(
|
|
196
|
+
set(o, e) {
|
|
197
|
+
N(o.storage, e.payload);
|
|
182
198
|
}
|
|
183
199
|
},
|
|
184
|
-
extraReducers: (
|
|
185
|
-
|
|
186
|
-
const
|
|
200
|
+
extraReducers: (o) => {
|
|
201
|
+
o.addCase(A.pending, (e, a) => {
|
|
202
|
+
const s = a.meta.arg.api, i = a.meta.requestId;
|
|
187
203
|
y(e.settings, "cancelation", () => {
|
|
188
|
-
|
|
204
|
+
I(s, i);
|
|
189
205
|
}), y(e.settings, "listener", () => {
|
|
190
|
-
e.request.active.push({ api:
|
|
206
|
+
e.request.active.push({ api: s, requestId: i });
|
|
191
207
|
});
|
|
192
|
-
}).addCase(A.fulfilled, (e,
|
|
193
|
-
const
|
|
208
|
+
}).addCase(A.fulfilled, (e, a) => {
|
|
209
|
+
const s = a.meta.requestId, i = a.meta.arg.api;
|
|
194
210
|
y(e.settings, "listener", () => {
|
|
195
|
-
e.request.active = e.request.active.filter((c) => !(c.api ===
|
|
211
|
+
e.request.active = e.request.active.filter((c) => !(c.api === i && c.requestId === s));
|
|
196
212
|
}), y(e.settings, "history", () => {
|
|
197
|
-
e.request.done[
|
|
213
|
+
e.request.done[i] || (e.request.done[i] = []), e.request.done[i].push({ api: i, request: a.payload, requestId: s });
|
|
198
214
|
}), y(e.settings, "storage", () => {
|
|
199
|
-
if (
|
|
215
|
+
if (a.meta.arg.ignore)
|
|
200
216
|
return;
|
|
201
|
-
const c =
|
|
217
|
+
const c = a.meta.arg.listStrategy ?? e.settings.listStrategy ?? {}, l = a.meta.arg.normalize ?? e.settings.normalize ?? M, u = L(e), d = l(u, a.payload.result, c);
|
|
202
218
|
e.storage = d;
|
|
203
219
|
});
|
|
204
|
-
}).addCase(A.rejected, (e,
|
|
205
|
-
const
|
|
220
|
+
}).addCase(A.rejected, (e, a) => {
|
|
221
|
+
const s = a.meta.requestId, i = a.meta.arg.api;
|
|
206
222
|
y(e.settings, "listener", () => {
|
|
207
|
-
e.request.active = e.request.active.filter((c) => !(c.api ===
|
|
223
|
+
e.request.active = e.request.active.filter((c) => !(c.api === i && c.requestId === s));
|
|
208
224
|
}), y(e.settings, "history", () => {
|
|
209
|
-
e.request.errors[
|
|
225
|
+
e.request.errors[i] || (e.request.errors[i] = []), e.request.errors[i].push({ requestId: s, api: i, request: a.error });
|
|
210
226
|
});
|
|
211
227
|
});
|
|
212
228
|
}
|
|
213
229
|
});
|
|
214
230
|
export {
|
|
215
231
|
N as batchingUpdate,
|
|
216
|
-
|
|
232
|
+
H as factory,
|
|
217
233
|
A as request
|
|
218
234
|
};
|
|
219
235
|
//# 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"],"sourcesContent":["import { type CdeebeeSettings, type CdeebeeModule, CdeebeeValueList } from './types';\n\nexport function checkModule(settings: 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\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 isNormalized = isRecord(responseValue);\n const strategy = strategyList[key as keyof T] ?? 'merge';\n\n if (isNormalized) {\n const existingValue = key in currentStorage ? (currentStorage[key] as StorageData) : {};\n\n if (strategy === 'replace') {\n result[key] = responseValue as ResponseValue;\n } else if (strategy === 'merge') {\n result[key] = mergeDeepRight(existingValue, responseValue as StorageData) as ResponseValue;\n } else {\n console.warn(`Cdeebee: Unknown strategy \"${strategy}\" for key \"${key}\". Skipping normalization.`);\n result[key] = mergeDeepRight(existingValue, responseValue as StorageData) as ResponseValue;\n }\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 } from '@reduxjs/toolkit';\n\nimport { type CdeebeeSettings, type CdeebeeState, type CdeebeeValueList } 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 },\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 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 ?? {};\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 const normalizedData = normalize(currentState, action.payload.result as Record<string, Record<string, unknown>>, strategyList);\n\n // Normalize already handles merge/replace 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"],"names":["checkModule","settings","module","result","isRecord","value","mergeDeepRight","left","right","rightRecord","key","leftValue","rightValue","omit","keys","obj","batchingUpdate","state","valueList","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","i","response","responseType","error","defaultNormalize","cdeebee","strategyList","keyList","currentStorage","keyListToOmit","responseValue","isNormalized","strategy","existingValue","initialState","factory","storage","createSlice","action","builder","q","normalize","currentState","normalizedData"],"mappings":";AAEO,SAASA,EAAYC,GAAoCC,GAAuBC,GAAoB;AACzG,EAAIF,EAAS,QAAQ,SAASC,CAAM,KAClCC,EAAA;AAEJ;AACO,SAASC,EAASC,GAAkD;AACzE,SAAOA,MAAU,QAAQ,OAAOA,KAAU,YAAY,CAAC,MAAM,QAAQA,CAAK;AAC5E;AAUO,SAASC,EACdC,GACAC,GACG;AACH,MAAI,CAACJ,EAASG,CAAI,KAAK,CAACH,EAASI,CAAK;AACpC,WAAOA;AAGT,QAAML,IAAS,EAAE,GAAGI,EAAA,GACdE,IAAcD;AAEpB,aAAWE,KAAOD;AAChB,QAAI,OAAO,UAAU,eAAe,KAAKA,GAAaC,CAAG,GAAG;AAC1D,YAAMC,IAAYR,EAAOO,CAAG,GACtBE,IAAaH,EAAYC,CAAG;AAElC,MACEN,EAASO,CAAS,KAClBP,EAASQ,CAAU,KACnB,CAAC,MAAM,QAAQD,CAAS,KACxB,CAAC,MAAM,QAAQC,CAAU,IAEzBT,EAAOO,CAAG,IAAIJ,EAAeK,GAAWC,CAAU,IAElDT,EAAOO,CAAG,IAAIE;AAAA,IAElB;AAGF,SAAOT;AACT;AAEO,SAASU,EAAwCC,GAAgBC,GAA0B;AAChG,QAAMZ,IAAS,EAAE,GAAGY,EAAA;AACpB,aAAWL,KAAOI;AAChB,WAAOX,EAAOO,CAAG;AAEnB,SAAOP;AACT;AAqBO,SAASa,EACdC,GACAC,GACM;AACN,WAAS,IAAI,GAAG,IAAIA,EAAU,QAAQ,KAAK;AACzC,UAAMC,IAAOD,EAAU,CAAC,GAClBE,IAAOD,EAAK,KACZd,IAAQc,EAAK;AAEnB,QAAIC,EAAK,WAAW;AAClB;AAGF,QAAIC,IAA+CJ;AAEnD,aAASK,IAAI,GAAGA,IAAIF,EAAK,SAAS,GAAGE,KAAK;AACxC,YAAMC,IAAUH,EAAKE,CAAC;AAEtB,UAAI,MAAM,QAAQD,CAAO,GAAG;AAC1B,cAAMG,IAAQ,OAAOD,KAAY,WAAWA,IAAU,OAAOA,CAAO;AACpE,SAAI,EAAEC,KAASH,MAAY,CAACjB,EAASiB,EAAQG,CAAK,CAAC,OACjDH,EAAQG,CAAK,IAAI,CAAA,IAEnBH,IAAUA,EAAQG,CAAK;AAAA,MACzB,OAAO;AACL,cAAMd,IAAM,OAAOa,CAAO;AAC1B,YAAI,EAAEb,KAAOW,IAAU;AACrB,gBAAMI,IAAgB,OAAOL,EAAKE,IAAI,CAAC,KAAM,YAAa,CAAC,MAAM,OAAOF,EAAKE,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,OAAOF,EAAKE,IAAI,CAAC,CAAC,CAAC,MAAM,OAAOF,EAAKE,IAAI,CAAC,CAAC;AAC3I,UAAAD,EAAQX,CAAG,IAAIe,IAAgB,CAAA,IAAK,CAAA;AAAA,QACtC;AACA,cAAMC,IAAOL,EAAQX,CAAG;AACxB,QAAAW,IAAW,MAAM,QAAQK,CAAI,KAAYtB,EAASsB,CAAI,IAArBA,IAAgC,CAAA;AAAA,MACnE;AAAA,IACF;AAEA,IAAI,MAAM,QAAQL,CAAO,MAGzBA,EAAQ,OAAOD,EAAKA,EAAK,SAAS,CAAC,CAAC,CAAC,IAAIf;AAAA,EAC3C;AACF;AChHA,MAAMsB,EAAqB;AAAA,EAA3B,cAAA;AACE,SAAQ,kCAAkB,IAAA,GAC1B,KAAQ,4BAAY,IAAA;AAAA,EAAyB;AAAA,EAE7C,IAAIC,GAAaC,GAAmBC,GAAmC;AACrE,UAAMX,IAA0B,EAAE,WAAAU,GAAW,YAAAC,GAAY,KAAAF,EAAA;AACzD,SAAK,YAAY,IAAIC,GAAWV,CAAI,GAE/B,KAAK,MAAM,IAAIS,CAAG,KACrB,KAAK,MAAM,IAAIA,GAAK,oBAAI,KAAK,GAE/B,KAAK,MAAM,IAAIA,CAAG,EAAG,IAAIC,CAAS;AAAA,EACpC;AAAA,EAEA,OAAOA,GAAyB;AAC9B,UAAMV,IAAO,KAAK,YAAY,IAAIU,CAAS;AAC3C,QAAI,CAACV,EAAM;AAEX,SAAK,YAAY,OAAOU,CAAS;AACjC,UAAME,IAAS,KAAK,MAAM,IAAIZ,EAAK,GAAG;AACtC,IAAIY,MACFA,EAAO,OAAOF,CAAS,GACnBE,EAAO,SAAS,KAClB,KAAK,MAAM,OAAOZ,EAAK,GAAG;AAAA,EAGhC;AAAA,EAEA,eAAeS,GAAaI,GAAgC;AAC1D,UAAMC,IAAa,KAAK,MAAM,IAAIL,CAAG;AACrC,IAAKK,KAELA,EAAW,QAAQ,CAAAJ,MAAa;AAC9B,UAAIA,MAAcG,GAAkB;AAClC,cAAMb,IAAO,KAAK,YAAY,IAAIU,CAAS;AAC3C,QAAIV,MACFA,EAAK,WAAW,MAAA,GAChB,KAAK,OAAOU,CAAS;AAAA,MAEzB;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,MAAMK,IAAa,IAAIP,EAAA;AAEhB,SAASQ,EAAWP,GAAaQ,GAAgC;AACtE,EAAAF,EAAW,eAAeN,GAAKQ,CAAgB;AACjD;AAEO,SAASC,EAAaC,GAAqBV,GAAaC,GAAmB;AAChF,QAAMC,IAAa,IAAI,gBAAA,GAEjBS,IAAU,MAAM;AACpB,IAAAL,EAAW,OAAOL,CAAS;AAAA,EAC7B;AAEA,SAAAS,EAAO,iBAAiB,SAAS,MAAM;AACrC,IAAAR,EAAW,MAAA,GACXS,EAAA;AAAA,EACF,CAAC,GAEM;AAAA,IACL,YAAAT;AAAA,IACA,MAAM,MAAMI,EAAW,IAAIN,GAAKC,GAAWC,CAAU;AAAA,IACrD,MAAMS;AAAA,EAAA;AAEV;ACzEA,MAAMC,EAAW;AAAA,EAAjB,cAAA;AACE,SAAQ,iBAAmC,QAAQ,QAAA,GACnD,KAAQ,cAAc;AAAA,EAAA;AAAA,EAEtB,MAAM,QAAWC,GAAoC;AACnD,SAAK;AAEL,UAAMC,IAAkB,KAAK;AAE7B,gBAAK,iBAAiBA,EACnB,KAAK,MAAMD,EAAA,GAAQ,MAAMA,EAAA,CAAM,EAC/B,QAAQ,MAAM;AACb,WAAK;AAAA,IACP,CAAC,GAEI,KAAK;AAAA,EACd;AAAA,EAEA,iBAAyB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAc;AACZ,SAAK,cAAc;AAAA,EACrB;AACF;AAEO,MAAME,IAAa,IAAIH,EAAA,GCrBjBI,IAAUC;AAAA,EACrB;AAAA,EACA,OAAOC,GAAyC,EAAE,iBAAAC,GAAkB,UAAAC,GAAU,WAAAnB,GAAW,QAAAS,QAAa;AACpG,UAAMW,KAAY,oBAAI,KAAA,GAAO,YAAA,GACvB,EAAE,SAAS,EAAE,UAAAhD,EAAA,EAAS,IAAM+C,EAAA,GAE5BE,IAAQb,EAAaC,GAAQQ,EAAQ,KAAKjB,CAAS,GACnDsB,IAAeL,EAAQ,YAAY,OAAOA,EAAQ,YAAa;AAErE,IAAA9C,EAAYC,GAAU,eAAeiD,EAAM,IAAI;AAE/C,UAAME,IAAiB,YAAY;AACjC,UAAI;AACJ,cAAM,EAAE,QAAAC,IAAS,QAAQ,MAAAC,GAAM,SAAAC,IAAU,CAAA,MAAOT,GAC1CU,IAAuC,EAAE,GAAIvD,EAAS,oBAAoB,CAAA,GAAK,GAAGsD,EAAA,GAElFE,IAAI,EAAE,GAAIxD,EAAS,iBAAiB,IAAK,GAAIqD,KAAQ,GAAC;AAC5D,YAAII,IAAiC,KAAK,UAAUD,CAAC;AAGrD,YAAIX,EAAQ,OAAO;AACjB,gBAAMa,IAAW,IAAI,SAAA,GACfC,IAAUd,EAAQ,WAAW7C,EAAS,SACtC4D,IAAUf,EAAQ,WAAW7C,EAAS;AAE5C,mBAAS6D,IAAI,GAAGA,IAAIhB,EAAQ,MAAM,QAAQgB,KAAK;AAC7C,YAAIF,KACFD,EAAS,OAAOC,GAASd,EAAQ,MAAMgB,CAAC,CAAC;AAI7C,UAAID,KACFF,EAAS,OAAOE,GAASH,CAAW,GAEtCA,IAAcC;AAAA,QAChB;AAGA,cAAMI,IAAW,MAAM,MAAMjB,EAAQ,KAAK;AAAA,UACxC,QAAAO;AAAA,UACA,SAAS;AAAA,YACP,iBAAiBxB;AAAA,YACjB,gBAAgB;AAAA,YAChB,GAAG2B;AAAA,UAAA;AAAA,UAEL,QAAQN,EAAM,WAAW;AAAA,UACzB,MAAMQ;AAAA,QAAA,CACP;AAED,QAAA1D,EAAYC,GAAU,eAAeiD,EAAM,IAAI;AAE/C,YAAI/C;AACJ,cAAM6D,IAAelB,EAAQ,gBAAgB;AAW7C,eATIkB,MAAiB,SACnB7D,IAAS,MAAM4D,EAAS,KAAA,IACfC,MAAiB,SAC1B7D,IAAS,MAAM4D,EAAS,KAAA,IAGxB5D,IAAS,MAAM4D,EAAS,KAAA,GAGrBA,EAAS,MAKVZ,KAAcL,EAAQ,SAAU3C,CAAM,GACnC,EAAE,QAAAA,GAAQ,WAAA8C,GAAW,8BAAa,KAAA,GAAO,cAAY,MALtDE,KAAcL,EAAQ,SAAU3C,CAAM,GACnC4C,EAAgBgB,CAAQ;AAAA,MAKjC,SAASE,GAAO;AAKd,eAJAjE,EAAYC,GAAU,eAAeiD,EAAM,IAAI,GAE3CC,KAAcL,EAAQ,SAAUmB,CAAK,GAErCA,aAAiB,SAASA,EAAM,SAAS,eACpClB,EAAgB,EAAE,SAAS,yBAAyB,WAAW,IAAM,IAGvEA,EAAgB,EAAE,SAASkB,aAAiB,QAAQA,EAAM,UAAU,0BAA0B;AAAA,MACvG;AAAA,IACF;AAEA,WAAIhE,EAAS,QAAQ,SAAS,YAAY,IACjC0C,EAAW,QAAQS,CAAc,IAGnCA,EAAA;AAAA,EACT;AACF;ACtFO,SAASc,EACdC,GACAJ,GACAK,GAC+B;AAC/B,QAAMC,IAAU,OAAO,KAAKN,CAAQ,GAC9BO,IAAiBlE,EAAS+D,EAAQ,OAAO,IAAKA,EAAQ,UAAsC,CAAA,GAE5FhE,IAAS,EAAE,GAAGmE,EAAA,GACdC,wBAAoB,IAAA;AAE1B,aAAW7D,KAAO2D,GAAS;AACzB,UAAMG,IAAgBT,EAASrD,CAAG;AAElC,QAAI8D,KAAkB,QAAuC,OAAOA,KAAkB,UAAU;AAC9F,MAAAD,EAAc,IAAI7D,CAAG;AACrB;AAAA,IACF;AAEA,UAAM+D,IAAerE,EAASoE,CAAa,GACrCE,IAAWN,EAAa1D,CAAc,KAAK;AAEjD,QAAI+D,GAAc;AAChB,YAAME,IAAgBjE,KAAO4D,IAAkBA,EAAe5D,CAAG,IAAoB,CAAA;AAErF,MAAIgE,MAAa,YACfvE,EAAOO,CAAG,IAAI8D,KACLE,MAAa,WAGtB,QAAQ,KAAK,8BAA8BA,CAAQ,cAAchE,CAAG,4BAA4B,GAChGP,EAAOO,CAAG,IAAIJ,EAAeqE,GAAeH,CAA4B;AAAA,IAE5E;AACE,MAAArE,EAAOO,CAAG,IAAI8D;AAAA,EAElB;AAEA,SAAOD,EAAc,OAAO,IAAI1D,EAAK,MAAM,KAAK0D,CAAa,GAAGpE,CAAM,IAAIA;AAC5E;ACxCA,MAAMyE,IAAsC;AAAA,EAC1C,UAAU;AAAA,IACR,SAAS,CAAC,WAAW,YAAY,WAAW,aAAa;AAAA,IACzD,SAAS;AAAA,IACT,SAAS;AAAA,IACT,cAAc,CAAA;AAAA,IACd,eAAe,CAAA;AAAA,IACf,kBAAkB,CAAA;AAAA,EAAC;AAAA,EAErB,SAAS,CAAA;AAAA,EACT,SAAS;AAAA,IACP,QAAQ,CAAA;AAAA,IACR,QAAQ,CAAA;AAAA,IACR,MAAM,CAAA;AAAA,EAAC;AAEX,GAEaC,IAAU,CAAI5E,GAA8B6E,MACzCC,EAAY;AAAA,EACxB,MAAM;AAAA,EACN,cAAczE,EAAesE,GAAc,EAAE,UAAA3E,GAAU,SAAS6E,KAAW,CAAA,GAAI;AAAA,EAC/E,UAAU;AAAA,IACR,IAAI7D,GAAO+D,GAA0C;AAInD,MAAAhE,EAAeC,EAAM,SAAoC+D,EAAO,OAAO;AAAA,IACzE;AAAA,EAAA;AAAA,EAEF,eAAe,CAAAC,MAAW;AACxB,IAAAA,EACG,QAAQrC,EAAQ,SAAS,CAAC3B,GAAO+D,MAAW;AAC3C,YAAMpD,IAAMoD,EAAO,KAAK,IAAI,KACtBnD,IAAYmD,EAAO,KAAK;AAE9B,MAAAhF,EAAYiB,EAAM,UAAU,eAAe,MAAM;AAC/C,QAAAkB,EAAWP,GAAKC,CAAS;AAAA,MAC3B,CAAC,GACD7B,EAAYiB,EAAM,UAAU,YAAY,MAAM;AAC5C,QAAAA,EAAM,QAAQ,OAAO,KAAK,EAAE,KAAAW,GAAK,WAAAC,GAAW;AAAA,MAC9C,CAAC;AAAA,IACH,CAAC,EACA,QAAQe,EAAQ,WAAW,CAAC3B,GAAO+D,MAAW;AAC7C,YAAMnD,IAAYmD,EAAO,KAAK,WACxBpD,IAAMoD,EAAO,KAAK,IAAI;AAE5B,MAAAhF,EAAYiB,EAAM,UAAU,YAAY,MAAM;AAC5C,QAAAA,EAAM,QAAQ,SAASA,EAAM,QAAQ,OAAO,OAAO,CAAAiE,MAAK,EAAEA,EAAE,QAAQtD,KAAOsD,EAAE,cAAcrD,EAAU;AAAA,MACvG,CAAC,GACD7B,EAAYiB,EAAM,UAAU,WAAW,MAAM;AAC3C,QAAKA,EAAM,QAAQ,KAAKW,CAAG,MAAIX,EAAM,QAAQ,KAAKW,CAAG,IAAI,CAAA,IACzDX,EAAM,QAAQ,KAAKW,CAAG,EAAE,KAAK,EAAE,KAAAA,GAAK,SAASoD,EAAO,SAAS,WAAAnD,EAAA,CAAW;AAAA,MAC1E,CAAC,GACD7B,EAAYiB,EAAM,UAAU,WAAW,MAAM;AAC3C,YAAI+D,EAAO,KAAK,IAAI;AAClB;AAGF,cAAMZ,IAAeY,EAAO,KAAK,IAAI,gBAAgB/D,EAAM,SAAS,gBAAgB,CAAA,GAC9EkE,IAAYH,EAAO,KAAK,IAAI,aAAa/D,EAAM,SAAS,aAAaiD,GAErEkB,IAAe/D,EAAQJ,CAAK,GAE5BoE,IAAiBF,EAAUC,GAAcJ,EAAO,QAAQ,QAAmDZ,CAAY;AAK5H,QAAAnD,EAAM,UAAkBoE;AAAA,MAC3B,CAAC;AAAA,IACH,CAAC,EACA,QAAQzC,EAAQ,UAAU,CAAC3B,GAAO+D,MAAW;AAC5C,YAAMnD,IAAYmD,EAAO,KAAK,WACxBpD,IAAMoD,EAAO,KAAK,IAAI;AAE5B,MAAAhF,EAAYiB,EAAM,UAAU,YAAY,MAAM;AAC5C,QAAAA,EAAM,QAAQ,SAASA,EAAM,QAAQ,OAAO,OAAO,CAAAiE,MAAK,EAAEA,EAAE,QAAQtD,KAAOsD,EAAE,cAAcrD,EAAU;AAAA,MACvG,CAAC,GACD7B,EAAYiB,EAAM,UAAU,WAAW,MAAM;AAC3C,QAAKA,EAAM,QAAQ,OAAOW,CAAG,MAAIX,EAAM,QAAQ,OAAOW,CAAG,IAAI,CAAA,IAC7DX,EAAM,QAAQ,OAAOW,CAAG,EAAE,KAAK,EAAE,WAAAC,GAAsB,KAAAD,GAAK,SAASoD,EAAO,MAAA,CAAO;AAAA,MACrF,CAAC;AAAA,IACH,CAAC;AAAA,EACL;AAAA,CACD;"}
|
|
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"],"sourcesContent":["import { type CdeebeeSettings, type CdeebeeModule, CdeebeeValueList } from './types';\n\nexport function checkModule(settings: 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 {\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 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 } from '@reduxjs/toolkit';\n\nimport { type CdeebeeSettings, type CdeebeeState, type CdeebeeValueList } 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 },\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 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 ?? {};\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 const normalizedData = normalize(currentState, action.payload.result as Record<string, Record<string, unknown>>, strategyList);\n\n // Normalize already handles merge/replace 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"],"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"],"mappings":"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"}
|