synapse-storage 3.0.11 → 3.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Synapse Storage
2
2
 
3
- > **🇺🇸 English** | [🇷🇺 Русский](./docs/ru/README.md)
3
+ > **🇺🇸 English** | [🇷🇺 Русский](./docs/ru/README.md) | [📝 ChangeLog](./CHANGELOG.md)
4
4
 
5
5
  State management toolkit + API client
6
6
 
@@ -99,6 +99,97 @@ npm install synapse-storage rxjs react react-dom
99
99
 
100
100
  ---
101
101
 
102
+ ## 📊 Why Synapse Storage?
103
+
104
+ **One library instead of many** - Synapse combines functionality that usually requires multiple dependencies:
105
+
106
+ | What you get | Traditional approach | Synapse Storage |
107
+ |--------------|---------------------|---------|
108
+ | **State Management** | Redux + RTK (~45KB) | ✅ |
109
+ | **HTTP Client + Caching** | React Query (~39KB) | ✅|
110
+ | **Reactive Effects** | Redux-Observable (~25KB) | ✅|
111
+ | **Storage Adapters** | Custom solutions | ✅|
112
+ | **React Integration** | Custom hooks | ✅|
113
+ | **Computed Selectors** | Reselect (~5KB) | ✅|
114
+ | **Middleware System** | Custom implementation | ✅|
115
+ | **Plugin Architecture** | Custom implementation | ✅|
116
+
117
+ ### Bundle Size Comparison
118
+
119
+ ```typescript
120
+ // Traditional stack
121
+ import { configureStore } from '@reduxjs/toolkit' // ~45KB
122
+ import { createApi } from '@reduxjs/toolkit/query' // included in RTK
123
+ import { QueryClient } from '@tanstack/react-query' // ~39KB
124
+ import { createEpicMiddleware } from 'redux-observable' // ~25KB
125
+ // Total: ~109KB + custom implementations
126
+
127
+ // Synapse Storage
128
+ import { createSynapse } from 'synapse-storage' // ~171KB
129
+ // Total: 171KB with ALL features included
130
+ ```
131
+
132
+ ### Modular Usage
133
+
134
+ Don't need everything? Import only what you use:
135
+
136
+ | Use Case | Import | Size | Comparison |
137
+ |-------------------|------------------------|------|---------------------------|
138
+ | **Basic state** | `synapse-storage/core` | ~42KB | vs Redux: 45KB |
139
+ | **+ HTTP client** | `+ /api` | +13KB | vs React Query: 39KB |
140
+ | **+ Reactive** | `+ /reactive` | +8KB | vs Redux-Observable: 25KB |
141
+ | **+ React hooks** | `+ /react` | +5KB | vs Custom hooks |
142
+ | **Full package** | all modules | ~171KB |vs 109KB stack + custom |
143
+
144
+ > **🎯 Result:** Similar or better performance with unified API and TypeScript support out of the box
145
+
146
+ ## 🧩 Modular Architecture "Like a Constructor"
147
+
148
+ **Use only what you need** - each module works independently:
149
+
150
+ ### 🎯 Flexible Usage Scenarios
151
+
152
+ ```typescript
153
+ // 📦 Minimal project - storage only
154
+ import { MemoryStorage } from 'synapse-storage/core' // 42KB
155
+
156
+ // 📦 + Add HTTP client when needed
157
+ import { ApiClient } from 'synapse-storage/api' // +13KB
158
+
159
+ // 📦 + Add reactive effects when required
160
+ import { createDispatcher } from 'synapse-storage/reactive' // +8KB
161
+
162
+ // 📦 + Add React hooks for UI
163
+ import { useSelector } from 'synapse-storage/react' // +5KB
164
+ ```
165
+
166
+ ### 🔧 Or Create Your Own Implementation
167
+
168
+ ```typescript
169
+ // Use core + your solutions
170
+ import { IStorage } from 'synapse-storage/core'
171
+
172
+ // Implement your HTTP client
173
+ class MyApiClient { /* your logic */ }
174
+
175
+ // Implement your React hooks
176
+ const useMyCustomHook = () => { /* your logic */ }
177
+
178
+ // Combine as convenient!
179
+ ```
180
+
181
+ ### 🎨 Constructor Approach Benefits
182
+
183
+ - **🚀 Quick Start** - begin with core, add modules as project grows
184
+ - **📦 Optimal Bundle** - don't pay for unused functionality
185
+ - **🔄 Flexibility** - replace any module with your implementation
186
+ - **🛠️ Compatibility** - modules work independently but integrate perfectly
187
+ - **📈 Scalability** - from simple state to full-featured architecture
188
+
189
+ > **💡 Evolution Example:** Started with MemoryStorage → added ApiClient → connected reactive effects → integrated React hooks. **Each step is optional!**
190
+ >
191
+ ---
192
+
102
193
  ## 📁 Documentation Structure
103
194
 
