UNPKG

@intlayer/chokidar

Version:

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

1 lines 3.05 kB
{"version":3,"sources":["../../../src/utils/runOnce.ts"],"sourcesContent":["import { mkdir, stat, unlink, writeFile } from 'fs/promises';\nimport { dirname } from 'path';\n\n/**\n * Ensures a callback function runs only once within a specified time window across multiple processes.\n * Uses a sentinel file to coordinate execution and prevent duplicate work.\n *\n * @param sentinelFilePath - Path to the sentinel file used for coordination\n * @param callback - The function to execute (should be async)\n * @param cacheTimeoutMs - Time window in milliseconds during which the sentinel is considered valid (default: 60000ms = 1 minute)\n *\n * @example\n * ```typescript\n * await runPrepareIntlayerOnce(\n * '/tmp/intlayer-sentinel',\n * async () => {\n * // Your initialization logic here\n * await prepareIntlayer();\n * },\n * 30 * 1000 // 30 seconds cache\n * );\n * ```\n *\n * @throws {Error} When there are unexpected filesystem errors\n */\nexport const runOnce = async (\n sentinelFilePath: string,\n callback: () => void | Promise<void>,\n cacheTimeoutMs: number = 60 * 1000 // 1 minute in milliseconds\n) => {\n const currentTimestamp = Date.now();\n const timeoutDuration = cacheTimeoutMs;\n\n try {\n // Check if sentinel file exists and get its stats\n const sentinelStats = await stat(sentinelFilePath);\n const sentinelAge = currentTimestamp - sentinelStats.mtime.getTime();\n\n // If sentinel is older than the timeout, delete it and rebuild\n if (sentinelAge > timeoutDuration) {\n await unlink(sentinelFilePath);\n // Fall through to create new sentinel and rebuild\n } else {\n // Sentinel is recent, no need to rebuild\n return;\n }\n } catch (err: any) {\n if (err.code === 'ENOENT') {\n // File doesn't exist, continue to create it\n } else {\n throw err; // unexpected FS error\n }\n }\n\n try {\n // Ensure the directory exists before writing the file\n await mkdir(dirname(sentinelFilePath), { recursive: true });\n\n // O_EXCL ensures only the *first* process can create the file\n await writeFile(sentinelFilePath, String(currentTimestamp), { flag: 'wx' });\n } catch (err: any) {\n if (err.code === 'EEXIST') {\n // Another process already created it → we're done\n return;\n }\n throw err; // unexpected FS error\n }\n\n await callback();\n};\n"],"mappings":"AAAA,SAAS,OAAO,MAAM,QAAQ,iBAAiB;AAC/C,SAAS,eAAe;AAwBjB,MAAM,UAAU,OACrB,kBACA,UACA,iBAAyB,KAAK,QAC3B;AACH,QAAM,mBAAmB,KAAK,IAAI;AAClC,QAAM,kBAAkB;AAExB,MAAI;AAEF,UAAM,gBAAgB,MAAM,KAAK,gBAAgB;AACjD,UAAM,cAAc,mBAAmB,cAAc,MAAM,QAAQ;AAGnE,QAAI,cAAc,iBAAiB;AACjC,YAAM,OAAO,gBAAgB;AAAA,IAE/B,OAAO;AAEL;AAAA,IACF;AAAA,EACF,SAAS,KAAU;AACjB,QAAI,IAAI,SAAS,UAAU;AAAA,IAE3B,OAAO;AACL,YAAM;AAAA,IACR;AAAA,EACF;AAEA,MAAI;AAEF,UAAM,MAAM,QAAQ,gBAAgB,GAAG,EAAE,WAAW,KAAK,CAAC;AAG1D,UAAM,UAAU,kBAAkB,OAAO,gBAAgB,GAAG,EAAE,MAAM,KAAK,CAAC;AAAA,EAC5E,SAAS,KAAU;AACjB,QAAI,IAAI,SAAS,UAAU;AAEzB;AAAA,IACF;AACA,UAAM;AAAA,EACR;AAEA,QAAM,SAAS;AACjB;","names":[]}