import*as m from"chokidar";import s from"path";import*as f from"node:fs/promises";import{removeTrailingSlash as w,slash as n}from"../../shared/utils.js";import l from"../utils/reporter/logger.js";import{debouncedEmit as u}from"./utils/debounced-emit.js";import{trackAccessStore as h,fsChangesStore as g}from"./utils/async-storage.js";import{sha1 as o}from"../utils/crypto.js";import{removeBom as y}from"./utils/string-utils.js";class x{cwd;ignored;filesList=new Map;watcher;callbacks=[];emitWrapper=t=>t();constructor(t,e=[]){this.cwd=t,this.ignored=e,this.watcher=this.startWatcher()}async getFileInfo(t){return await this.watcher,this.filesList.get(t)}async watch(t){await this.watcher,this.callbacks.push(t)}async dispose(){(await this.watcher).close()}async readdir(t){await this.watcher;const e=[],a=w(n(t))||".";return this.filesList.forEach(i=>{i.dirname===a&&e.push(i)}),h.getStore()?.push({type:"readdir",path:t,hash:o(e.join(`
`))}),e}async exists(t){await this.watcher;const e=this.filesList.has(t);return h.getStore()?.push({type:"exists",path:t,hash:e?"t":"f"}),e}async read(t,e="utf-8"){try{let a=await f.readFile(s.join(this.cwd,t),e);a=y(a);const i=o(a);return h.getStore()?.push({type:"read",path:t,hash:i}),a}catch(a){throw h.getStore()?.push({type:"read",path:t,hash:"error"}),a}}async scan(t){await this.watcher;const e=[];return this.filesList.forEach(a=>{(!t||t.test(a.relativePath))&&e.push(a)}),h.getStore()?.push({type:"scan",path:".",hash:o(e.join(`
`)),pattern:t}),e}setEmitWrapper(t){this.emitWrapper=t}emitCodeUpdated(){this.emit({event:"code-updated"})}addVirtualFile(t,e){this.filesList.set(t,{relativePath:e.relativePath,realRelativePath:e.realRelativePath,dirname:e.dirname,isVirtual:!0}),h.getStore()?.push({type:"load",loaderKey:o(t),cacheKey:o(e.relativePath),hash:o(JSON.stringify(e))})}emit=u(async t=>{for(const e of t)switch(e.event){case"add":this.filesList.set(e.path,{relativePath:e.path,realRelativePath:e.path,dirname:s.posix.dirname(e.path)});break;case"change":break;case"unlink":this.filesList.delete(e.path);break}await this.emitWrapper(()=>g.run(t,async()=>{for(const e of this.callbacks)await e(t)}))});async startWatcher(){return l.startTiming("init-fs"),new Promise((t,e)=>{const a=m.watch(this.cwd,{usePolling:!1,ignoreInitial:!0,ignored:[/(\/.git\/|\/node_modules\/|@theme)/,s.join(this.cwd,"public"),s.join(this.cwd,"README.md"),...this.ignored]});a.on("ready",()=>{this.filesList=v(a.getWatched(),this.cwd),t(a),l.infoTime("init-fs","File system scan completed")}).on("error",e).on("add",(i,r)=>{this.emit({event:"add",path:n(s.relative(this.cwd,i)),stats:r})}).on("change",(i,r)=>{this.emit({event:"change",path:n(s.relative(this.cwd,i)),stats:r})}).on("unlink",i=>{this.emit({event:"unlink",path:n(s.relative(this.cwd,i))})})})}}function v(c,t){const e=new Map;for(const a of Object.keys(c))for(const i of c[a]){const r=s.join(a,i);if(c[r])continue;const p=n(s.dirname(s.relative(t,r))),d=s.posix.join(p,i);e.set(d,{relativePath:d,realRelativePath:d,dirname:p})}return e}export{x as Fs};
