@net-vert/core
Version:
Dependency Inversion Network Library with Type-Safe Injection.
2 lines (1 loc) • 10.8 kB
JavaScript
(function(c,w){typeof exports=="object"&&typeof module<"u"?w(exports,require("id-queue")):typeof define=="function"&&define.amd?define(["exports","id-queue"],w):(c=typeof globalThis<"u"?globalThis:c||self,w(c.netVertCore={},c.idQueue))})(this,function(c,w){"use strict";var p=(r=>(r.GET="get",r.POST="post",r.PUT="put",r.DELETE="delete",r))(p||{}),f=(r=>(r.CACHE="cache",r.RETRY="retry",r.IDEMPOTENT="idempotent",r.CONCURRENT="concurrent",r.THROTTLE="throttle",r))(f||{});const v="default",b=new Map,B=(r,e=v)=>{b.set(e,r)},T=(r=v)=>{const e=b.get(r);if(!e)throw new Error(`Requestor实例 ${String(r)} 未注册`);return e},P={get:(r,e)=>({url:r,method:p.GET,...e,params:e?.params}),post:(r,e,t)=>({url:r,method:p.POST,data:e,...t}),delete:(r,e)=>({url:r,method:p.DELETE,...e}),put:(r,e,t)=>({url:r,method:p.PUT,data:e,...t}),request:r=>r},_=Object.keys(P);function K(r,e,t){const n={},o=s=>{if(s===e.length)return t(r);const a=e[s];return a({config:r,ctx:n,next:()=>o(s+1)})};return o(0)}function A(r,e){const t={},n=e??[];return _.forEach(o=>{t[o]=(...s)=>{const a=P[o](...s);return K(a,n,r)}}),t}function S(r){const{extensions:e,instanceKey:t}=r??{},n=T(t);return A(n,e)}const J={retries:3,delay:0,retryCondition:()=>!0},N=r=>{const e={...J,...r};return Object.assign(async({config:n,next:o})=>{let s=0,a;for(;s<=e.retries;)try{return await o()}catch(i){if(a=i,s===e.retries)throw i;const u={config:n,lastResponse:i,attempt:s};if(!e.retryCondition(u))throw i;s++;const h=typeof e.delay=="function"?e.delay(u):e.delay;h>0&&await new Promise(k=>setTimeout(k,h))}throw a},{__middlewareType:f.RETRY})},z=()=>{const r=new Map;return{getPromise:s=>r.get(s),setPromise:(s,a)=>{r.set(s,a),a.finally(()=>r.delete(s))},delPromise:s=>r.delete(s),clearCache:()=>r.clear()}},G={key:r=>{const{config:e}=r,{method:t,url:n,data:o}=e;return[t,n,JSON.stringify(o)].join("|")}},q=r=>{const e={...G,...r},t=z();return Object.assign(({config:o,next:s})=>{const a=e.key({config:o}),i=t.getPromise(a);if(i)return i;const u=s();return t.setPromise(a,u),u},{__middlewareType:f.IDEMPOTENT,promiseCache:t})};class H{parallelCount;tasks;runningCount;constructor(e=4){this.parallelCount=e,this.tasks=new w.TaskQueue,this.runningCount=0}add(e,t){return new Promise((n,o)=>{this.tasks.enqueue(e,{task:t,resolve:n,reject:o}),this._run()})}remove(e){this.tasks.remove(e)}execute(e){const{task:t,resolve:n,reject:o}=e;return t().then(n).catch(o).finally(()=>{this.runningCount--,this._run()})}_run(){for(;this.runningCount<this.parallelCount&&this.tasks.size>0;){const e=this.tasks.dequeue();this.runningCount++,this.execute(e)}}}let L=0;const U={parallelCount:4,createId:()=>L++},O=r=>{const{parallelCount:e,createId:t}={...U,...r},n=new H(e);return Object.assign(({config:s,next:a})=>{const i=t({config:s});return n.add(i,()=>a())},{__middlewareType:f.CONCURRENT,pool:n})},j=new Map,C=(r,e)=>{j.set(e,r)};function M(r){const e=j.get(r);if(!e)throw new Error(`Store实例 ${String(r)} 未注册`);return e}class Q{store=new Map;getItem(e){return this.store.get(e)}setItem(e,t){return this.store.set(e,t),t}removeItem(e){this.store.delete(e)}clear(){this.store.clear()}length(){return this.store.size}key(e){return Array.from(this.store.keys())[e]}keys(){return Array.from(this.store.keys())}iterate(e){let t=0;for(const[n,o]of this.store.entries())e(o,n,t),t++}}const X=r=>!!r&&(typeof r=="object"||typeof r=="function")&&typeof r.then=="function",x=r=>typeof window<"u"?r():{getItem(){return null},setItem(){},removeItem(){},clear(){},key(){return null},get length(){return 0}},y=x(()=>window.localStorage);class Z{constructor(){}getItem(e){const t=String(e),n=y.getItem(t);if(n!==null)try{return JSON.parse(n)}catch(o){console.error(`Failed to parse value for key: ${t}`,o);return}}setItem(e,t){const n=String(e);try{y.setItem(n,JSON.stringify(t))}catch(o){throw console.error(`Failed to set value for key: ${n}`,o),o}return t}removeItem(e){const t=String(e);y.removeItem(t)}clear(){y.clear()}length(){return y.length}key(e){return y.key(e)}keys(){const e=[];for(let t=0;t<y.length;t++){const n=y.key(t);n&&e.push(n)}return e}iterate(e){this.keys().forEach((t,n)=>{const o=this.getItem(t);o!==void 0&&e(o,t,n)})}}const g=x(()=>window.sessionStorage);class Y{constructor(){}getItem(e){const t=String(e),n=g.getItem(t);if(n!==null)try{return JSON.parse(n)}catch(o){console.error(`Failed to parse value for key: ${t}`,o);return}}setItem(e,t){const n=String(e);try{g.setItem(n,JSON.stringify(t))}catch(o){throw console.error(`Failed to set value for key: ${n}`,o),o}return t}removeItem(e){const t=String(e);g.removeItem(t)}clear(){g.clear()}length(){return g.length}key(e){return g.key(e)}keys(){const e=[];for(let t=0;t<g.length;t++){const n=g.key(t);n&&e.push(n)}return e}iterate(e){this.keys().forEach((t,n)=>{const o=this.getItem(t);o!==void 0&&e(o,t,n)})}}class W{dbName;storeName;dbPromise=null;DB_VERSION=1;constructor(e,t){this.dbName=e,this.storeName=t,this.initDB()}initDB(){if(typeof window>"u"||!window.indexedDB){console.warn("IndexedDB is not available");return}this.dbPromise=new Promise((e,t)=>{const n=indexedDB.open(this.dbName,this.DB_VERSION);n.onerror=()=>{t(new Error(`Failed to open database: ${this.dbName}`))},n.onsuccess=()=>{e(n.result)},n.onupgradeneeded=o=>{const s=o.target.result;s.objectStoreNames.contains(this.storeName)||s.createObjectStore(this.storeName)}})}async getDB(){if(!this.dbPromise)throw new Error("IndexedDB is not initialized");return this.dbPromise}async withStore(e,t){const n=await this.getDB();return new Promise((o,s)=>{const a=n.transaction([this.storeName],e).objectStore(this.storeName),i=t(a);i.onsuccess=()=>{o(i.result)},i.onerror=()=>{s(i.error)}})}async getItem(e){try{const t=await this.withStore("readonly",n=>n.get(String(e)));return t===void 0?void 0:t}catch(t){console.error(`Failed to get value for key: ${String(e)}`,t);return}}async setItem(e,t){try{return await this.withStore("readwrite",n=>n.put(t,String(e))),t}catch(n){throw console.error(`Failed to set value for key: ${String(e)}`,n),n}}async removeItem(e){try{await this.withStore("readwrite",t=>t.delete(String(e)))}catch(t){throw console.error(`Failed to remove value for key: ${String(e)}`,t),t}}async clear(){try{await this.withStore("readwrite",e=>e.clear())}catch(e){throw console.error("Failed to clear storage",e),e}}async length(){try{return await this.withStore("readonly",e=>e.count())}catch(e){return console.error("Failed to get storage length",e),0}}async key(e){try{return(await this.withStore("readonly",t=>t.getAllKeys()))[e]}catch(t){console.error("Failed to get key",t);return}}async keys(){try{return await this.withStore("readonly",e=>e.getAllKeys())}catch(e){return console.error("Failed to get all keys",e),[]}}async iterate(e){try{const t=(await this.getDB()).transaction([this.storeName],"readonly").objectStore(this.storeName).openCursor();return new Promise((n,o)=>{let s=0;t.onsuccess=a=>{const i=a.target.result;if(i){const u=i.key,h=i.value;e(h,u,s),s++,i.continue()}else n()},t.onerror=()=>{o(t.error)}})}catch(t){console.error("Failed to iterate storage",t)}}}const I={memory:"memory",local:"local",session:"session",indexeddb:"indexeddb"};function R(r,e){Object.assign(r,e)}function ee(r){return R(r,{async getItemOrDefault(e,t){const n=await this.getItem(e);return n!==null?n:t},async hasItem(e){return await this.getItem(e)!==null},async removeItems(e){await Promise.all(e.map(t=>this.removeItem(t)))},async getItems(e){return await Promise.all(e.map(t=>this.getItem(t)))}}),r}function te(r){return R(r,{getItemOrDefault(e,t){const n=this.getItem(e);return n!==null?n:t},hasItem(e){return this.getItem(e)!==null},removeItems(e){e.forEach(t=>this.removeItem(t))},getItems(e){return e.map(t=>this.getItem(t))}}),r}function re(r){const e=r.getItem("");return X(e)?ee(r):te(r)}function E(r,...e){const t=M(r);let n;try{n=new t(...e)}catch{n=t(...e)}return re(n)}C(Q,I.memory),C(Z,I.local),C(Y,I.session),C(W,I.indexeddb);function D(r,e){return{value:r,expireAt:Date.now()+e}}function F(r,e=Date.now()){return r.expireAt<=e}function ne(r,e=Date.now()){return F(r,e)?void 0:r.value}const oe=r=>{const{config:e}=r,{method:t,url:n,data:o}=e;return[t,n,JSON.stringify(o)].join("|")},se=()=>!0,$=24*60*60*1e3,ie={key:oe,duration:$,isValid:se,store:I.memory};class ae{store;constructor(e){return typeof e=="string"?this.store=E(e):(C(e.factory,e.key),this.store=E(e.key)),new Proxy(this,{get(t,n){if(n in t)return t[n];const o=t.store[n];return typeof o=="function"?o.bind(t.store):o}})}setCache(e,t,n=$){const o=D(t,n);this.store.setItem(e,o)}async getCache(e){const t=await this.store.getItem(e);if(t)return ne(t)}async hasValidCache(e){const t=await this.store.getItem(e);return t?!F(t):!1}}const ce=ae,V=r=>{const e={...ie,...r},t=new ce(e.store),n=s=>typeof e.duration=="function"?e.duration(s):e.duration;return Object.assign(async({config:s,next:a})=>{const i=e.key({config:s}),u=await t.getCache(i);if(u){if(await e.isValid({key:i,config:s,cachedData:u}))return u;t.removeItem(i)}const h=await a(),k=n({key:i,config:s,cachedData:u,response:h}),l=D(h,k);return t.setItem(i,l),h},{__middlewareType:f.CACHE,storage:t})};class ue extends Error{constructor(e,t){super(`请求在节流队列中等待超时:配置超时 ${e}ms,实际等待 ${t}ms`),this.name="ThrottleTimeoutError"}}function le(r,e){const t=[];let n=0,o=!1;const s=l=>new Promise(d=>setTimeout(d,l)),a=()=>{if(e===void 0||t.length===0)return!1;const l=Date.now(),d=t[0],m=l-d.timestamp;return m>=e?(t.shift(),d.reject(new ue(e,m)),!0):!1},i=async()=>{if(!(o||t.length===0)){for(o=!0;t.length>0;){if(e!==void 0&&a())continue;if(t.length===0)break;const d=Date.now()-n;if(n>0&&d<r){const ge=r-d;await s(ge)}const m=t.shift();m&&(n=Date.now(),m.task().then(m.resolve).catch(m.reject))}o=!1}};return{add:l=>new Promise((d,m)=>{t.push({task:l,resolve:d,reject:m,timestamp:Date.now()}),i()}),getStatus:()=>{const l=t.length>0?n+r:null;return{queueLength:t.length,lastExecutionTime:n,isProcessing:o,nextExecutionTime:l}},clear:()=>{t.length=0}}}const de={interval:1e3},he=r=>{const e={...de,...r},t=le(e.interval,e.timeout);return Object.assign(async({config:o,next:s})=>t.add(s),{__middlewareType:f.THROTTLE,throttler:t})};function me(r){const{instanceKey:e,key:t,duration:n,isValid:o,store:s,...a}=r;return S({instanceKey:e,extensions:[q(a),V({key:t,duration:n,isValid:o,store:s})]})}function ye(r){const{instanceKey:e,parallelCount:t,createId:n,retries:o,delay:s,retryCondition:a}=r;return S({instanceKey:e,extensions:[O({parallelCount:t,createId:n}),N({retries:o,delay:s,retryCondition:a})]})}c.cache=V,c.concurrent=O,c.createCachedIdempotentRequestor=me,c.createConcurrentRetryRequestor=ye,c.createRequestor=S,c.idempotent=q,c.inject=B,c.retry=N,c.throttle=he,c.useRequestor=T,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})});