import{LRUCache as H}from"lru-cache";import{sha1 as M}from"../utils/crypto/sha1.js";import{envConfig as S}from"../config/env-config.js";import{NestedMap as x}from"./utils/nested-map.js";import{trackAccessStore as w}from"./utils/async-storage.js";import{isLoaderCacheEnabled as k}from"./utils/is-loader-cache-enabled.js";import{LoadError as v}from"./load-error.js";import{createLifecycleContext as D}from"../plugins/lifecycle.js";function f(y,t){return y+":"+t}class J{fs;errors=new Map;#t=new Map;#i=new Map;#e=new Map;#s=new Map;#a=new x;#r;#o={};#n=new Map;constructor(t){this.fs=t,this.#r=D(t,this),this.#f()}#c(t){let e=this.#t.get(t);return e||(e=new H({max:S.isBuildMode?1e3:1e6}),this.#t.set(t,e)),e}async load(t,e,i){let s,h;typeof e=="string"?(s=e,h=this.#o[e]):(s=e.name,h=e.loader);const a=f(s,t);if(this.#n.has(a))return this.#n.get(a);const n=i?.join(""),r=n!==void 0?n.length>30?M(n):n:void 0,c=w.getStore()??[],F=!this.#h(t,s,r),p=this.#c(s),g=p.get(t);if(F&&g)return c.push({type:"load",loaderId:s,resource:t,hash:g.compoundHash}),g;const d=Promise.withResolvers();this.#n.set(a,d.promise),r!==void 0&&this.#e.set(a,r);const{status:L,value:l}=await this.#p(t,s,async()=>{let m;const I=w.getStore()||[],u=[],P=o=>u.push(o);try{m=await h(t,this.#r,P),u.length>0?this.errors.set(a,u):this.errors.delete(a)}catch(o){const R=p.get(t)?.data,E=s==="redocly-config"||s==="nearest-redocly-config"?!1:(await this.load(t,"is-ignored")).data;if(!(o instanceof v)&&!E&&this.errors.set(a,[o]),!R)return{status:"error",value:o instanceof v?o:new v(o.message,{cause:o,loaderId:s})};m=R}const C=M(t+(r??"")+I.map(o=>o.hash).join(""));return c.push({type:"load",loaderId:s,resource:t,hash:C}),{status:"success",value:{data:m,compoundHash:C}}});return L==="error"?d.reject(l):(this.#l(t),k(s)&&p.set(t,l),this.#i.set(a,l.compoundHash),d.resolve(l)),this.#n.delete(a),d.promise}setLoaders(t){this.#o={...this.#o,...t}}delete(t,e){if(e){const i=f(e,t);this.#d(t,e),this.errors.delete(i),this.#i.delete(i),this.#e.delete(i);const s=this.#s.get(t);if(s){for(const h of s)this.delete(h,e);this.#s.delete(t)}this.#a.delete(e,t)}else for(const i of this.#t.keys())this.delete(t,i)}#d(t,e){const i=this.#t.get(e);i&&i.delete(t)}#l(t){const[e,i]=t.split("#");if(!i)return;const s=this.#s.get(e);s?s.add(t):this.#s.set(e,new Set([t]))}#f(){this.fs.watch(async t=>{for(const e of t)e.event==="unlink"&&this.delete(e.path)})}#h(t,e,i){const s=f(e,t);return i!==void 0&&this.#e.get(s)!==i?!0:(this.#a.get(e,t)??[]).some(n=>{switch(n.type){case"load":const r=f(n.loaderId,n.resource);return this.#i.get(r)!==n.hash||this.#h(n.resource,n.loaderId,this.#e.get(r));case"read":return n.hash!==this.fs.getFileInfo(n.path)?.hash;case"exists":const c=this.fs.getFileInfo(n.path);return n.hash!==(c&&!c.isVirtual?"t":"f");case"scan":return n.hash!==this.fs.getPatternScanHash(n.pattern)}})}#p(t,e,i){const s=[];return this.#a.set(e,t,s),w.run(s,i)}}export{J as Cache};
