{"version":3,"file":"lintScheduler.js","names":[],"sources":["../../../src/checkers/_shared/lintScheduler.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\n\nexport const DEFAULT_DEBOUNCE_MS = 300\n\nexport interface LintScheduler {\n /** Enqueue an absolute file path for the next batch. No-op after dispose. */\n schedule(filePath: string): void\n /**\n * Stop accepting new events, discard pending files that have not yet been\n * submitted, and return a promise that resolves when any in-flight batch\n * finishes. Callers must ensure their `onBatch` eventually settles — a\n * hanging `onBatch` will hang `dispose()`.\n */\n dispose(): Promise\n}\n\nexport interface LintSchedulerOptions {\n debounceMs: number\n onBatch: (files: string[]) => Promise\n /** Existence probe, overridable for tests. Defaults to `fs.existsSync`. */\n fileExists?: (filePath: string) => boolean\n}\n\nexport function createLintScheduler(opts: LintSchedulerOptions): LintScheduler {\n const { debounceMs, onBatch, fileExists = existsSync } = opts\n\n const pending = new Set()\n let timer: NodeJS.Timeout | null = null\n let inFlight: Promise | null = null\n let disposed = false\n\n function clearTimer() {\n if (timer !== null) {\n clearTimeout(timer)\n timer = null\n }\n }\n\n function drain(): void {\n if (disposed || inFlight || pending.size === 0) return\n clearTimer()\n // Drop files deleted inside the debounce window; linting them would fail\n // the whole batch. The watcher's `unlink` handler clears their diagnostics.\n const snapshot = [...pending].filter((f) => fileExists(f))\n pending.clear()\n if (snapshot.length === 0) return\n\n const raw = onBatch(snapshot)\n inFlight = raw\n\n raw\n .catch((err) => {\n // One failed lint run must not wedge the checker. Log and continue.\n console.error('[vite-plugin-checker] lint batch failed:', err)\n })\n .then(() => {\n inFlight = null\n drain()\n })\n }\n\n return {\n schedule(filePath: string) {\n if (disposed) return\n pending.add(filePath)\n clearTimer()\n timer = setTimeout(() => {\n timer = null\n drain()\n }, debounceMs)\n },\n\n dispose() {\n disposed = true\n clearTimer()\n pending.clear()\n return (inFlight ?? Promise.resolve()).catch(() => {})\n },\n }\n}\n"],"mappings":";;AAEA,MAAa,sBAAsB;AAqBnC,SAAgB,oBAAoB,MAA2C;CAC7E,MAAM,EAAE,YAAY,SAAS,aAAa,eAAe;CAEzD,MAAM,0BAAU,IAAI,IAAY;CAChC,IAAI,QAA+B;CACnC,IAAI,WAAiC;CACrC,IAAI,WAAW;CAEf,SAAS,aAAa;EACpB,IAAI,UAAU,MAAM;GAClB,aAAa,KAAK;GAClB,QAAQ;EACV;CACF;CAEA,SAAS,QAAc;EACrB,IAAI,YAAY,YAAY,QAAQ,SAAS,GAAG;EAChD,WAAW;EAGX,MAAM,WAAW,CAAC,GAAG,OAAO,CAAC,CAAC,QAAQ,MAAM,WAAW,CAAC,CAAC;EACzD,QAAQ,MAAM;EACd,IAAI,SAAS,WAAW,GAAG;EAE3B,MAAM,MAAM,QAAQ,QAAQ;EAC5B,WAAW;EAEX,IACG,OAAO,QAAQ;GAEd,QAAQ,MAAM,4CAA4C,GAAG;EAC/D,CAAC,CAAC,CACD,WAAW;GACV,WAAW;GACX,MAAM;EACR,CAAC;CACL;CAEA,OAAO;EACL,SAAS,UAAkB;GACzB,IAAI,UAAU;GACd,QAAQ,IAAI,QAAQ;GACpB,WAAW;GACX,QAAQ,iBAAiB;IACvB,QAAQ;IACR,MAAM;GACR,GAAG,UAAU;EACf;EAEA,UAAU;GACR,WAAW;GACX,WAAW;GACX,QAAQ,MAAM;GACd,QAAQ,YAAY,QAAQ,QAAQ,EAAA,CAAG,YAAY,CAAC,CAAC;EACvD;CACF;AACF"}