@recats/cdeebee 2.3.7 → 3.0.0-beta.11

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/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("@reduxjs/toolkit"),d=require("react-redux");function f(e,r,s){e.modules.includes(r)&&s()}function y(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function p(e,r){if(!y(e)||!y(r))return r;const s={...e},o=r;for(const t in o)if(Object.prototype.hasOwnProperty.call(o,t)){const u=s[t],i=o[t];y(u)&&y(i)&&!Array.isArray(u)&&!Array.isArray(i)?s[t]=p(u,i):s[t]=i}return s}function C(e,r){const s={...r};for(const o of e)delete s[o];return s}function D(e,r){for(let s=0;s<r.length;s++){const o=r[s],t=o.key,u=o.value;if(t.length===0)continue;let i=e;for(let n=0;n<t.length-1;n++){const c=t[n];if(Array.isArray(i)){const a=typeof c=="number"?c:Number(c);(!(a in i)||!y(i[a]))&&(i[a]={}),i=i[a]}else{const a=String(c);if(!(a in i)){const g=typeof t[n+1]=="number"||!isNaN(Number(t[n+1]))&&String(Number(t[n+1]))===String(t[n+1]);i[a]=g?[]:{}}const l=i[a];i=Array.isArray(l)||y(l)?l:{}}}Array.isArray(i)||(i[String(t[t.length-1])]=u)}}class E{constructor(){this.byRequestId=new Map,this.byApi=new Map}add(r,s,o){const t={requestId:s,controller:o,api:r};this.byRequestId.set(s,t),this.byApi.has(r)||this.byApi.set(r,new Set),this.byApi.get(r).add(s)}delete(r){const s=this.byRequestId.get(r);if(!s)return;this.byRequestId.delete(r);const o=this.byApi.get(s.api);o&&(o.delete(r),o.size===0&&this.byApi.delete(s.api))}abortAllForApi(r,s){const o=this.byApi.get(r);o&&o.forEach(t=>{if(t!==s){const u=this.byRequestId.get(t);u&&(u.controller.abort(),this.delete(t))}})}}const k=new E;function H(e,r){k.abortAllForApi(e,r)}function T(e,r,s){const o=new AbortController,t=()=>{k.delete(s)};return e.addEventListener("abort",()=>{o.abort(),t()}),{controller:o,init:()=>k.add(r,s,o),drop:t}}class x{constructor(){this.currentPromise=Promise.resolve(),this.queueLength=0}async enqueue(r){this.queueLength++;const s=this.currentPromise;return this.currentPromise=s.then(()=>r(),()=>r()).finally(()=>{this.queueLength--}),this.currentPromise}getQueueLength(){return this.queueLength}clear(){this.queueLength=0}}const N=new x,m=R.createAsyncThunk("cdeebee/request",async(e,{rejectWithValue:r,getState:s,requestId:o,signal:t})=>{const u=new Date().toUTCString(),{cdeebee:{settings:i}}=s(),n=T(t,e.api,o),c=e.onResult&&typeof e.onResult=="function";f(i,"cancelation",n.init);const a=async()=>{try{const{method:l="POST",body:g,headers:I={}}=e,P={...i.mergeWithHeaders??{},...I},z={...i.mergeWithData??{},...g??{}};let q=JSON.stringify(z);if(e.files){const S=new FormData,w=e.fileKey||i.fileKey,v=e.bodyKey||i.bodyKey;for(let A=0;A<e.files.length;A+=1)w&&S.append(w,e.files[A]);v&&S.append(v,q),q=S}const h=await fetch(e.api,{method:l,headers:{"ui-request-id":o,"Content-Type":"application/json",...P},signal:n.controller.signal,body:q});f(i,"cancelation",n.drop);let b;const L=e.responseType||"json";return L==="text"?b=await h.text():L==="blob"?b=await h.blob():b=await h.json(),h.ok?(c&&e.onResult(b),{result:b,startedAt:u,endedAt:new Date().toUTCString()}):(c&&e.onResult(b),r(h))}catch(l){return f(i,"cancelation",n.drop),c&&e.onResult(l),l instanceof Error&&l.name==="AbortError"?r({message:"Request was cancelled",cancelled:!0}):r({message:l instanceof Error?l.message:"Unknown error occurred"})}};return i.modules.includes("queryQueue")?N.enqueue(a):a()});function j(e){return y(e)&&Array.isArray(e.data)&&typeof e.primaryKey=="string"}function O(e,r){const s={};for(const o of e)if(y(o)&&r in o){const t=String(o[r]);s[t]=o}return s}function K(e,r,s,o){return s==="replace"?r:s==="merge"?p(e,r):s==="skip"?e:(console.warn(`Cdeebee: Unknown strategy "${s}" for key "${o}". Skipping normalization.`),p(e,r))}function Q(e,r,s){const o=Object.keys(r),t=y(e.storage)?e.storage:{},u={...t},i=new Set;for(const n of o){const c=r[n];if(c==null||typeof c=="string"){i.add(n);continue}const a=s[n]??"merge";if(a==="skip"&&!(n in t))continue;const l=n in t?t[n]:{};if(j(c)){const g=O(c.data,c.primaryKey);u[n]=K(l,g,a,n);continue}y(c)?u[n]=K(l,c,a,n):u[n]=c}return i.size>0?C(Array.from(i),u):u}const U={settings:{modules:["history","listener","storage","cancelation"],fileKey:"file",bodyKey:"value",listStrategy:{},mergeWithData:{},mergeWithHeaders:{}},storage:{},request:{active:[],errors:{},done:{}}},M=(e,r)=>R.createSlice({name:"cdeebee",initialState:p(U,{settings:e,storage:r??{}}),reducers:{set(o,t){D(o.storage,t.payload)},historyClear(o,t){const u=t.payload;u?(delete o.request.done[u],delete o.request.errors[u]):(o.request.done={},o.request.errors={})}},extraReducers:o=>{o.addCase(m.pending,(t,u)=>{const i=u.meta.arg.api,n=u.meta.requestId;u.meta.arg.historyClear&&f(t.settings,"history",()=>{delete t.request.done[i],delete t.request.errors[i]}),f(t.settings,"cancelation",()=>{H(i,n)}),f(t.settings,"listener",()=>{t.request.active.push({api:i,requestId:n})})}).addCase(m.fulfilled,(t,u)=>{const i=u.meta.requestId,n=u.meta.arg.api;f(t.settings,"listener",()=>{t.request.active=t.request.active.filter(c=>!(c.api===n&&c.requestId===i))}),f(t.settings,"history",()=>{t.request.done[n]||(t.request.done[n]=[]),t.request.done[n].push({api:n,request:u.payload,requestId:i})}),f(t.settings,"storage",()=>{if(u.meta.arg.ignore)return;const c=u.meta.arg.listStrategy??t.settings.listStrategy??{},a=u.meta.arg.normalize??t.settings.normalize??Q,l=R.current(t),g=a(l,u.payload.result,c);t.storage=g})}).addCase(m.rejected,(t,u)=>{const i=u.meta.requestId,n=u.meta.arg.api;f(t.settings,"listener",()=>{t.request.active=t.request.active.filter(c=>!(c.api===n&&c.requestId===i))}),f(t.settings,"history",()=>{t.request.errors[n]||(t.request.errors[n]=[]),t.request.errors[n].push({requestId:i,api:n,request:u.error})})})}});function W(e){function r(n){return d.useSelector(c=>e(c).request.active.some(l=>n.includes(l.api)))}function s(n){return d.useSelector(c=>e(c).request.done[n]??[])}function o(n){return d.useSelector(c=>e(c).request.errors[n]??[])}function t(n){return d.useSelector(c=>e(c).storage[n])}function u(){return d.useSelector(n=>e(n).storage)}function i(){return d.useSelector(n=>e(n).request.active.length>0)}return{useLoading:r,useRequestHistory:s,useRequestErrors:o,useStorageList:t,useStorage:u,useIsLoading:i}}function F(e){return d.useSelector(r=>r.cdeebee.request.active.some(s=>e.includes(s.api)))}function $(e){return d.useSelector(r=>r.cdeebee.request.done[e]??[])}function J(e){return d.useSelector(r=>r.cdeebee.request.errors[e]??[])}function B(e){return d.useSelector(r=>r.cdeebee.storage[e])}function G(){return d.useSelector(e=>e.cdeebee.storage)}function X(){return d.useSelector(e=>e.cdeebee.request.active.length>0)}exports.batchingUpdate=D;exports.createCdeebeeHooks=W;exports.factory=M;exports.request=m;exports.useIsLoading=X;exports.useLoading=F;exports.useRequestErrors=J;exports.useRequestHistory=$;exports.useStorage=G;exports.useStorageList=B;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../lib/reducer/helpers.ts","../lib/reducer/abortController.ts","../lib/reducer/queryQueue.ts","../lib/reducer/request.ts","../lib/reducer/storage.ts","../lib/reducer/index.ts","../lib/hooks.ts"],"sourcesContent":["import { type WritableDraft } from '@reduxjs/toolkit';\nimport { type CdeebeeSettings, type CdeebeeModule, CdeebeeValueList } from './types';\n\nexport function checkModule(settings: CdeebeeSettings<unknown> | WritableDraft<CdeebeeSettings<unknown>>, module: CdeebeeModule, result: () => void) {\n if (settings.modules.includes(module)) {\n result();\n }\n}\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function hasDataProperty(value: unknown): value is Record<string, unknown> & { data: unknown[] } {\n return isRecord(value) && Array.isArray(value.data);\n}\n\nexport function hasProperty(value: unknown, prop: string): boolean {\n return isRecord(value) && Object.prototype.hasOwnProperty.call(value, prop);\n}\n\nexport function mergeDeepRight<T>(\n left: T,\n right: Partial<T> | Record<string, unknown>\n): T {\n if (!isRecord(left) || !isRecord(right)) {\n return right as T;\n }\n\n const result = { ...left } as Record<string, unknown>;\n const rightRecord = right as Record<string, unknown>;\n\n for (const key in rightRecord) {\n if (Object.prototype.hasOwnProperty.call(rightRecord, key)) {\n const leftValue = result[key];\n const rightValue = rightRecord[key];\n\n if (\n isRecord(leftValue) &&\n isRecord(rightValue) &&\n !Array.isArray(leftValue) &&\n !Array.isArray(rightValue)\n ) {\n result[key] = mergeDeepRight(leftValue, rightValue);\n } else {\n result[key] = rightValue;\n }\n }\n }\n\n return result as T;\n}\n\nexport function omit<T extends Record<string, unknown>>(keys: string[], obj: T): Omit<T, keyof T> {\n const result = { ...obj };\n for (const key of keys) {\n delete result[key];\n }\n return result as Omit<T, keyof T>;\n}\n\nexport function assocPath<T>(path: (string | number)[], value: unknown, obj: T): T {\n if (path.length === 0) {\n return value as T;\n }\n\n const [first, ...rest] = path;\n const firstKey = String(first);\n const result = Array.isArray(obj) ? [...obj] : { ...obj } as Record<string, unknown>;\n\n if (rest.length === 0) {\n (result as Record<string, unknown>)[firstKey] = value;\n } else {\n const currentValue = (result as Record<string, unknown>)[firstKey];\n (result as Record<string, unknown>)[firstKey] = assocPath(rest, value, currentValue ?? {});\n }\n\n return result as T;\n}\n\nexport function batchingUpdate<T extends Record<string, unknown>>(\n state: T,\n valueList: CdeebeeValueList<T>\n): void {\n for (let i = 0; i < valueList.length; i++) {\n const item = valueList[i] as { key: readonly (string | number)[]; value: unknown };\n const path = item.key;\n const value = item.value;\n \n if (path.length === 0) {\n continue;\n }\n\n let current: Record<string, unknown> | unknown[] = state as Record<string, unknown>;\n \n for (let j = 0; j < path.length - 1; j++) {\n const pathKey = path[j];\n \n if (Array.isArray(current)) {\n const index = typeof pathKey === 'number' ? pathKey : Number(pathKey);\n if (!(index in current) || !isRecord(current[index])) {\n current[index] = {};\n }\n current = current[index] as Record<string, unknown>;\n } else {\n const key = String(pathKey);\n if (!(key in current)) {\n const nextIsNumeric = typeof path[j + 1] === 'number' || (!isNaN(Number(path[j + 1])) && String(Number(path[j + 1])) === String(path[j + 1]));\n current[key] = nextIsNumeric ? [] : {};\n }\n const next = current[key];\n current = (Array.isArray(next) ? next : (isRecord(next) ? next : {})) as Record<string, unknown> | unknown[];\n }\n }\n \n if (Array.isArray(current)) {\n continue; // Can't update array element directly\n }\n current[String(path[path.length - 1])] = value;\n }\n}\n","interface RequestController {\n requestId: string;\n controller: AbortController;\n api: string;\n}\n\nclass AbortControllerStore {\n private byRequestId = new Map<string, RequestController>();\n private byApi = new Map<string, Set<string>>();\n\n add(api: string, requestId: string, controller: AbortController): void {\n const item: RequestController = { requestId, controller, api };\n this.byRequestId.set(requestId, item);\n\n if (!this.byApi.has(api)) {\n this.byApi.set(api, new Set());\n }\n this.byApi.get(api)!.add(requestId);\n }\n\n delete(requestId: string): void {\n const item = this.byRequestId.get(requestId);\n if (!item) return;\n\n this.byRequestId.delete(requestId);\n const apiSet = this.byApi.get(item.api);\n if (apiSet) {\n apiSet.delete(requestId);\n if (apiSet.size === 0) {\n this.byApi.delete(item.api);\n }\n }\n }\n\n abortAllForApi(api: string, excludeRequestId: string): void {\n const requestIds = this.byApi.get(api);\n if (!requestIds) return;\n\n requestIds.forEach(requestId => {\n if (requestId !== excludeRequestId) {\n const item = this.byRequestId.get(requestId);\n if (item) {\n item.controller.abort();\n this.delete(requestId);\n }\n }\n });\n }\n}\n\nconst abortStore = new AbortControllerStore();\n\nexport function abortQuery(api: string, currentRequestId: string): void {\n abortStore.abortAllForApi(api, currentRequestId);\n}\n\nexport function abortManager(signal: AbortSignal, api: string, requestId: string) {\n const controller = new AbortController();\n\n const cleanup = () => {\n abortStore.delete(requestId);\n };\n\n signal.addEventListener('abort', () => {\n controller.abort();\n cleanup();\n });\n\n return {\n controller,\n init: () => abortStore.add(api, requestId, controller),\n drop: cleanup,\n };\n}\n","class QueryQueue {\n private currentPromise: Promise<unknown> = Promise.resolve();\n private queueLength = 0;\n\n async enqueue<T>(task: () => Promise<T>): Promise<T> {\n this.queueLength++;\n \n const previousPromise = this.currentPromise;\n \n this.currentPromise = previousPromise\n .then(() => task(), () => task())\n .finally(() => {\n this.queueLength--;\n });\n\n return this.currentPromise as Promise<T>;\n }\n\n getQueueLength(): number {\n return this.queueLength;\n }\n\n clear(): void {\n this.queueLength = 0;\n }\n}\n\nexport const queryQueue = new QueryQueue();\n\n","import { createAsyncThunk } from '@reduxjs/toolkit';\nimport { checkModule } from './helpers';\nimport { abortManager } from './abortController';\nimport { queryQueue } from './queryQueue';\nimport { type CdeebeeState, type CdeebeeRequestOptions } from './types';\n\nexport const request = createAsyncThunk(\n 'cdeebee/request',\n async (options: CdeebeeRequestOptions<unknown>, { rejectWithValue, getState, requestId, signal }) => {\n const startedAt = new Date().toUTCString();\n const { cdeebee: { settings } } = getState() as { cdeebee: CdeebeeState<unknown> };\n\n const abort = abortManager(signal, options.api, requestId);\n const withCallback = options.onResult && typeof options.onResult === 'function';\n\n checkModule(settings, 'cancelation', abort.init);\n\n const executeRequest = async () => {\n try {\n const { method = 'POST', body, headers = {} } = options;\n const extraHeaders: Record<string, string> = { ...(settings.mergeWithHeaders ?? {}), ...headers };\n\n const b = { ...(settings.mergeWithData ?? {}), ...(body ?? {}) };\n let requestData: FormData | string = JSON.stringify(b);\n\n // handling files\n if (options.files) {\n const formData = new FormData();\n const fileKey = options.fileKey || settings.fileKey;\n const bodyKey = options.bodyKey || settings.bodyKey;\n\n for (let i = 0; i < options.files.length; i += 1) {\n if (fileKey) {\n formData.append(fileKey, options.files[i]);\n }\n }\n\n if (bodyKey) {\n formData.append(bodyKey, requestData);\n }\n requestData = formData;\n }\n // [end] handling files\n \n const response = await fetch(options.api, {\n method,\n headers: {\n 'ui-request-id': requestId,\n 'Content-Type': 'application/json',\n ...extraHeaders,\n },\n signal: abort.controller.signal,\n body: requestData,\n });\n\n checkModule(settings, 'cancelation', abort.drop);\n\n let result: unknown;\n const responseType = options.responseType || 'json';\n \n if (responseType === 'text') {\n result = await response.text();\n } else if (responseType === 'blob') {\n result = await response.blob();\n } else {\n // default: json\n result = await response.json();\n }\n\n if (!response.ok) {\n if (withCallback) options.onResult!(result);\n return rejectWithValue(response);\n }\n\n if (withCallback) options.onResult!(result);\n return { result, startedAt, endedAt: new Date().toUTCString() };\n } catch (error) {\n checkModule(settings, 'cancelation', abort.drop);\n\n if (withCallback) options.onResult!(error); \n\n if (error instanceof Error && error.name === 'AbortError') {\n return rejectWithValue({ message: 'Request was cancelled', cancelled: true });\n }\n\n return rejectWithValue({ message: error instanceof Error ? error.message : 'Unknown error occurred' });\n }\n };\n\n if (settings.modules.includes('queryQueue')) {\n return queryQueue.enqueue(executeRequest);\n }\n\n return executeRequest();\n },\n);\n\n","import { type CdeebeeListStrategy, type CdeebeeState } from './types';\nimport { isRecord, mergeDeepRight, omit } from './helpers';\n\ntype ResponseValue = Record<string, unknown>;\n\ntype IResponse = Record<string, ResponseValue>;\n\ntype StorageData = Record<string, unknown>;\n\nfunction isDataWithPrimaryKey(value: unknown): value is { data: unknown[]; primaryKey: string } {\n return (\n isRecord(value) &&\n Array.isArray(value.data) &&\n typeof value.primaryKey === 'string'\n );\n}\nfunction normalizeDataWithPrimaryKey(data: unknown[], primaryKey: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n \n for (const item of data) {\n if (isRecord(item) && primaryKey in item) {\n const key = String(item[primaryKey]);\n result[key] = item;\n }\n }\n \n return result;\n}\n\nfunction applyStrategy(\n existingValue: StorageData,\n newValue: StorageData | ResponseValue,\n strategy: string,\n key: string\n): ResponseValue {\n if (strategy === 'replace') {\n return newValue as ResponseValue;\n } else if (strategy === 'merge') {\n return mergeDeepRight(existingValue, newValue as StorageData) as ResponseValue;\n } else if (strategy === 'skip') {\n return existingValue as ResponseValue;\n } else {\n console.warn(`Cdeebee: Unknown strategy \"${strategy}\" for key \"${key}\". Skipping normalization.`);\n return mergeDeepRight(existingValue, newValue as StorageData) as ResponseValue;\n }\n}\n\nexport function defaultNormalize<T>(\n cdeebee: CdeebeeState<T>,\n response: IResponse,\n strategyList: CdeebeeListStrategy<T> \n): Record<string, ResponseValue> {\n const keyList = Object.keys(response);\n const currentStorage = isRecord(cdeebee.storage) ? (cdeebee.storage as Record<string, unknown>) : {};\n \n const result = { ...currentStorage } as Record<string, ResponseValue>;\n const keyListToOmit = new Set<string>();\n\n for (const key of keyList) {\n const responseValue = response[key];\n\n if (responseValue === null || responseValue === undefined || typeof responseValue === 'string') {\n keyListToOmit.add(key);\n continue;\n }\n\n const strategy = strategyList[key as keyof T] ?? 'merge';\n \n // For 'skip' strategy, if key doesn't exist in storage, skip it entirely\n if (strategy === 'skip' && !(key in currentStorage)) {\n continue;\n }\n \n const existingValue = key in currentStorage ? (currentStorage[key] as StorageData) : {};\n\n if (isDataWithPrimaryKey(responseValue)) {\n const normalizedValue = normalizeDataWithPrimaryKey(responseValue.data, responseValue.primaryKey);\n result[key] = applyStrategy(existingValue, normalizedValue, strategy, key);\n continue;\n }\n\n if (isRecord(responseValue)) {\n result[key] = applyStrategy(existingValue, responseValue as StorageData, strategy, key);\n } else {\n result[key] = responseValue;\n }\n }\n\n return keyListToOmit.size > 0 ? omit(Array.from(keyListToOmit), result) : result;\n}\n","import { createSlice, current } from '@reduxjs/toolkit';\n\nimport { type CdeebeeSettings, type CdeebeeState, type CdeebeeValueList, type CdeebeeListStrategy } from './types';\nimport { checkModule, mergeDeepRight, batchingUpdate } from './helpers';\nimport { abortQuery } from './abortController';\nimport { request } from './request';\nimport { defaultNormalize } from './storage';\n\nconst initialState: CdeebeeState<unknown> = {\n settings: {\n modules: ['history', 'listener', 'storage', 'cancelation'],\n fileKey: 'file',\n bodyKey: 'value',\n listStrategy: {},\n mergeWithData: {},\n mergeWithHeaders: {},\n },\n storage: {},\n request: {\n active: [],\n errors: {},\n done: {}\n },\n};\n\nexport const factory = <T>(settings: CdeebeeSettings<T>, storage?: T) => {\n const slice = createSlice({\n name: 'cdeebee',\n initialState: mergeDeepRight(initialState, { settings, storage: storage ?? {} }) as CdeebeeState<T>,\n reducers: {\n set(state, action: { payload: CdeebeeValueList<T> }) {\n // Directly mutate state.storage using Immer Draft\n // This is more performant than creating a new object\n // Immer will track changes and create minimal updates\n batchingUpdate(state.storage as Record<string, unknown>, action.payload);\n },\n historyClear(state, action: { payload?: string }) {\n const api = action.payload;\n\n if (api) {\n delete state.request.done[api];\n delete state.request.errors[api];\n } else {\n state.request.done = {};\n state.request.errors = {};\n }\n }\n },\n extraReducers: builder => {\n builder\n .addCase(request.pending, (state, action) => {\n const api = action.meta.arg.api;\n const requestId = action.meta.requestId;\n\n if (action.meta.arg.historyClear) {\n checkModule(state.settings, 'history', () => {\n delete state.request.done[api];\n delete state.request.errors[api];\n });\n }\n\n checkModule(state.settings, 'cancelation', () => {\n abortQuery(api, requestId);\n });\n checkModule(state.settings, 'listener', () => {\n state.request.active.push({ api, requestId });\n });\n })\n .addCase(request.fulfilled, (state, action) => {\n const requestId = action.meta.requestId;\n const api = action.meta.arg.api;\n\n checkModule(state.settings, 'listener', () => {\n state.request.active = state.request.active.filter(q => !(q.api === api && q.requestId === requestId));\n });\n checkModule(state.settings, 'history', () => {\n if (!state.request.done[api]) state.request.done[api] = [];\n state.request.done[api].push({ api, request: action.payload, requestId });\n });\n checkModule(state.settings, 'storage', () => {\n if (action.meta.arg.ignore) {\n return;\n }\n \n const strategyList = (action.meta.arg.listStrategy ?? state.settings.listStrategy ?? {}) as CdeebeeListStrategy<T>;\n const normalize = action.meta.arg.normalize ?? state.settings.normalize ?? defaultNormalize;\n\n const currentState = current(state) as CdeebeeState<T>;\n // Type assertion is safe here because we've already checked isRecord\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const normalizedData = normalize(currentState, action.payload.result as any, strategyList);\n\n // Normalize already handles merge/replace/skip and preserves keys not in response\n // Simply apply the result\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (state.storage as any) = normalizedData;\n });\n })\n .addCase(request.rejected, (state, action) => {\n const requestId = action.meta.requestId;\n const api = action.meta.arg.api;\n\n checkModule(state.settings, 'listener', () => {\n state.request.active = state.request.active.filter(q => !(q.api === api && q.requestId === requestId));\n });\n checkModule(state.settings, 'history', () => {\n if (!state.request.errors[api]) state.request.errors[api] = [];\n state.request.errors[api].push({ requestId: requestId, api, request: action.error });\n });\n });\n },\n });\n\n return slice;\n};\n","import { useSelector } from 'react-redux';\nimport { type CdeebeeState } from './reducer/types';\n\n/**\n * Generic hook factory that creates a selector hook for cdeebee state.\n * This allows the hooks to work with any Redux root state structure.\n *\n * @template RootState - The shape of the Redux root state\n * @template Storage - The shape of the cdeebee storage\n * @param selectCdeebee - Function to select the cdeebee slice from root state\n * @returns An object containing all cdeebee hooks\n */\nexport function createCdeebeeHooks<RootState, Storage>(\n selectCdeebee: (state: RootState) => CdeebeeState<Storage>\n) {\n /**\n * Check if any of the specified APIs are currently loading.\n *\n * @param apiList - Array of API endpoints to check\n * @returns true if any of the APIs are currently active/loading\n *\n * @example\n * const isLoading = useLoading(['/api/forums', '/api/threads']);\n * if (isLoading) return <Spinner />;\n */\n function useLoading(apiList: string[]): boolean {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.active.some(q => apiList.includes(q.api));\n });\n }\n\n /**\n * Get the successful request history for a specific API endpoint.\n *\n * @param api - The API endpoint\n * @returns Array of successful request history entries\n *\n * @example\n * const history = useRequestHistory('/api/forums');\n * console.log(`Made ${history.length} successful requests`);\n */\n function useRequestHistory(api: string) {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.done[api] ?? [];\n });\n }\n\n /**\n * Get the error history for a specific API endpoint.\n *\n * @param api - The API endpoint\n * @returns Array of error history entries\n *\n * @example\n * const errors = useRequestErrors('/api/forums');\n * if (errors.length > 0) {\n * console.error('Last error:', errors[errors.length - 1]);\n * }\n */\n function useRequestErrors(api: string) {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.errors[api] ?? [];\n });\n }\n\n /**\n * Get a specific list from storage with full type safety.\n *\n * @param listName - The name of the list in storage\n * @returns The list data\n *\n * @example\n * const forums = useStorageList('forumList');\n * const forumArray = Object.values(forums);\n */\n function useStorageList<K extends keyof Storage>(listName: K): Storage[K] {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.storage[listName];\n });\n }\n\n /**\n * Get the entire cdeebee storage.\n *\n * @returns The complete storage object\n *\n * @example\n * const storage = useStorage();\n * console.log(Object.keys(storage)); // ['forumList', 'threadList', ...]\n */\n function useStorage(): Storage {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.storage;\n });\n }\n\n /**\n * Check if any request is currently loading (across all APIs).\n *\n * @returns true if any request is active\n *\n * @example\n * const isAnythingLoading = useIsLoading();\n * if (isAnythingLoading) return <GlobalSpinner />;\n */\n function useIsLoading(): boolean {\n return useSelector((state: RootState) => {\n const cdeebee = selectCdeebee(state);\n return cdeebee.request.active.length > 0;\n });\n }\n\n return {\n useLoading,\n useRequestHistory,\n useRequestErrors,\n useStorageList,\n useStorage,\n useIsLoading,\n };\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param apiList - Array of API endpoints to check\n * @returns true if any of the APIs are currently active/loading\n *\n * @example\n * const isLoading = useLoading(['/api/forums', '/api/threads']);\n */\nexport function useLoading<Storage = unknown>(apiList: string[]): boolean {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.active.some(q => apiList.includes(q.api));\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param api - The API endpoint\n * @returns Array of successful request history entries\n */\nexport function useRequestHistory<Storage = unknown>(api: string) {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.done[api] ?? [];\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param api - The API endpoint\n * @returns Array of error history entries\n */\nexport function useRequestErrors<Storage = unknown>(api: string) {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.errors[api] ?? [];\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @param listName - The name of the list in storage\n * @returns The list data\n */\nexport function useStorageList<Storage, K extends keyof Storage>(listName: K): Storage[K] {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.storage[listName];\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @returns The complete storage object\n */\nexport function useStorage<Storage>(): Storage {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.storage;\n });\n}\n\n/**\n * Standalone hook that can be used without createCdeebeeHooks.\n * Assumes the cdeebee slice is at state.cdeebee.\n *\n * @returns true if any request is active\n */\nexport function useIsLoading<Storage = unknown>(): boolean {\n return useSelector((state: { cdeebee: CdeebeeState<Storage> }) => {\n return state.cdeebee.request.active.length > 0;\n });\n}\n"],"names":["checkModule","settings","module","result","isRecord","value","mergeDeepRight","left","right","rightRecord","key","leftValue","rightValue","omit","keys","obj","batchingUpdate","state","valueList","i","item","path","current","j","pathKey","index","nextIsNumeric","next","AbortControllerStore","api","requestId","controller","apiSet","excludeRequestId","requestIds","abortStore","abortQuery","currentRequestId","abortManager","signal","cleanup","QueryQueue","task","previousPromise","queryQueue","request","createAsyncThunk","options","rejectWithValue","getState","startedAt","abort","withCallback","executeRequest","method","body","headers","extraHeaders","b","requestData","formData","fileKey","bodyKey","response","responseType","error","isDataWithPrimaryKey","normalizeDataWithPrimaryKey","data","primaryKey","applyStrategy","existingValue","newValue","strategy","defaultNormalize","cdeebee","strategyList","keyList","currentStorage","keyListToOmit","responseValue","normalizedValue","initialState","factory","storage","createSlice","action","builder","q","normalize","currentState","normalizedData","createCdeebeeHooks","selectCdeebee","useLoading","apiList","useSelector","useRequestHistory","useRequestErrors","useStorageList","listName","useStorage","useIsLoading"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,234 @@
1
- import { cdeebee, requestManager } from './reducer';
2
- import { default as CdeebeeRequest } from './request';
3
- import { cdeebeeTypes, cdeebeeMergeStrategy, cdeebeeEntityState, cdeebeeValueList, cdeebeActiveRequest, cdeebeeIActions } from './definition';
4
- import * as cdeebeeHelpers from './helpers';
5
- import * as cdeebeeActions from './actions';
6
- export { cdeebeeValueList, cdeebee, cdeebeeHelpers, requestManager, CdeebeeRequest, cdeebeeTypes, cdeebeeEntityState, cdeebeeMergeStrategy, cdeebeeActions, cdeebeActiveRequest, cdeebeeIActions, };
1
+ import { AsyncThunk } from '@reduxjs/toolkit';
2
+ import { AsyncThunkConfig } from '@reduxjs/toolkit';
3
+ import { Draft } from '@reduxjs/toolkit';
4
+ import { Slice } from '@reduxjs/toolkit';
5
+ import { SliceSelectors } from '@reduxjs/toolkit';
6
+
7
+ declare type Append<P extends readonly (string | number)[], K extends string | number> = [...P, K];
8
+
9
+ declare type ArrayElement<T> = T extends readonly (infer U)[] ? U : T extends (infer U)[] ? U : never;
10
+
11
+ export declare function batchingUpdate<T extends Record<string, unknown>>(state: T, valueList: CdeebeeValueList<T>): void;
12
+
13
+ export declare interface CdeebeeActiveRequest {
14
+ api: string;
15
+ requestId: string;
16
+ }
17
+
18
+ export declare interface CdeebeeHistoryState {
19
+ requestId: string;
20
+ api: string;
21
+ request: unknown;
22
+ }
23
+
24
+ export declare type CdeebeeListStrategy<T> = Record<keyof T, CdeebeeStrategy>;
25
+
26
+ export declare type CdeebeeModule = 'history' | 'listener' | 'storage' | 'cancelation' | 'queryQueue';
27
+
28
+ export declare interface CdeebeeRequestOptions<T> extends Partial<Pick<CdeebeeSettings<T>, 'fileKey' | 'bodyKey' | 'normalize'>> {
29
+ api: string;
30
+ files?: File[];
31
+ method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
32
+ body?: unknown;
33
+ headers?: Record<string, string>;
34
+ onResult?: (response: T) => void;
35
+ ignore?: boolean;
36
+ responseType?: 'json' | 'text' | 'blob';
37
+ listStrategy?: Partial<CdeebeeListStrategy<T>>;
38
+ historyClear?: boolean;
39
+ }
40
+
41
+ declare interface CdeebeeRequestState {
42
+ active: CdeebeeActiveRequest[];
43
+ errors: Record<string, CdeebeeHistoryState[]>;
44
+ done: Record<string, CdeebeeHistoryState[]>;
45
+ }
46
+
47
+ declare interface CdeebeeSettings<T> {
48
+ modules: CdeebeeModule[];
49
+ fileKey: string;
50
+ bodyKey: string;
51
+ mergeWithData: unknown;
52
+ mergeWithHeaders: unknown;
53
+ listStrategy?: CdeebeeListStrategy<T>;
54
+ normalize?: <T>(storage: CdeebeeState<T>, result: T, strategyList: CdeebeeListStrategy<T>) => T;
55
+ }
56
+
57
+ export declare interface CdeebeeState<T> {
58
+ settings: CdeebeeSettings<T>;
59
+ storage: T;
60
+ request: CdeebeeRequestState;
61
+ }
62
+
63
+ declare type CdeebeeStrategy = 'merge' | 'replace' | 'skip';
64
+
65
+ declare type CdeebeeValueItem<T> = NonEmptyPaths<T> extends infer P ? P extends readonly (string | number)[] ? {
66
+ key: P;
67
+ value: ValueAtPath<T, P>;
68
+ } : never : never;
69
+
70
+ export declare type CdeebeeValueList<T> = ReadonlyArray<CdeebeeValueItem<T>>;
71
+
72
+ /**
73
+ * Generic hook factory that creates a selector hook for cdeebee state.
74
+ * This allows the hooks to work with any Redux root state structure.
75
+ *
76
+ * @template RootState - The shape of the Redux root state
77
+ * @template Storage - The shape of the cdeebee storage
78
+ * @param selectCdeebee - Function to select the cdeebee slice from root state
79
+ * @returns An object containing all cdeebee hooks
80
+ */
81
+ export declare function createCdeebeeHooks<RootState, Storage>(selectCdeebee: (state: RootState) => CdeebeeState<Storage>): {
82
+ useLoading: (apiList: string[]) => boolean;
83
+ useRequestHistory: (api: string) => CdeebeeHistoryState[];
84
+ useRequestErrors: (api: string) => CdeebeeHistoryState[];
85
+ useStorageList: <K extends keyof Storage>(listName: K) => Storage[K];
86
+ useStorage: () => Storage;
87
+ useIsLoading: () => boolean;
88
+ };
89
+
90
+ export declare const factory: <T>(settings: CdeebeeSettings<T>, storage?: T) => Slice<CdeebeeState<T>, {
91
+ set(state: {
92
+ settings: {
93
+ modules: CdeebeeModule[];
94
+ fileKey: string;
95
+ bodyKey: string;
96
+ mergeWithData: unknown;
97
+ mergeWithHeaders: unknown;
98
+ listStrategy?: (CdeebeeListStrategy<T> | undefined extends infer V ? V extends object ? Draft<V> : V : never) | undefined;
99
+ normalize?: (<T_1>(storage: CdeebeeState<T_1>, result: T_1, strategyList: CdeebeeListStrategy<T_1>) => T_1) | undefined;
100
+ };
101
+ storage: T extends infer V ? V extends object ? Draft<V> : V : never;
102
+ request: {
103
+ active: {
104
+ api: string;
105
+ requestId: string;
106
+ }[];
107
+ errors: {
108
+ [x: string]: {
109
+ requestId: string;
110
+ api: string;
111
+ request: unknown;
112
+ }[];
113
+ };
114
+ done: {
115
+ [x: string]: {
116
+ requestId: string;
117
+ api: string;
118
+ request: unknown;
119
+ }[];
120
+ };
121
+ };
122
+ }, action: {
123
+ payload: CdeebeeValueList<T>;
124
+ }): void;
125
+ historyClear(state: {
126
+ settings: {
127
+ modules: CdeebeeModule[];
128
+ fileKey: string;
129
+ bodyKey: string;
130
+ mergeWithData: unknown;
131
+ mergeWithHeaders: unknown;
132
+ listStrategy?: (CdeebeeListStrategy<T> | undefined extends infer V ? V extends object ? Draft<V> : V : never) | undefined;
133
+ normalize?: (<T_1>(storage: CdeebeeState<T_1>, result: T_1, strategyList: CdeebeeListStrategy<T_1>) => T_1) | undefined;
134
+ };
135
+ storage: T extends infer V ? V extends object ? Draft<V> : V : never;
136
+ request: {
137
+ active: {
138
+ api: string;
139
+ requestId: string;
140
+ }[];
141
+ errors: {
142
+ [x: string]: {
143
+ requestId: string;
144
+ api: string;
145
+ request: unknown;
146
+ }[];
147
+ };
148
+ done: {
149
+ [x: string]: {
150
+ requestId: string;
151
+ api: string;
152
+ request: unknown;
153
+ }[];
154
+ };
155
+ };
156
+ }, action: {
157
+ payload?: string;
158
+ }): void;
159
+ }, "cdeebee", "cdeebee", SliceSelectors<CdeebeeState<T>>>;
160
+
161
+ declare type IsArray<T> = T extends readonly unknown[] ? true : T extends unknown[] ? true : false;
162
+
163
+ declare type KeyOf<T> = Extract<keyof T, string | number>;
164
+
165
+ declare type NonEmptyPaths<T> = Exclude<Paths<T>, []>;
166
+
167
+ declare type Paths<T, P extends readonly (string | number)[] = []> = IsArray<T> extends true ? P | Paths<ArrayElement<T>, Append<P, number>> : T extends object ? {
168
+ [K in KeyOf<T>]: Paths<T[K], Append<P, K>>;
169
+ }[KeyOf<T>] : P;
170
+
171
+ export declare const request: AsyncThunk< {
172
+ result: unknown;
173
+ startedAt: string;
174
+ endedAt: string;
175
+ }, CdeebeeRequestOptions<unknown>, AsyncThunkConfig>;
176
+
177
+ /**
178
+ * Standalone hook that can be used without createCdeebeeHooks.
179
+ * Assumes the cdeebee slice is at state.cdeebee.
180
+ *
181
+ * @returns true if any request is active
182
+ */
183
+ export declare function useIsLoading<Storage = unknown>(): boolean;
184
+
185
+ /**
186
+ * Standalone hook that can be used without createCdeebeeHooks.
187
+ * Assumes the cdeebee slice is at state.cdeebee.
188
+ *
189
+ * @param apiList - Array of API endpoints to check
190
+ * @returns true if any of the APIs are currently active/loading
191
+ *
192
+ * @example
193
+ * const isLoading = useLoading(['/api/forums', '/api/threads']);
194
+ */
195
+ export declare function useLoading<Storage = unknown>(apiList: string[]): boolean;
196
+
197
+ /**
198
+ * Standalone hook that can be used without createCdeebeeHooks.
199
+ * Assumes the cdeebee slice is at state.cdeebee.
200
+ *
201
+ * @param api - The API endpoint
202
+ * @returns Array of error history entries
203
+ */
204
+ export declare function useRequestErrors<Storage = unknown>(api: string): CdeebeeHistoryState[];
205
+
206
+ /**
207
+ * Standalone hook that can be used without createCdeebeeHooks.
208
+ * Assumes the cdeebee slice is at state.cdeebee.
209
+ *
210
+ * @param api - The API endpoint
211
+ * @returns Array of successful request history entries
212
+ */
213
+ export declare function useRequestHistory<Storage = unknown>(api: string): CdeebeeHistoryState[];
214
+
215
+ /**
216
+ * Standalone hook that can be used without createCdeebeeHooks.
217
+ * Assumes the cdeebee slice is at state.cdeebee.
218
+ *
219
+ * @returns The complete storage object
220
+ */
221
+ export declare function useStorage<Storage>(): Storage;
222
+
223
+ /**
224
+ * Standalone hook that can be used without createCdeebeeHooks.
225
+ * Assumes the cdeebee slice is at state.cdeebee.
226
+ *
227
+ * @param listName - The name of the list in storage
228
+ * @returns The list data
229
+ */
230
+ export declare function useStorageList<Storage, K extends keyof Storage>(listName: K): Storage[K];
231
+
232
+ declare type ValueAtPath<T, P extends readonly (string | number)[]> = P extends [] ? T : P extends readonly [infer K, ...infer R] ? K extends keyof T ? ValueAtPath<T[K], Extract<R, readonly (string | number)[]>> : T extends readonly (infer U)[] | (infer U)[] ? K extends number | `${number}` ? ValueAtPath<U, Extract<R, readonly (string | number)[]>> : never : never : never;
233
+
234
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,298 @@
1
+ import { createAsyncThunk as I, createSlice as P, current as x } from "@reduxjs/toolkit";
2
+ import { useSelector as d } from "react-redux";
3
+ function f(e, r, s) {
4
+ e.modules.includes(r) && s();
5
+ }
6
+ function y(e) {
7
+ return e !== null && typeof e == "object" && !Array.isArray(e);
8
+ }
9
+ function b(e, r) {
10
+ if (!y(e) || !y(r))
11
+ return r;
12
+ const s = { ...e }, o = r;
13
+ for (const t in o)
14
+ if (Object.prototype.hasOwnProperty.call(o, t)) {
15
+ const u = s[t], i = o[t];
16
+ y(u) && y(i) && !Array.isArray(u) && !Array.isArray(i) ? s[t] = b(u, i) : s[t] = i;
17
+ }
18
+ return s;
19
+ }
20
+ function C(e, r) {
21
+ const s = { ...r };
22
+ for (const o of e)
23
+ delete s[o];
24
+ return s;
25
+ }
26
+ function E(e, r) {
27
+ for (let s = 0; s < r.length; s++) {
28
+ const o = r[s], t = o.key, u = o.value;
29
+ if (t.length === 0)
30
+ continue;
31
+ let i = e;
32
+ for (let n = 0; n < t.length - 1; n++) {
33
+ const c = t[n];
34
+ if (Array.isArray(i)) {
35
+ const a = typeof c == "number" ? c : Number(c);
36
+ (!(a in i) || !y(i[a])) && (i[a] = {}), i = i[a];
37
+ } else {
38
+ const a = String(c);
39
+ if (!(a in i)) {
40
+ const g = typeof t[n + 1] == "number" || !isNaN(Number(t[n + 1])) && String(Number(t[n + 1])) === String(t[n + 1]);
41
+ i[a] = g ? [] : {};
42
+ }
43
+ const l = i[a];
44
+ i = Array.isArray(l) || y(l) ? l : {};
45
+ }
46
+ }
47
+ Array.isArray(i) || (i[String(t[t.length - 1])] = u);
48
+ }
49
+ }
50
+ class N {
51
+ constructor() {
52
+ this.byRequestId = /* @__PURE__ */ new Map(), this.byApi = /* @__PURE__ */ new Map();
53
+ }
54
+ add(r, s, o) {
55
+ const t = { requestId: s, controller: o, api: r };
56
+ this.byRequestId.set(s, t), this.byApi.has(r) || this.byApi.set(r, /* @__PURE__ */ new Set()), this.byApi.get(r).add(s);
57
+ }
58
+ delete(r) {
59
+ const s = this.byRequestId.get(r);
60
+ if (!s) return;
61
+ this.byRequestId.delete(r);
62
+ const o = this.byApi.get(s.api);
63
+ o && (o.delete(r), o.size === 0 && this.byApi.delete(s.api));
64
+ }
65
+ abortAllForApi(r, s) {
66
+ const o = this.byApi.get(r);
67
+ o && o.forEach((t) => {
68
+ if (t !== s) {
69
+ const u = this.byRequestId.get(t);
70
+ u && (u.controller.abort(), this.delete(t));
71
+ }
72
+ });
73
+ }
74
+ }
75
+ const R = new N();
76
+ function T(e, r) {
77
+ R.abortAllForApi(e, r);
78
+ }
79
+ function H(e, r, s) {
80
+ const o = new AbortController(), t = () => {
81
+ R.delete(s);
82
+ };
83
+ return e.addEventListener("abort", () => {
84
+ o.abort(), t();
85
+ }), {
86
+ controller: o,
87
+ init: () => R.add(r, s, o),
88
+ drop: t
89
+ };
90
+ }
91
+ class j {
92
+ constructor() {
93
+ this.currentPromise = Promise.resolve(), this.queueLength = 0;
94
+ }
95
+ async enqueue(r) {
96
+ this.queueLength++;
97
+ const s = this.currentPromise;
98
+ return this.currentPromise = s.then(() => r(), () => r()).finally(() => {
99
+ this.queueLength--;
100
+ }), this.currentPromise;
101
+ }
102
+ getQueueLength() {
103
+ return this.queueLength;
104
+ }
105
+ clear() {
106
+ this.queueLength = 0;
107
+ }
108
+ }
109
+ const O = new j(), S = I(
110
+ "cdeebee/request",
111
+ async (e, { rejectWithValue: r, getState: s, requestId: o, signal: t }) => {
112
+ const u = (/* @__PURE__ */ new Date()).toUTCString(), { cdeebee: { settings: i } } = s(), n = H(t, e.api, o), c = e.onResult && typeof e.onResult == "function";
113
+ f(i, "cancelation", n.init);
114
+ const a = async () => {
115
+ try {
116
+ const { method: l = "POST", body: g, headers: K = {} } = e, D = { ...i.mergeWithHeaders ?? {}, ...K }, z = { ...i.mergeWithData ?? {}, ...g ?? {} };
117
+ let p = JSON.stringify(z);
118
+ if (e.files) {
119
+ const q = new FormData(), w = e.fileKey || i.fileKey, L = e.bodyKey || i.bodyKey;
120
+ for (let A = 0; A < e.files.length; A += 1)
121
+ w && q.append(w, e.files[A]);
122
+ L && q.append(L, p), p = q;
123
+ }
124
+ const h = await fetch(e.api, {
125
+ method: l,
126
+ headers: {
127
+ "ui-request-id": o,
128
+ "Content-Type": "application/json",
129
+ ...D
130
+ },
131
+ signal: n.controller.signal,
132
+ body: p
133
+ });
134
+ f(i, "cancelation", n.drop);
135
+ let m;
136
+ const k = e.responseType || "json";
137
+ return k === "text" ? m = await h.text() : k === "blob" ? m = await h.blob() : m = await h.json(), h.ok ? (c && e.onResult(m), { result: m, startedAt: u, endedAt: (/* @__PURE__ */ new Date()).toUTCString() }) : (c && e.onResult(m), r(h));
138
+ } catch (l) {
139
+ return f(i, "cancelation", n.drop), c && e.onResult(l), l instanceof Error && l.name === "AbortError" ? r({ message: "Request was cancelled", cancelled: !0 }) : r({ message: l instanceof Error ? l.message : "Unknown error occurred" });
140
+ }
141
+ };
142
+ return i.modules.includes("queryQueue") ? O.enqueue(a) : a();
143
+ }
144
+ );
145
+ function Q(e) {
146
+ return y(e) && Array.isArray(e.data) && typeof e.primaryKey == "string";
147
+ }
148
+ function U(e, r) {
149
+ const s = {};
150
+ for (const o of e)
151
+ if (y(o) && r in o) {
152
+ const t = String(o[r]);
153
+ s[t] = o;
154
+ }
155
+ return s;
156
+ }
157
+ function v(e, r, s, o) {
158
+ return s === "replace" ? r : s === "merge" ? b(e, r) : s === "skip" ? e : (console.warn(`Cdeebee: Unknown strategy "${s}" for key "${o}". Skipping normalization.`), b(e, r));
159
+ }
160
+ function M(e, r, s) {
161
+ const o = Object.keys(r), t = y(e.storage) ? e.storage : {}, u = { ...t }, i = /* @__PURE__ */ new Set();
162
+ for (const n of o) {
163
+ const c = r[n];
164
+ if (c == null || typeof c == "string") {
165
+ i.add(n);
166
+ continue;
167
+ }
168
+ const a = s[n] ?? "merge";
169
+ if (a === "skip" && !(n in t))
170
+ continue;
171
+ const l = n in t ? t[n] : {};
172
+ if (Q(c)) {
173
+ const g = U(c.data, c.primaryKey);
174
+ u[n] = v(l, g, a, n);
175
+ continue;
176
+ }
177
+ y(c) ? u[n] = v(l, c, a, n) : u[n] = c;
178
+ }
179
+ return i.size > 0 ? C(Array.from(i), u) : u;
180
+ }
181
+ const W = {
182
+ settings: {
183
+ modules: ["history", "listener", "storage", "cancelation"],
184
+ fileKey: "file",
185
+ bodyKey: "value",
186
+ listStrategy: {},
187
+ mergeWithData: {},
188
+ mergeWithHeaders: {}
189
+ },
190
+ storage: {},
191
+ request: {
192
+ active: [],
193
+ errors: {},
194
+ done: {}
195
+ }
196
+ }, J = (e, r) => P({
197
+ name: "cdeebee",
198
+ initialState: b(W, { settings: e, storage: r ?? {} }),
199
+ reducers: {
200
+ set(o, t) {
201
+ E(o.storage, t.payload);
202
+ },
203
+ historyClear(o, t) {
204
+ const u = t.payload;
205
+ u ? (delete o.request.done[u], delete o.request.errors[u]) : (o.request.done = {}, o.request.errors = {});
206
+ }
207
+ },
208
+ extraReducers: (o) => {
209
+ o.addCase(S.pending, (t, u) => {
210
+ const i = u.meta.arg.api, n = u.meta.requestId;
211
+ u.meta.arg.historyClear && f(t.settings, "history", () => {
212
+ delete t.request.done[i], delete t.request.errors[i];
213
+ }), f(t.settings, "cancelation", () => {
214
+ T(i, n);
215
+ }), f(t.settings, "listener", () => {
216
+ t.request.active.push({ api: i, requestId: n });
217
+ });
218
+ }).addCase(S.fulfilled, (t, u) => {
219
+ const i = u.meta.requestId, n = u.meta.arg.api;
220
+ f(t.settings, "listener", () => {
221
+ t.request.active = t.request.active.filter((c) => !(c.api === n && c.requestId === i));
222
+ }), f(t.settings, "history", () => {
223
+ t.request.done[n] || (t.request.done[n] = []), t.request.done[n].push({ api: n, request: u.payload, requestId: i });
224
+ }), f(t.settings, "storage", () => {
225
+ if (u.meta.arg.ignore)
226
+ return;
227
+ const c = u.meta.arg.listStrategy ?? t.settings.listStrategy ?? {}, a = u.meta.arg.normalize ?? t.settings.normalize ?? M, l = x(t), g = a(l, u.payload.result, c);
228
+ t.storage = g;
229
+ });
230
+ }).addCase(S.rejected, (t, u) => {
231
+ const i = u.meta.requestId, n = u.meta.arg.api;
232
+ f(t.settings, "listener", () => {
233
+ t.request.active = t.request.active.filter((c) => !(c.api === n && c.requestId === i));
234
+ }), f(t.settings, "history", () => {
235
+ t.request.errors[n] || (t.request.errors[n] = []), t.request.errors[n].push({ requestId: i, api: n, request: u.error });
236
+ });
237
+ });
238
+ }
239
+ });
240
+ function B(e) {
241
+ function r(n) {
242
+ return d((c) => e(c).request.active.some((l) => n.includes(l.api)));
243
+ }
244
+ function s(n) {
245
+ return d((c) => e(c).request.done[n] ?? []);
246
+ }
247
+ function o(n) {
248
+ return d((c) => e(c).request.errors[n] ?? []);
249
+ }
250
+ function t(n) {
251
+ return d((c) => e(c).storage[n]);
252
+ }
253
+ function u() {
254
+ return d((n) => e(n).storage);
255
+ }
256
+ function i() {
257
+ return d((n) => e(n).request.active.length > 0);
258
+ }
259
+ return {
260
+ useLoading: r,
261
+ useRequestHistory: s,
262
+ useRequestErrors: o,
263
+ useStorageList: t,
264
+ useStorage: u,
265
+ useIsLoading: i
266
+ };
267
+ }
268
+ function G(e) {
269
+ return d((r) => r.cdeebee.request.active.some((s) => e.includes(s.api)));
270
+ }
271
+ function X(e) {
272
+ return d((r) => r.cdeebee.request.done[e] ?? []);
273
+ }
274
+ function Y(e) {
275
+ return d((r) => r.cdeebee.request.errors[e] ?? []);
276
+ }
277
+ function Z(e) {
278
+ return d((r) => r.cdeebee.storage[e]);
279
+ }
280
+ function _() {
281
+ return d((e) => e.cdeebee.storage);
282
+ }
283
+ function V() {
284
+ return d((e) => e.cdeebee.request.active.length > 0);
285
+ }
286
+ export {
287
+ E as batchingUpdate,
288
+ B as createCdeebeeHooks,
289
+ J as factory,
290
+ S as request,
291
+ V as useIsLoading,
292
+ G as useLoading,
293
+ Y as useRequestErrors,
294
+ X as useRequestHistory,
295
+ _ as useStorage,
296
+ Z as useStorageList
297
+ };
298
+ //# sourceMappingURL=index.js.map