UNPKG

@intlayer/chokidar

Version:

Uses chokidar to scan and build Intlayer declaration files into dictionaries based on Intlayer configuration.

93 lines (91 loc) 2.79 kB
import { mkdir, readFile, stat, unlink, writeFile } from "node:fs/promises"; import { dirname } from "node:path"; import packageJson from "@intlayer/core/package.json" with { type: "json" }; //#region src/utils/runOnce.ts const DEFAULT_RUN_ONCE_OPTIONS = { cacheTimeoutMs: 60 * 1e3 }; const writeSentinelFile = async (sentinelFilePath, currentTimestamp) => { const data = { version: packageJson.version, timestamp: currentTimestamp }; try { await mkdir(dirname(sentinelFilePath), { recursive: true }); await writeFile(sentinelFilePath, JSON.stringify(data), { flag: "wx" }); } catch (err) { if (err.code === "EEXIST") return; if (err.code === "ENOENT") try { await mkdir(dirname(sentinelFilePath), { recursive: true }); await writeFile(sentinelFilePath, JSON.stringify(data), { flag: "wx" }); return; } catch (retryErr) { if (retryErr.code === "EEXIST") return; } throw err; } }; /** * Ensures a callback function runs only once within a specified time window across multiple processes. * Uses a sentinel file to coordinate execution and prevent duplicate work. * * @param sentinelFilePath - Path to the sentinel file used for coordination * @param callback - The function to execute (should be async) * @param options - The options for the runOnce function * * @example * ```typescript * await runPrepareIntlayerOnce( * '/tmp/intlayer-sentinel', * async () => { * // Your initialization logic here * await prepareIntlayer(); * }, * 30 * 1000 // 30 seconds cache * ); * ``` * * @throws {Error} When there are unexpected filesystem errors */ const runOnce = async (sentinelFilePath, callback, options) => { const { onIsCached, cacheTimeoutMs, forceRun } = { ...DEFAULT_RUN_ONCE_OPTIONS, ...options ?? {} }; const currentTimestamp = Date.now(); try { const sentinelAge = currentTimestamp - (await stat(sentinelFilePath)).mtime.getTime(); let shouldRebuild = Boolean(forceRun) || sentinelAge > cacheTimeoutMs; if (!shouldRebuild) try { const raw = await readFile(sentinelFilePath, "utf8"); let cachedVersion; try { cachedVersion = JSON.parse(raw).version; } catch { cachedVersion = void 0; } if (!cachedVersion || cachedVersion !== packageJson.version) shouldRebuild = true; } catch { shouldRebuild = true; } if (shouldRebuild) try { await unlink(sentinelFilePath); } catch {} else { await onIsCached?.(); return; } } catch (err) { if (err.code === "ENOENT") {} else throw err; } await writeSentinelFile(sentinelFilePath, currentTimestamp); try { await callback(); await writeSentinelFile(sentinelFilePath, currentTimestamp); } catch { try { await unlink(sentinelFilePath); } catch {} } }; //#endregion export { runOnce }; //# sourceMappingURL=runOnce.mjs.map