UNPKG

@push.rocks/smartchok

Version:

A cross-runtime file watcher with glob pattern support for Node.js, Deno, and Bun.

84 lines 6.24 kB
import * as fs from 'fs'; /** * Implements awaitWriteFinish functionality by polling file size until stable. * This replaces chokidar's built-in write stabilization. */ export class WriteStabilizer { constructor(stabilityThreshold = 300, pollInterval = 100) { this.stabilityThreshold = stabilityThreshold; this.pollInterval = pollInterval; this.pendingWrites = new Map(); } /** * Wait for a file write to complete by polling until size is stable */ async waitForWriteFinish(filePath) { // Cancel any existing pending check for this file this.cancel(filePath); return new Promise((resolve, reject) => { const poll = async () => { try { const stats = await fs.promises.stat(filePath); const pending = this.pendingWrites.get(filePath); if (!pending) { // Was cancelled return; } const now = Date.now(); if (stats.size !== pending.lastSize) { // Size changed - file is still being written, reset timer pending.lastSize = stats.size; pending.lastChange = now; pending.timeoutId = setTimeout(poll, this.pollInterval); } else if (now - pending.lastChange >= this.stabilityThreshold) { // Size has been stable for the threshold duration this.pendingWrites.delete(filePath); resolve(stats); } else { // Size is the same but not yet past threshold pending.timeoutId = setTimeout(poll, this.pollInterval); } } catch (error) { this.pendingWrites.delete(filePath); if (error.code === 'ENOENT') { // File was deleted during polling reject(new Error(`File was deleted: ${filePath}`)); } else { reject(error); } } }; this.pendingWrites.set(filePath, { lastSize: -1, lastChange: Date.now(), timeoutId: setTimeout(poll, this.pollInterval), resolve, reject }); }); } /** * Cancel any pending write stabilization for a file */ cancel(filePath) { const pending = this.pendingWrites.get(filePath); if (pending) { clearTimeout(pending.timeoutId); this.pendingWrites.delete(filePath); } } /** * Cancel all pending write stabilizations */ cancelAll() { for (const [filePath, pending] of this.pendingWrites) { clearTimeout(pending.timeoutId); } this.pendingWrites.clear(); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JpdGUtc3RhYmlsaXplci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3V0aWxzL3dyaXRlLXN0YWJpbGl6ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFVekI7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLGVBQWU7SUFHMUIsWUFDVSxxQkFBNkIsR0FBRyxFQUNoQyxlQUF1QixHQUFHO1FBRDFCLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBYztRQUNoQyxpQkFBWSxHQUFaLFlBQVksQ0FBYztRQUo1QixrQkFBYSxHQUFHLElBQUksR0FBRyxFQUF5QixDQUFDO0lBS3RELENBQUM7SUFFSjs7T0FFRztJQUNILEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxRQUFnQjtRQUN2QyxrREFBa0Q7UUFDbEQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUV0QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3JDLE1BQU0sSUFBSSxHQUFHLEtBQUssSUFBSSxFQUFFO2dCQUN0QixJQUFJLENBQUM7b0JBQ0gsTUFBTSxLQUFLLEdBQUcsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztvQkFDL0MsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7b0JBRWpELElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQzt3QkFDYixnQkFBZ0I7d0JBQ2hCLE9BQU87b0JBQ1QsQ0FBQztvQkFFRCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7b0JBRXZCLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUM7d0JBQ3BDLDBEQUEwRDt3QkFDMUQsT0FBTyxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDO3dCQUM5QixPQUFPLENBQUMsVUFBVSxHQUFHLEdBQUcsQ0FBQzt3QkFDekIsT0FBTyxDQUFDLFNBQVMsR0FBRyxVQUFVLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztvQkFDMUQsQ0FBQzt5QkFBTSxJQUFJLEdBQUcsR0FBRyxPQUFPLENBQUMsVUFBVSxJQUFJLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO3dCQUMvRCxrREFBa0Q7d0JBQ2xELElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO3dCQUNwQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQ2pCLENBQUM7eUJBQU0sQ0FBQzt3QkFDTiw4Q0FBOEM7d0JBQzlDLE9BQU8sQ0FBQyxTQUFTLEdBQUcsVUFBVSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7b0JBQzFELENBQUM7Z0JBQ0gsQ0FBQztnQkFBQyxPQUFPLEtBQVUsRUFBRSxDQUFDO29CQUNwQixJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztvQkFDcEMsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO3dCQUM1QixrQ0FBa0M7d0JBQ2xDLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxxQkFBcUIsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO29CQUNyRCxDQUFDO3lCQUFNLENBQUM7d0JBQ04sTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUNoQixDQUFDO2dCQUNILENBQUM7WUFDSCxDQUFDLENBQUM7WUFFRixJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUU7Z0JBQy9CLFFBQVEsRUFBRSxDQUFDLENBQUM7Z0JBQ1osVUFBVSxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7Z0JBQ3RCLFNBQVMsRUFBRSxVQUFVLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUM7Z0JBQzlDLE9BQU87Z0JBQ1AsTUFBTTthQUNQLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0gsTUFBTSxDQUFDLFFBQWdCO1FBQ3JCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2pELElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixZQUFZLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ2hDLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3RDLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxTQUFTO1FBQ1AsS0FBSyxNQUFNLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNyRCxZQUFZLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ2xDLENBQUM7UUFDRCxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQzdCLENBQUM7Q0FDRiJ9