104
195
  ```
package/dist/api.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { I as IStorage } from './storage.interface-Dl8SLUd1.js';
1
+ import { j as IStorage } from './storage.interface-2HKvqdAJ.js';
2
2
 
3
3
  /**
4
4
  * Тип для функции отписки от событий
package/dist/api.js CHANGED
@@ -1 +1 @@
1
- var k={debug:(r,...e)=>{process.env.NODE_ENV!=="production"&&console.debug(`[API] ${r}`,...e)},log:(r,...e)=>{process.env.NODE_ENV!=="production"&&console.log(`[API] ${r}`,...e)},info:(r,...e)=>{console.info(`[API] ${r}`,...e)},warn:(r,...e)=>{console.warn(`[API] ${r}`,...e)},error:(r,...e)=>{console.error(`[API] ${r}`,...e)}};function O(r){return`${r?`${r}|`:""}${Math.random().toString(36).substring(2,9)+Date.now().toString(36)}`}function I(r){let e={};return r.forEach((t,a)=>{e[a.toLowerCase()]=t}),e}function T(r={},e={}){return{...r,...e,getFromStorage:r.getFromStorage||(t=>{try{let a=localStorage.getItem(t);return a?JSON.parse(a):void 0}catch(a){console.warn(`[API] \u041E\u0448\u0438\u0431\u043A\u0430 \u0447\u0442\u0435\u043D\u0438\u044F \u0438\u0437 localStorage: ${a}`);return}}),getCookie:r.getCookie||(t=>{try{let a=document.cookie.match(new RegExp(`(?:^|; )${t.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g,"\\$1")}=([^;]*)`));return a?decodeURIComponent(a[1]):void 0}catch(a){console.warn(`[API] \u041E\u0448\u0438\u0431\u043A\u0430 \u0447\u0442\u0435\u043D\u0438\u044F cookie: ${a}`);return}})}}async function D(r,e){let t=new Headers,a=e||T({},{});if(r)try{t=await Promise.resolve(r(t,a))}catch(n){console.warn("[API] \u041E\u0448\u0438\u0431\u043A\u0430 \u043F\u0440\u0438 \u043F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043A\u0435 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u043E\u0432",n)}return t}function K(r,e){return async(t,a)=>{let n=new Headers(t);if(r)try{n=await Promise.resolve(r(n,a))}catch(i){console.warn("[API] \u041E\u0448\u0438\u0431\u043A\u0430 \u043F\u0440\u0438 \u043F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043A\u0435 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u044B\u0445 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u043E\u0432",i)}if(e)try{n=await Promise.resolve(e(n,a))}catch(i){console.warn("[API] \u041E\u0448\u0438\u0431\u043A\u0430 \u043F\u0440\u0438 \u043F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043A\u0435 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u043E\u0432 \u044D\u043D\u0434\u043F\u043E\u0438\u043D\u0442\u0430",i)}return n}}var q=(s=>(s.Json="json",s.Blob="blob",s.ArrayBuffer="arrayBuffer",s.Text="text",s.FormData="formData",s.Raw="raw",s))(q||{});function Q(r){let e=r.toLowerCase().split(";")[0].trim();if(e.includes("application/json"))return"json";if(e.includes("text/"))return"text";if(e.includes("multipart/form-data"))return"formData";if(e.includes("application/octet-stream")||e.includes("application/pdf")||e.includes("image/")||e.includes("audio/")||e.includes("video/"))return"blob"}function H(r){let e=r.get("content-type")||"",t=r.get("content-disposition")||"",a=e.includes("application/octet-stream")||e.includes("application/pdf")||e.includes("image/")||e.includes("audio/")||e.includes("video/"),n=t.includes("attachment")||t.includes("filename=");return a||n}function L(r){let e=r.get("content-disposition");if(!e)return;let t=e.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);if(t&&t[1])return t[1].replace(/['"]/g,"").trim()}function B(r){let e=r.get("content-type")||"",t=r.get("content-disposition")||"",a=r.get("content-length");return H(r)?{filename:L(r),contentType:e,contentDisposition:t,size:a?parseInt(a,10):void 0}:void 0}async function J(r,e){let t=e,a=r.headers.get("content-type")||"";!t&&a&&(H(r.headers)?t="blob":t=Q(a)),t||(t="json");try{let n;switch((t==="blob"||t==="arrayBuffer")&&(n=B(r.headers)),t){case"json":try{let s=await r.json();return r.ok?{data:s,fileMetadata:n}:{error:s,fileMetadata:n}}catch{let l=await r.text();return r.ok?{data:l,fileMetadata:n}:{error:l,fileMetadata:n}}case"text":{let s=await r.text();return r.ok?{data:s,fileMetadata:n}:{error:s,fileMetadata:n}}case"blob":{let s=await r.blob();return r.ok?{data:s,fileMetadata:n}:{error:s,fileMetadata:n}}case"arrayBuffer":{let s=await r.arrayBuffer();return r.ok?{data:s,fileMetadata:n}:{error:s,fileMetadata:n}}case"formData":{let s=await r.formData();return r.ok?{data:s,fileMetadata:n}:{error:s,fileMetadata:n}}case"raw":return r.ok?{data:r,fileMetadata:n}:{error:r,fileMetadata:n};default:let i=await r.blob();return r.ok?{data:i,fileMetadata:n}:{error:i,fileMetadata:n}}}catch(n){return console.error(`[API] \u041E\u0448\u0438\u0431\u043A\u0430 \u0438\u0437\u0432\u043B\u0435\u0447\u0435\u043D\u0438\u044F \u0434\u0430\u043D\u043D\u044B\u0445 \u0438\u0437 \u043E\u0442\u0432\u0435\u0442\u0430 (\u0444\u043E\u0440\u043C\u0430\u0442: ${t})`,n),r.ok?{data:void 0}:{error:n}}}function M(r){let{baseUrl:e,timeout:t=3e4,fetchFn:a=fetch,credentials:n="same-origin"}=r;return async(i,s={},l)=>{let{path:h,method:C,body:o,query:u,responseFormat:f}=i,{signal:b,timeout:R=t,responseFormat:p}=s,A=p||f,m=new URL(h.startsWith("http")?h:`${e}${h}`);u&&Object.entries(u).forEach(([d,c])=>{c!=null&&(Array.isArray(c)?c.forEach(w=>m.searchParams.append(d,String(w))):m.searchParams.append(d,String(c)))});let E;if(o!==void 0)if(o instanceof FormData||o instanceof Blob)E=o;else if(typeof o=="object"&&o!==null)try{E=JSON.stringify(o),l.has("Content-Type")||l.set("Content-Type","application/json")}catch(d){console.error("[API] \u041E\u0448\u0438\u0431\u043A\u0430 \u0441\u0435\u0440\u0438\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0435\u043B\u0430 \u0437\u0430\u043F\u0440\u043E\u0441\u0430",d),E=String(o)}else E=String(o);let P,g=new Promise((d,c)=>{R&&(P=window.setTimeout(()=>{c(new Error(`\u041F\u0440\u0435\u0432\u044B\u0448\u0435\u043D\u043E \u0432\u0440\u0435\u043C\u044F \u043E\u0436\u0438\u0434\u0430\u043D\u0438\u044F \u0437\u0430\u043F\u0440\u043E\u0441\u0430 (${R}\u043C\u0441)`))},R))});try{let d=a(m.toString(),{method:C,headers:l,body:E,signal:b,credentials:n}),c=await Promise.race([d,g]),{data:w,error:F,fileMetadata:j}=await J(c,A);return{data:w,error:F,ok:c.ok,status:c.status,statusText:c.statusText,headers:c.headers,fileDownloadResult:j}}catch(d){let c=d;return console.error("[API] \u041E\u0448\u0438\u0431\u043A\u0430 \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u044F \u0437\u0430\u043F\u0440\u043E\u0441\u0430",c),{error:c,ok:!1,status:0,statusText:c.message,headers:new Headers}}finally{P&&window.clearTimeout(P)}}}function $(r,e=[]){let t={};return!r||e.length===0||e.forEach(a=>{r.has(a)&&(t[a]=r.get(a)||"")}),t}var v=class{constructor(e,t,a,n,i,s){this.name=e;this.queryStorage=t;this.configCurrentEndpoint=a;this.cacheableHeaderKeys=n;this.globalCacheConfig=i;this.baseQueryConfig=s;this.prepareHeaders=K(s.prepareHeaders,a.prepareHeaders),this.queryFunction=M({baseUrl:s.baseUrl,fetchFn:s.fetchFn,timeout:s.timeout,credentials:s.credentials}),this.cacheableHeaders=[...n||[],...a.includeCacheableHeaderKeys||[]].filter(l=>!a.excludeCacheableHeaderKeys?.includes(l)),this.meta.name=e,this.meta.tags=a.tags??this.meta.tags,this.meta.invalidatesTags=a.invalidatesTags??this.meta.invalidatesTags,this.meta.cache=this.queryStorage.createCacheConfig(this.configCurrentEndpoint)??this.meta.cache}endpointSubscribers=new Set;fetchCounts=0;meta={cache:!1,invalidatesTags:[],name:"",tags:[]};queryFunction;cacheableHeaders;prepareHeaders;request(e,t){this.fetchCounts++;let a=O(this.name),n=new AbortController,i=new Set,s={status:"idle",requestParams:e,headers:{},error:void 0,data:void 0,fromCache:!1},l=T({requestParams:e},t?.context||{}),h=o=>{Object.assign(s,o),i.forEach(u=>{u({...s})})},C=new Promise(async(o,u)=>{try{let f=await D(this.prepareHeaders,l),b=$(f,t?.cacheableHeaderKeys?t.cacheableHeaderKeys:this.cacheableHeaders),R=this.queryStorage.shouldCache(this.configCurrentEndpoint,t),[p,A]=this.queryStorage.createCacheKey(this.name,{...e,...b}),m;if(R&&(m=await this.queryStorage.getCachedResult(p)),m)h({fromCache:!0,status:"success",data:m.data,error:void 0,headers:m.headers,requestParams:e}),o({...m,fromCache:!0});else{h({fromCache:!1,status:"loading"});let E=this.configCurrentEndpoint.request(e,t?.context),P={...t,signal:n.signal},g=await this.queryFunction(E,P,f);if(g.ok){let{headers:d,...c}=g;if(R){let w=this.queryStorage.createCacheConfig(this.configCurrentEndpoint);await this.queryStorage.setCachedResult(p,{...c,headers:I(d)},w,A??{},this.configCurrentEndpoint.tags??[],this.configCurrentEndpoint.invalidatesTags??[])}h({fromCache:!1,status:"success",data:g.data,error:void 0,headers:g.headers,requestParams:e}),this.endpointSubscribers.forEach(w=>{let F={status:"success",fetchCounts:this.fetchCounts,meta:this.meta,cacheableHeaders:this.cacheableHeaders,error:void 0};w(F)}),o({...g,fromCache:!1})}else h({fromCache:!1,status:"error",data:void 0,error:g.error,headers:g.headers,requestParams:e}),this.endpointSubscribers.forEach(d=>{let c={status:"error",fetchCounts:this.fetchCounts,meta:this.meta,cacheableHeaders:this.cacheableHeaders,error:g.error};d(c)}),u(g.error)}}catch(f){h({fromCache:!1,status:"error",data:void 0,error:f,headers:void 0,requestParams:e}),u(f)}});return{id:a,subscribe(o,u={}){let{autoUnsubscribe:f=!0}=u;i.add(o),o(s);let b=()=>i.delete(o);return f&&C.finally(()=>{b()}),b},wait:()=>C,waitWithCallbacks(o={}){let{idle:u,loading:f,success:b,error:R}=o;return this.subscribe(p=>{switch(p.status){case"idle":u?.(p);break;case"loading":f?.(p);break;case"success":b?.(p.data,p);break;case"error":R?.(p.error,p);break}},{autoUnsubscribe:!0}),C},abort:()=>{n&&!n.signal.aborted&&n.abort()},then:(o,u)=>C.then(o,u),catch:o=>C.catch(o),finally:o=>C.finally(o)}}subscribe(e){this.endpointSubscribers.add(e);let t={status:"idle",fetchCounts:this.fetchCounts,meta:this.meta,cacheableHeaders:this.cacheableHeaders,error:void 0};return e(t),()=>this.endpointSubscribers.delete(e)}reset(){return this.fetchCounts=0,Promise.resolve()}destroy(){this.endpointSubscribers.clear()}};var x=class{constructor(e,t=!1){this.value=e;this.isRawKey=t}toString(){return this.value}toJSON(){return this.value}valueOf(){return this.value}isUnparseable(){return this.isRawKey}};var y=class{static createMetadata(e=0,t=[]){let a=Date.now(),n=e>0?a+e:1/0;return{createdAt:a,updatedAt:a,expiresAt:n,tags:t,createdAtDateTime:this.formatDateTime(a),updatedAtDateTime:this.formatDateTime(a),expiresAtDateTime:n===1/0?"never":this.formatDateTime(n)}}static formatDateTime(e){return new Date(e).toISOString()}static isExpired(e){return Date.now()>e.expiresAt}static updateMetadata(e){return{...e,updatedAt:Date.now()}}static createKey(...e){return new x(e.join("_"))}static createApiKey(e,t){if(!t)return[new x(e,!0),t];let a=Object.entries(t).sort(([n],[i])=>n.localeCompare(i)).map(([n,i])=>`${n}=${i}`).join("&");return[new x(`${e}_${a}`,!0),t]}static hasAnyTag(e,t=[]){return!e.tags||!t.length?!1:t.some(a=>e.tags?.includes(a))}};var S=class{constructor(e,t){this.storageExternal=e;this.globalCacheConfig=t}storage=null;cleanupInterval=null;defaultCacheOptions={ttl:5*60*1e3,cleanup:{enabled:!0,interval:10*60*1e3},invalidateOnError:!0};async initialize(){return await this.createStorage(),this.startCleanupInterval(),this}async createStorage(){try{let e=this.storageExternal;await e.initialize(),this.storage=e}catch(e){throw console.error("\u041E\u0448\u0438\u0431\u043A\u0430 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u0438 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430",e),e}}startCleanupInterval(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=null);let e=typeof this.globalCacheConfig=="object"?this.globalCacheConfig.cleanup:this.defaultCacheOptions.cleanup;e?.enabled&&e.interval&&(this.cleanupInterval=setInterval(()=>{this.cleanup().catch(t=>console.error("\u041E\u0448\u0438\u0431\u043A\u0430 \u043F\u0440\u0438 \u043E\u0447\u0438\u0441\u0442\u043A\u0435 \u043A\u044D\u0448\u0430:",t))},e.interval))}getStorage(){return this.storage}createCacheKey(e,t){return y.createApiKey(e,t)}async getCachedResult(e){if(!this.storage)throw new Error("\u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u043D\u0435 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043E");let t=await this.storage.get(e);if(!t)return;if(y.isExpired(t.metadata)){await this.storage.delete(e);return}let a={...t,metadata:y.updateMetadata(t.metadata)};return await this.storage.set(e,a),t.data}async setCachedResult(e,t,a,n,i,s){if(!this.storage)throw new Error("\u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u043D\u0435 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043E");s?.length&&await this.invalidateCacheByTags(s);let l=y.createMetadata(a.ttl,i),h={data:t,metadata:l,params:n};await this.storage.set(e,h)}shouldCache(e,t){return!(this.globalCacheConfig===!1||e?.cache===!1||typeof e?.cache=="object"&&e?.cache.ttl===0||t?.disableCache===!0||this.globalCacheConfig===void 0&&e?.cache===void 0)}createCacheConfig(e){let t=this.defaultCacheOptions;if(typeof this.globalCacheConfig=="object"&&(t=this.globalCacheConfig),typeof e?.cache=="object"){let a=e.cache;t={...t,...a}}return t}async invalidateCacheByTags(e){if(!this.storage)throw new Error("\u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u043D\u0435 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043E");let t=await this.storage.keys();for(let a of t){let n=await this.storage.get(a);n&&y.hasAnyTag(n.metadata,e)&&await this.storage.delete(a)}}async invalidateCache(e){if(!this.storage)throw new Error("\u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u043D\u0435 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043E");await this.storage.delete(e)}async cleanup(){if(!this.storage)throw new Error("\u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u043D\u0435 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043E");let e=await this.storage.keys();for(let t of e){let a=await this.storage.get(t);a&&y.isExpired(a.metadata)&&await this.storage.delete(t)}}async destroy(){this.cleanupInterval&&(window.clearInterval(this.cleanupInterval),this.cleanupInterval=null),this.storage&&(await this.storage.destroy(),this.storage=null)}};var U=class{queryStorage;cacheableHeaderKeys;globalCacheConfig;baseQueryConfig;storageExternal;createEndpoints;endpoints={};constructor(e){this.cacheableHeaderKeys=e.cacheableHeaderKeys,this.globalCacheConfig=e.cache,this.baseQueryConfig=e.baseQuery,this.storageExternal=e.storage,this.createEndpoints=e.endpoints}async init(){return this.queryStorage=await new S(this.storageExternal,this.globalCacheConfig).initialize(),await this.initializeEndpoints(),this}async initializeEndpoints(){let e=a=>a,t=await this.createEndpoints(e)||{};for(let[a,n]of Object.entries(t)){let i=a;this.endpoints[i]=new v(a,this.queryStorage,n,this.cacheableHeaderKeys,this.globalCacheConfig,this.baseQueryConfig)}}getEndpoints(){return this.endpoints}async request(e,t,a){let i=this.getEndpoints()[e];if(!i)throw new Error(`\u042D\u043D\u0434\u043F\u043E\u0438\u043D\u0442 ${String(e)} \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D`);try{return await i.request(t,a).wait()}catch(s){throw k.error(`\u041E\u0448\u0438\u0431\u043A\u0430 \u0437\u0430\u043F\u0440\u043E\u0441\u0430 \u043A ${String(e)}`,{error:s,params:t}),s}}async destroy(){await Promise.all(Object.values(this.endpoints).map(async e=>(e.destroy(),Promise.resolve()))),this.endpoints={},await this.queryStorage.destroy()}};export{U as ApiClient,q as ResponseFormat,k as apiLogger,O as createUniqueId,I as headersToObject};
1
+ var k={debug:(r,...e)=>{process.env.NODE_ENV},log:(r,...e)=>{process.env.NODE_ENV},info:(r,...e)=>{},warn:(r,...e)=>{},error:(r,...e)=>{}};function O(r){return`${r?`${r}|`:""}${Math.random().toString(36).substring(2,9)+Date.now().toString(36)}`}function I(r){let e={};return r.forEach((t,a)=>{e[a.toLowerCase()]=t}),e}function T(r={},e={}){return{...r,...e,getFromStorage:r.getFromStorage||(t=>{try{let a=localStorage.getItem(t);return a?JSON.parse(a):void 0}catch{return}}),getCookie:r.getCookie||(t=>{try{let a=document.cookie.match(new RegExp(`(?:^|; )${t.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g,"\\$1")}=([^;]*)`));return a?decodeURIComponent(a[1]):void 0}catch{return}})}}async function D(r,e){let t=new Headers,a=e||T({},{});if(r)try{t=await Promise.resolve(r(t,a))}catch{}return t}function K(r,e){return async(t,a)=>{let n=new Headers(t);if(r)try{n=await Promise.resolve(r(n,a))}catch{}if(e)try{n=await Promise.resolve(e(n,a))}catch{}return n}}var q=(s=>(s.Json="json",s.Blob="blob",s.ArrayBuffer="arrayBuffer",s.Text="text",s.FormData="formData",s.Raw="raw",s))(q||{});function Q(r){let e=r.toLowerCase().split(";")[0].trim();if(e.includes("application/json"))return"json";if(e.includes("text/"))return"text";if(e.includes("multipart/form-data"))return"formData";if(e.includes("application/octet-stream")||e.includes("application/pdf")||e.includes("image/")||e.includes("audio/")||e.includes("video/"))return"blob"}function H(r){let e=r.get("content-type")||"",t=r.get("content-disposition")||"",a=e.includes("application/octet-stream")||e.includes("application/pdf")||e.includes("image/")||e.includes("audio/")||e.includes("video/"),n=t.includes("attachment")||t.includes("filename=");return a||n}function L(r){let e=r.get("content-disposition");if(!e)return;let t=e.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);if(t&&t[1])return t[1].replace(/['"]/g,"").trim()}function B(r){let e=r.get("content-type")||"",t=r.get("content-disposition")||"",a=r.get("content-length");return H(r)?{filename:L(r),contentType:e,contentDisposition:t,size:a?parseInt(a,10):void 0}:void 0}async function J(r,e){let t=e,a=r.headers.get("content-type")||"";!t&&a&&(H(r.headers)?t="blob":t=Q(a)),t||(t="json");try{let n;switch((t==="blob"||t==="arrayBuffer")&&(n=B(r.headers)),t){case"json":try{let s=await r.json();return r.ok?{data:s,fileMetadata:n}:{error:s,fileMetadata:n}}catch{let d=await r.text();return r.ok?{data:d,fileMetadata:n}:{error:d,fileMetadata:n}}case"text":{let s=await r.text();return r.ok?{data:s,fileMetadata:n}:{error:s,fileMetadata:n}}case"blob":{let s=await r.blob();return r.ok?{data:s,fileMetadata:n}:{error:s,fileMetadata:n}}case"arrayBuffer":{let s=await r.arrayBuffer();return r.ok?{data:s,fileMetadata:n}:{error:s,fileMetadata:n}}case"formData":{let s=await r.formData();return r.ok?{data:s,fileMetadata:n}:{error:s,fileMetadata:n}}case"raw":return r.ok?{data:r,fileMetadata:n}:{error:r,fileMetadata:n};default:let i=await r.blob();return r.ok?{data:i,fileMetadata:n}:{error:i,fileMetadata:n}}}catch(n){return r.ok?{data:void 0}:{error:n}}}function M(r){let{baseUrl:e,timeout:t=3e4,fetchFn:a=fetch,credentials:n="same-origin"}=r;return async(i,s={},d)=>{let{path:h,method:C,body:o,query:u,responseFormat:f}=i,{signal:b,timeout:R=t,responseFormat:l}=s,A=l||f,m=new URL(h.startsWith("http")?h:`${e}${h}`);u&&Object.entries(u).forEach(([p,c])=>{c!=null&&(Array.isArray(c)?c.forEach(w=>m.searchParams.append(p,String(w))):m.searchParams.append(p,String(c)))});let E;if(o!==void 0)if(o instanceof FormData||o instanceof Blob)E=o;else if(typeof o=="object"&&o!==null)try{E=JSON.stringify(o),d.has("Content-Type")||d.set("Content-Type","application/json")}catch{E=String(o)}else E=String(o);let P,g=new Promise((p,c)=>{R&&(P=window.setTimeout(()=>{c(new Error(`\u041F\u0440\u0435\u0432\u044B\u0448\u0435\u043D\u043E \u0432\u0440\u0435\u043C\u044F \u043E\u0436\u0438\u0434\u0430\u043D\u0438\u044F \u0437\u0430\u043F\u0440\u043E\u0441\u0430 (${R}\u043C\u0441)`))},R))});try{let p=a(m.toString(),{method:C,headers:d,body:E,signal:b,credentials:n}),c=await Promise.race([p,g]),{data:w,error:F,fileMetadata:j}=await J(c,A);return{data:w,error:F,ok:c.ok,status:c.status,statusText:c.statusText,headers:c.headers,fileDownloadResult:j}}catch(p){let c=p;return{error:c,ok:!1,status:0,statusText:c.message,headers:new Headers}}finally{P&&window.clearTimeout(P)}}}function $(r,e=[]){let t={};return!r||e.length===0||e.forEach(a=>{r.has(a)&&(t[a]=r.get(a)||"")}),t}var v=class{constructor(e,t,a,n,i,s){this.name=e;this.queryStorage=t;this.configCurrentEndpoint=a;this.cacheableHeaderKeys=n;this.globalCacheConfig=i;this.baseQueryConfig=s;this.prepareHeaders=K(s.prepareHeaders,a.prepareHeaders),this.queryFunction=M({baseUrl:s.baseUrl,fetchFn:s.fetchFn,timeout:s.timeout,credentials:s.credentials}),this.cacheableHeaders=[...n||[],...a.includeCacheableHeaderKeys||[]].filter(d=>!a.excludeCacheableHeaderKeys?.includes(d)),this.meta.name=e,this.meta.tags=a.tags??this.meta.tags,this.meta.invalidatesTags=a.invalidatesTags??this.meta.invalidatesTags,this.meta.cache=this.queryStorage.createCacheConfig(this.configCurrentEndpoint)??this.meta.cache}endpointSubscribers=new Set;fetchCounts=0;meta={cache:!1,invalidatesTags:[],name:"",tags:[]};queryFunction;cacheableHeaders;prepareHeaders;request(e,t){this.fetchCounts++;let a=O(this.name),n=new AbortController,i=new Set,s={status:"idle",requestParams:e,headers:{},error:void 0,data:void 0,fromCache:!1},d=T({requestParams:e},t?.context||{}),h=o=>{Object.assign(s,o),i.forEach(u=>{u({...s})})},C=new Promise(async(o,u)=>{try{let f=await D(this.prepareHeaders,d),b=$(f,t?.cacheableHeaderKeys?t.cacheableHeaderKeys:this.cacheableHeaders),R=this.queryStorage.shouldCache(this.configCurrentEndpoint,t),[l,A]=this.queryStorage.createCacheKey(this.name,{...e,...b}),m;if(R&&(m=await this.queryStorage.getCachedResult(l)),m)h({fromCache:!0,status:"success",data:m.data,error:void 0,headers:m.headers,requestParams:e}),o({...m,fromCache:!0});else{h({fromCache:!1,status:"loading"});let E=this.configCurrentEndpoint.request(e,t?.context),P={...t,signal:n.signal},g=await this.queryFunction(E,P,f);if(g.ok){let{headers:p,...c}=g;if(R){let w=this.queryStorage.createCacheConfig(this.configCurrentEndpoint);await this.queryStorage.setCachedResult(l,{...c,headers:I(p)},w,A??{},this.configCurrentEndpoint.tags??[],this.configCurrentEndpoint.invalidatesTags??[])}h({fromCache:!1,status:"success",data:g.data,error:void 0,headers:g.headers,requestParams:e}),this.endpointSubscribers.forEach(w=>{let F={status:"success",fetchCounts:this.fetchCounts,meta:this.meta,cacheableHeaders:this.cacheableHeaders,error:void 0};w(F)}),o({...g,fromCache:!1})}else h({fromCache:!1,status:"error",data:void 0,error:g.error,headers:g.headers,requestParams:e}),this.endpointSubscribers.forEach(p=>{let c={status:"error",fetchCounts:this.fetchCounts,meta:this.meta,cacheableHeaders:this.cacheableHeaders,error:g.error};p(c)}),u(g.error)}}catch(f){h({fromCache:!1,status:"error",data:void 0,error:f,headers:void 0,requestParams:e}),u(f)}});return{id:a,subscribe(o,u={}){let{autoUnsubscribe:f=!0}=u;i.add(o),o(s);let b=()=>i.delete(o);return f&&C.finally(()=>{b()}),b},wait:()=>C,waitWithCallbacks(o={}){let{idle:u,loading:f,success:b,error:R}=o;return this.subscribe(l=>{switch(l.status){case"idle":u?.(l);break;case"loading":f?.(l);break;case"success":b?.(l.data,l);break;case"error":R?.(l.error,l);break}},{autoUnsubscribe:!0}),C},abort:()=>{n&&!n.signal.aborted&&n.abort()},then:(o,u)=>C.then(o,u),catch:o=>C.catch(o),finally:o=>C.finally(o)}}subscribe(e){this.endpointSubscribers.add(e);let t={status:"idle",fetchCounts:this.fetchCounts,meta:this.meta,cacheableHeaders:this.cacheableHeaders,error:void 0};return e(t),()=>this.endpointSubscribers.delete(e)}reset(){return this.fetchCounts=0,Promise.resolve()}destroy(){this.endpointSubscribers.clear()}};var x=class{constructor(e,t=!1){this.value=e;this.isRawKey=t}toString(){return this.value}toJSON(){return this.value}valueOf(){return this.value}isUnparseable(){return this.isRawKey}};var y=class{static createMetadata(e=0,t=[]){let a=Date.now(),n=e>0?a+e:1/0;return{createdAt:a,updatedAt:a,expiresAt:n,tags:t,createdAtDateTime:this.formatDateTime(a),updatedAtDateTime:this.formatDateTime(a),expiresAtDateTime:n===1/0?"never":this.formatDateTime(n)}}static formatDateTime(e){return new Date(e).toISOString()}static isExpired(e){return Date.now()>e.expiresAt}static updateMetadata(e){return{...e,updatedAt:Date.now()}}static createKey(...e){return new x(e.join("_"))}static createApiKey(e,t){if(!t)return[new x(e,!0),t];let a=Object.entries(t).sort(([n],[i])=>n.localeCompare(i)).map(([n,i])=>`${n}=${i}`).join("&");return[new x(`${e}_${a}`,!0),t]}static hasAnyTag(e,t=[]){return!e.tags||!t.length?!1:t.some(a=>e.tags?.includes(a))}};var S=class{constructor(e,t){this.storageExternal=e;this.globalCacheConfig=t}storage=null;cleanupInterval=null;defaultCacheOptions={ttl:5*60*1e3,cleanup:{enabled:!0,interval:10*60*1e3},invalidateOnError:!0};async initialize(){return await this.createStorage(),this.startCleanupInterval(),this}async createStorage(){try{let e=this.storageExternal;await e.initialize(),this.storage=e}catch(e){throw e}}startCleanupInterval(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=null);let e=typeof this.globalCacheConfig=="object"?this.globalCacheConfig.cleanup:this.defaultCacheOptions.cleanup;e?.enabled&&e.interval&&(this.cleanupInterval=setInterval(()=>{this.cleanup().catch(t=>{})},e.interval))}getStorage(){return this.storage}createCacheKey(e,t){return y.createApiKey(e,t)}async getCachedResult(e){if(!this.storage)throw new Error("\u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u043D\u0435 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043E");let t=await this.storage.get(e);if(!t)return;if(y.isExpired(t.metadata)){await this.storage.delete(e);return}let a={...t,metadata:y.updateMetadata(t.metadata)};return await this.storage.set(e,a),t.data}async setCachedResult(e,t,a,n,i,s){if(!this.storage)throw new Error("\u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u043D\u0435 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043E");s?.length&&await this.invalidateCacheByTags(s);let d=y.createMetadata(a.ttl,i),h={data:t,metadata:d,params:n};await this.storage.set(e,h)}shouldCache(e,t){return!(this.globalCacheConfig===!1||e?.cache===!1||typeof e?.cache=="object"&&e?.cache.ttl===0||t?.disableCache===!0||this.globalCacheConfig===void 0&&e?.cache===void 0)}createCacheConfig(e){let t=this.defaultCacheOptions;if(typeof this.globalCacheConfig=="object"&&(t=this.globalCacheConfig),typeof e?.cache=="object"){let a=e.cache;t={...t,...a}}return t}async invalidateCacheByTags(e){if(!this.storage)throw new Error("\u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u043D\u0435 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043E");let t=await this.storage.keys();for(let a of t){let n=await this.storage.get(a);n&&y.hasAnyTag(n.metadata,e)&&await this.storage.delete(a)}}async invalidateCache(e){if(!this.storage)throw new Error("\u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u043D\u0435 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043E");await this.storage.delete(e)}async cleanup(){if(!this.storage)throw new Error("\u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u043D\u0435 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043E");let e=await this.storage.keys();for(let t of e){let a=await this.storage.get(t);a&&y.isExpired(a.metadata)&&await this.storage.delete(t)}}async destroy(){this.cleanupInterval&&(window.clearInterval(this.cleanupInterval),this.cleanupInterval=null),this.storage&&(await this.storage.destroy(),this.storage=null)}};var U=class{queryStorage;cacheableHeaderKeys;globalCacheConfig;baseQueryConfig;storageExternal;createEndpoints;endpoints={};constructor(e){this.cacheableHeaderKeys=e.cacheableHeaderKeys,this.globalCacheConfig=e.cache,this.baseQueryConfig=e.baseQuery,this.storageExternal=e.storage,this.createEndpoints=e.endpoints}async init(){return this.queryStorage=await new S(this.storageExternal,this.globalCacheConfig).initialize(),await this.initializeEndpoints(),this}async initializeEndpoints(){let e=a=>a,t=await this.createEndpoints(e)||{};for(let[a,n]of Object.entries(t)){let i=a;this.endpoints[i]=new v(a,this.queryStorage,n,this.cacheableHeaderKeys,this.globalCacheConfig,this.baseQueryConfig)}}getEndpoints(){return this.endpoints}async request(e,t,a){let i=this.getEndpoints()[e];if(!i)throw new Error(`\u042D\u043D\u0434\u043F\u043E\u0438\u043D\u0442 ${String(e)} \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D`);try{return await i.request(t,a).wait()}catch(s){throw k.error(`\u041E\u0448\u0438\u0431\u043A\u0430 \u0437\u0430\u043F\u0440\u043E\u0441\u0430 \u043A ${String(e)}`,{error:s,params:t}),s}}async destroy(){await Promise.all(Object.values(this.endpoints).map(async e=>(e.destroy(),Promise.resolve()))),this.endpoints={},await this.queryStorage.destroy()}};export{U as ApiClient,q as ResponseFormat,k as apiLogger,O as createUniqueId,I as headersToObject};
package/dist/core.d.ts CHANGED
@@ -1,267 +1,6 @@
1
1
  import { I as ISelectorModule, a as Selector, b as SelectorOptions, S as SelectorAPI } from './selector.interface-CA5y-kD_.js';
2
- import { c as StorageKeyType, I as IStorage, h as StorageConfig, f as IEventEmitter, g as ILogger, D as DefaultMiddlewares, e as StorageEvent, i as StorageType, M as Middleware, C as ConfigureMiddlewares, l as StorageKey } from './storage.interface-Dl8SLUd1.js';
3
- export { B as BatchingMiddlewareOptions, G as GetDefaultMiddleware, k as IndexedDBStorageConfig, L as LocalStorageConfig, j as MemoryStorageConfig, a as MiddlewareAPI, N as NextFunction, S as ShallowCompareMiddlewareOptions, b as StorageAction, d as StorageEvents } from './storage.interface-Dl8SLUd1.js';
4
-
5
- /**
6
- * Контекст выполнения для плагинов
7
- * Содержит информацию о текущей операции и хранилище
8
- */
9
- interface PluginContext {
10
- /** Имя хранилища, к которому применяется плагин */
11
- storageName: string;
12
- /** Временная метка выполнения операции (timestamp) */
13
- timestamp: number;
14
- /** Дополнительные метаданные операции (могут быть предоставлены хранилищем или другими плагинами) */
15
- metadata?: Record<string, any>;
16
- }
17
- /**
18
- * Базовый интерфейс для всех плагинов
19
- * Определяет основные свойства и методы жизненного цикла
20
- */
21
- interface IPlugin {
22
- /** Уникальное имя плагина */
23
- name: string;
24
- /**
25
- * Метод инициализации плагина
26
- * Вызывается при добавлении плагина в хранилище или при инициализации хранилища
27
- */
28
- initialize?(): Promise<void>;
29
- /**
30
- * Метод уничтожения плагина
31
- * Вызывается при удалении плагина из хранилища или при уничтожении хранилища
32
- * Используется для освобождения ресурсов и очистки состояния
33
- */
34
- destroy?(): Promise<void>;
35
- }
36
- /**
37
- * Интерфейс плагина для хранилища данных
38
- * Определяет хуки для различных операций хранилища
39
- */
40
- interface IStoragePlugin extends IPlugin {
41
- /**
42
- * Вызывается перед установкой значения в хранилище
43
- * Позволяет изменить значение до его сохранения
44
- *
45
- * @param value Значение, которое будет сохранено
46
- * @param context Контекст выполнения операции
47
- * @returns Модифицированное значение для сохранения
48
- */
49
- onBeforeSet?<T>(value: T, context: PluginContext): Promise<T>;
50
- /**
51
- * Вызывается после установки значения в хранилище
52
- * Позволяет выполнить дополнительные действия или модифицировать результат
53
- *
54
- * @param key Ключ, по которому было сохранено значение
55
- * @param value Сохраненное значение
56
- * @param context Контекст выполнения операции
57
- * @returns Финальное значение (может быть модифицировано)
58
- */
59
- onAfterSet?<T>(key: StorageKeyType, value: T, context: PluginContext): Promise<T>;
60
- /**
61
- * Вызывается перед получением значения из хранилища
62
- * Позволяет модифицировать запрашиваемый ключ
63
- *
64
- * @param key Ключ, по которому запрашивается значение
65
- * @param context Контекст выполнения операции
66
- * @returns Возможно модифицированный ключ для запроса
67
- */
68
- onBeforeGet?(key: StorageKeyType, context: PluginContext): Promise<StorageKeyType>;
69
- /**
70
- * Вызывается после получения значения из хранилища
71
- * Позволяет модифицировать полученное значение
72
- *
73
- * @param key Ключ, по которому было запрошено значение
74
- * @param value Полученное значение (undefined, если значение не найдено)
75
- * @param context Контекст выполнения операции
76
- * @returns Финальное значение (может быть модифицировано)
77
- */
78
- onAfterGet?<T>(key: StorageKeyType, value: T | undefined, context: PluginContext): Promise<T | undefined>;
79
- /**
80
- * Вызывается перед удалением значения из хранилища
81
- * Позволяет разрешить или запретить удаление
82
- *
83
- * @param key Ключ, по которому будет удалено значение
84
- * @param context Контекст выполнения операции
85
- * @returns Булево значение, разрешающее (true) или запрещающее (false) удаление
86
- */
87
- onBeforeDelete?(key: StorageKeyType, context: PluginContext): Promise<boolean>;
88
- /**
89
- * Вызывается после удаления значения из хранилища
90
- * Позволяет выполнить дополнительные действия после удаления
91
- *
92
- * @param key Ключ, по которому было удалено значение
93
- * @param context Контекст выполнения операции
94
- */
95
- onAfterDelete?(key: StorageKeyType, context: PluginContext): Promise<void>;
96
- /**
97
- * Вызывается перед очисткой хранилища
98
- * Позволяет выполнить дополнительные действия перед удалением всех данных
99
- *
100
- * @param context Контекст выполнения операции
101
- */
102
- onClear?(context: PluginContext): Promise<void>;
103
- }
104
- /**
105
- * Исполнитель плагинов
106
- * Отвечает за выполнение хуков плагинов в определенной последовательности
107
- */
108
- interface IPluginExecutor {
109
- /**
110
- * Выполняет хуки onBeforeSet всех зарегистрированных плагинов
111
- *
112
- * @param value Исходное значение
113
- * @param metadata Дополнительные метаданные
114
- * @returns Модифицированное значение после прохождения всех плагинов
115
- */
116
- executeBeforeSet<T>(value: T, metadata?: Record<string, any>): Promise<T>;
117
- /**
118
- * Выполняет хуки onAfterSet всех зарегистрированных плагинов
119
- *
120
- * @param key Ключ, по которому было сохранено значение
121
- * @param value Сохраненное значение
122
- * @param metadata Дополнительные метаданные
123
- * @returns Финальное значение после прохождения всех плагинов
124
- */
125
- executeAfterSet<T>(key: StorageKeyType, value: T, metadata?: Record<string, any>): Promise<T>;
126
- /**
127
- * Выполняет хуки onBeforeGet всех зарегистрированных плагинов
128
- *
129
- * @param key Исходный ключ
130
- * @param metadata Дополнительные метаданные
131
- * @returns Модифицированный ключ после прохождения всех плагинов
132
- */
133
- executeBeforeGet(key: StorageKeyType, metadata?: Record<string, any>): Promise<StorageKeyType>;
134
- /**
135
- * Выполняет хуки onAfterGet всех зарегистрированных плагинов
136
- *
137
- * @param key Ключ, по которому было запрошено значение
138
- * @param value Полученное значение
139
- * @param metadata Дополнительные метаданные
140
- * @returns Финальное значение после прохождения всех плагинов
141
- */
142
- executeAfterGet<T>(key: StorageKeyType, value: T | undefined, metadata?: Record<string, any>): Promise<T | undefined>;
143
- /**
144
- * Выполняет хуки onBeforeDelete всех зарегистрированных плагинов
145
- *
146
- * @param key Ключ, по которому будет удалено значение
147
- * @param metadata Дополнительные метаданные
148
- * @returns Результат проверки всех плагинов (false если хотя бы один плагин запретил удаление)
149
- */
150
- executeBeforeDelete(key: StorageKeyType, metadata?: Record<string, any>): Promise<boolean>;
151
- /**
152
- * Выполняет хуки onAfterDelete всех зарегистрированных плагинов
153
- *
154
- * @param key Ключ, по которому было удалено значение
155
- * @param metadata Дополнительные метаданные
156
- */
157
- executeAfterDelete(key: StorageKeyType, metadata?: Record<string, any>): Promise<void>;
158
- /**
159
- * Выполняет хуки onClear всех зарегистрированных плагинов
160
- *
161
- * @param metadata Дополнительные метаданные
162
- */
163
- executeOnClear(metadata?: Record<string, any>): Promise<void>;
164
- }
165
- /**
166
- * Менеджер плагинов
167
- * Отвечает за регистрацию, получение и удаление плагинов
168
- */
169
- interface IPluginManager<T extends IPlugin> {
170
- /**
171
- * Добавляет плагин в менеджер
172
- *
173
- * @param plugin Экземпляр плагина
174
- */
175
- add(plugin: T): Promise<void>;
176
- /**
177
- * Удаляет плагин из менеджера по имени
178
- *
179
- * @param name Имя плагина
180
- */
181
- remove(name: string): Promise<void>;
182
- /**
183
- * Получает плагин по имени
184
- *
185
- * @param name Имя плагина
186
- * @returns Экземпляр плагина или undefined, если плагин не найден
187
- */
188
- get(name: string): T | undefined;
189
- /**
190
- * Получает все зарегистрированные плагины
191
- *
192
- * @returns Массив всех плагинов
193
- */
194
- getAll(): T[];
195
- /**
196
- * Инициализирует все зарегистрированные плагины
197
- */
198
- initialize(): Promise<void>;
199
- /**
200
- * Уничтожает все зарегистрированные плагины
201
- */
202
- destroy(): Promise<void>;
203
- }
204
-
205
- type PathSelector<T, R> = (state: T) => R;
206
- declare abstract class BaseStorage<T extends Record<string, any>> implements IStorage<T> {
207
- protected readonly config: StorageConfig;
208
- protected readonly pluginExecutor?: IPluginExecutor | undefined;
209
- protected readonly eventEmitter?: IEventEmitter | undefined;
210
- protected readonly logger?: ILogger | undefined;
211
- protected static readonly GLOBAL_SUBSCRIPTION_KEY = "*";
212
- name: string;
213
- private selectorPathCache;
214
- private middlewareModule;
215
- private initializedMiddlewares;
216
- protected subscribers: Map<StorageKeyType, Set<(value: any) => void>>;
217
- constructor(config: StorageConfig, pluginExecutor?: IPluginExecutor | undefined, eventEmitter?: IEventEmitter | undefined, logger?: ILogger | undefined);
218
- protected initializeMiddlewares(): void;
219
- protected getDefaultMiddleware(): DefaultMiddlewares;
220
- protected initializeWithMiddlewares(): Promise<void>;
221
- abstract initialize(): Promise<this>;
222
- protected abstract doGet(key: StorageKeyType): Promise<any>;
223
- protected abstract doSet(key: StorageKeyType, value: any): Promise<void>;
224
- protected abstract doUpdate(updates: Array<{
225
- key: StorageKeyType;
226
- value: any;
227
- }>): Promise<void>;
228
- protected abstract doDelete(key: StorageKeyType): Promise<boolean>;
229
- protected abstract doClear(): Promise<void>;
230
- protected abstract doKeys(): Promise<string[]>;
231
- protected abstract doHas(key: StorageKeyType): Promise<boolean>;
232
- protected abstract doDestroy(): Promise<void>;
233
- get<R>(key: StorageKeyType): Promise<R | undefined>;
234
- set<R>(key: StorageKeyType, value: R): Promise<void>;
235
- update(updater: (state: T) => void): Promise<void>;
236
- delete(key: StorageKeyType): Promise<void>;
237
- clear(): Promise<void>;
238
- keys(): Promise<string[]>;
239
- has(key: StorageKeyType): Promise<boolean>;
240
- getState(): Promise<T>;
241
- subscribeToAll(callback: (event: {
242
- type: string;
243
- key?: StorageKeyType[] | StorageKeyType;
244
- value?: any;
245
- changedPaths?: string[];
246
- }) => void): VoidFunction;
247
- subscribe(key: string, callback: (value: any) => void): VoidFunction;
248
- subscribe<R>(pathSelector: PathSelector<T, R>, callback: (value: R) => void): VoidFunction;
249
- destroy(): Promise<void>;
250
- private subscribeByKey;
251
- private createDummyState;
252
- private isEqual;
253
- /**
254
- * Возвращает полный путь, а не только корневой ключ
255
- */
256
- private extractPath;
257
- protected notifySubscribers(key: StorageKeyType, value: any): void;
258
- /**
259
- * Метод для определения изменившихся путей между двумя объектами
260
- */
261
- private findChangedPaths;
262
- private subscribeBySelector;
263
- protected emitEvent(event: StorageEvent): Promise<void>;
264
- }
2
+ import { p as StorageType, M as Middleware, g as IPluginManager, e as IStoragePlugin, f as IPluginExecutor, n as ILogger, c as StorageKeyType, s as BaseStorage, o as StorageConfig, m as IEventEmitter, j as IStorage } from './storage.interface-2HKvqdAJ.js';
3
+ export { B as BatchingMiddlewareOptions, C as ConfigureMiddlewares, D as DefaultMiddlewares, G as GetDefaultMiddleware, d as IPlugin, I as IndexedDBStorage, r as IndexedDBStorageConfig, L as LocalStorageConfig, q as MemoryStorageConfig, a as MiddlewareAPI, N as NextFunction, P as PluginContext, S as ShallowCompareMiddlewareOptions, b as StorageAction, l as StorageEvent, k as StorageEvents, i as StorageInitStatus, h as StorageStatus } from './storage.interface-2HKvqdAJ.js';
265
4
 
266
5
  interface SharedStateMiddlewareProps {
267
6
  storageType: StorageType;
@@ -291,50 +30,9 @@ declare class StoragePluginModule implements IPluginManager<IStoragePlugin>, IPl
291
30
  executeOnClear(metadata?: Record<string, any>): Promise<void>;
292
31
  }
293
32
 
294
- interface IndexedDBConfig {
295
- dbName?: string;
296
- dbVersion: number;
297
- }
298
- declare class IndexedDBStorage<T extends Record<string, any>> extends BaseStorage<T> {
299
- private readonly DB_NAME;
300
- private readonly STORE_NAME;
301
- private readonly DB_VERSION;
302
- private dbManager;
303
- constructor(config: StorageConfig & {
304
- options: IndexedDBConfig;
305
- }, pluginExecutor?: IPluginExecutor, eventEmitter?: IEventEmitter, logger?: ILogger);
306
- initialize(): Promise<this>;
307
- static getCurrentDBVersion(dbName: string): Promise<number>;
308
- static createStorages<S extends Record<string, any>>(dbName: string, configs: {
309
- [K in keyof S]: {
310
- name: string;
311
- initialState?: S[K];
312
- middlewares?: ConfigureMiddlewares;
313
- pluginExecutor?: IPluginExecutor;
314
- eventEmitter?: IEventEmitter;
315
- };
316
- }, logger?: ILogger): Promise<{
317
- [K in keyof S]: IndexedDBStorage<S[K]>;
318
- }>;
319
- private getTransaction;
320
- private getObjectStore;
321
- protected doGet(key: StorageKeyType): Promise<any>;
322
- protected doSet(key: StorageKeyType, value: any): Promise<void>;
323
- private putValueInStore;
324
- protected doUpdate(updates: Array<{
325
- key: string | StorageKey;
326
- value: any;
327
- }>): Promise<void>;
328
- protected doDelete(key: StorageKeyType): Promise<boolean>;
329
- protected doClear(): Promise<void>;
330
- protected doKeys(): Promise<string[]>;
331
- protected doHas(key: StorageKeyType): Promise<boolean>;
332
- protected doDestroy(): Promise<void>;
333
- }
334
-
335
33
  declare class LocalStorage<T extends Record<string, any>> extends BaseStorage<T> {
336
34
  constructor(config: StorageConfig, pluginExecutor?: IPluginExecutor, eventEmitter?: IEventEmitter, logger?: ILogger);
337
- initialize(): Promise<this>;
35
+ protected doInitialize(): Promise<this>;
338
36
  protected doGet(key: StorageKeyType): Promise<any>;
339
37
  protected doSet(key: StorageKeyType, value: any): Promise<void>;
340
38
  protected doDelete(key: StorageKeyType): Promise<boolean>;
@@ -352,7 +50,7 @@ declare class LocalStorage<T extends Record<string, any>> extends BaseStorage<T>
352
50
  declare class MemoryStorage<T extends Record<string, any>> extends BaseStorage<T> {
353
51
  private storage;
354
52
  constructor(config: StorageConfig, pluginExecutor?: IPluginExecutor, eventEmitter?: IEventEmitter, logger?: ILogger);
355
- initialize(): Promise<this>;
53
+ protected doInitialize(): Promise<this>;
356
54
  protected doGet(key: StorageKeyType): Promise<any>;
357
55
  protected doSet(key: StorageKeyType, value: any): Promise<void>;
358
56
  protected doDelete(key: StorageKeyType): Promise<boolean>;
@@ -394,4 +92,4 @@ declare class SelectorModule<S extends Record<string, any>> implements ISelector
394
92
  destroy(): void;
395
93
  }
396
94
 
397
- export { ConfigureMiddlewares, DefaultMiddlewares, IEventEmitter, ILogger, type IPlugin, type IPluginExecutor, type IPluginManager, ISelectorModule, IStorage, type IStoragePlugin, IndexedDBStorage, LocalStorage, MemoryStorage, Middleware, type PluginContext, SelectorAPI, SelectorModule, StorageConfig, StorageEvent, StorageKeyType, StoragePluginModule, StorageType, broadcastMiddleware };
95
+ export { IEventEmitter, ILogger, IPluginExecutor, IPluginManager, ISelectorModule, IStorage, IStoragePlugin, LocalStorage, MemoryStorage, Middleware, SelectorAPI, SelectorModule, StorageConfig, StorageKeyType, StoragePluginModule, StorageType, broadcastMiddleware };