{"_id":"@bybrave/proper-lockfile2","name":"@bybrave/proper-lockfile2","dist-tags":{"latest":"5.0.0"},"versions":{"5.0.0":{"name":"@bybrave/proper-lockfile2","version":"5.0.0","description":"Maintained fork of proper-lockfile — an inter-process and inter-machine lockfile utility that works on a local or network file system","main":"index.js","types":"index.d.ts","scripts":{"test":"jest --env node --runInBand"},"repository":{"type":"git","url":"git+https://github.com/bybraveHQ/proper-lockfile2.git"},"bugs":{"url":"https://github.com/bybraveHQ/proper-lockfile2/issues"},"homepage":"https://github.com/bybraveHQ/proper-lockfile2#readme","keywords":["lock","lockfile","locker","mutex","flock","proper-lockfile","stale","typescript"],"author":{"name":"bybrave","url":"https://github.com/bybraveHQ"},"contributors":[{"name":"André Cruz","email":"andre@moxy.studio","url":"author of the original proper-lockfile"}],"license":"MIT","funding":"https://ko-fi.com/bybrave","engines":{"node":">=18"},"dependencies":{"graceful-fs":"^4.2.11","retry":"^0.13.1","signal-exit":"^3.0.7"},"devDependencies":{"@segment/clear-timeouts":"^2.0.0","delay":"^5.0.0","execa":"^5.1.1","jest":"^29.7.0","mkdirp":"^1.0.4","p-defer":"^3.0.0","rimraf":"^3.0.2","thread-sleep":"^2.2.0"},"_id":"@bybrave/proper-lockfile2@5.0.0","gitHead":"5022035795b86c47157807ba30f343c1de3b89f6","_nodeVersion":"20.19.6","_npmVersion":"10.8.2","dist":{"integrity":"sha512-oeebmWF78nnEw/v3B93dOsuqpGFseDoab9YdSDXSNGfksh5n9KIabFo9lzleEdiPygbpm6btCj6O58k0z1xaEw==","shasum":"08ac52edda4528cec4c3b3f052744262db150be6","tarball":"https://registry.npmjs.org/@bybrave/proper-lockfile2/-/proper-lockfile2-5.0.0.tgz","fileCount":8,"unpackedSize":28127,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDDh8EEBgRjHqNzwBy3ZvLzK1HoiCZKM+ZnbNkknKcEVAIhAPUz0TU5zzMwdggU+bJ7/hlJvQxgNj/YkV0raiC8NjWv"}]},"_npmUser":{"name":"bybrave","email":"opmybrave@gmail.com"},"directories":{},"maintainers":[{"name":"bybrave","email":"opmybrave@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/proper-lockfile2_5.0.0_1783201496449_0.5820295678380456"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-04T21:44:56.317Z","5.0.0":"2026-07-04T21:44:56.589Z","modified":"2026-07-04T21:44:56.740Z"},"maintainers":[{"name":"bybrave","email":"opmybrave@gmail.com"}],"description":"Maintained fork of proper-lockfile — an inter-process and inter-machine lockfile utility that works on a local or network file system","homepage":"https://github.com/bybraveHQ/proper-lockfile2#readme","keywords":["lock","lockfile","locker","mutex","flock","proper-lockfile","stale","typescript"],"repository":{"type":"git","url":"git+https://github.com/bybraveHQ/proper-lockfile2.git"},"contributors":[{"name":"André Cruz","email":"andre@moxy.studio","url":"author of the original proper-lockfile"}],"author":{"name":"bybrave","url":"https://github.com/bybraveHQ"},"bugs":{"url":"https://github.com/bybraveHQ/proper-lockfile2/issues"},"license":"MIT","readme":"# @bybrave/proper-lockfile2\n\n[![CI](https://github.com/bybraveHQ/proper-lockfile2/actions/workflows/ci.yml/badge.svg)](https://github.com/bybraveHQ/proper-lockfile2/actions/workflows/ci.yml)\n[![npm](https://img.shields.io/npm/v/@bybrave/proper-lockfile2.svg)](https://www.npmjs.com/package/@bybrave/proper-lockfile2)\n[![node](https://img.shields.io/node/v/@bybrave/proper-lockfile2.svg?color=339933&logo=node.js&logoColor=white)](https://www.npmjs.com/package/@bybrave/proper-lockfile2)\n[![types](https://img.shields.io/badge/types-included-3178C6?logo=typescript&logoColor=white)](index.d.ts)\n[![license](https://img.shields.io/npm/l/@bybrave/proper-lockfile2.svg?color=blue)](LICENSE)\n\nMaintained fork of [proper-lockfile](https://github.com/moxystudio/node-proper-lockfile) — an inter-process and inter-machine lockfile utility that works on a local or network file system.\n\n## Why this fork\n\nThe original `proper-lockfile` has not been released since 2021. This fork is a drop-in replacement that fixes a real double-lock race and ships the most requested features:\n\n| Change | Upstream issue |\n|---|---|\n| **Stale-lock reclaim race fixed**: two processes could both \"reclaim\" the same stale lock and end up holding it simultaneously | [#121](https://github.com/moxystudio/node-proper-lockfile/issues/121), root cause of many [#92](https://github.com/moxystudio/node-proper-lockfile/issues/92) reports |\n| `onReclaimed` callback: know when your lock was acquired by reclaiming a stale one (e.g. to run crash recovery exactly once) | [#105](https://github.com/moxystudio/node-proper-lockfile/issues/105) |\n| `ELOCKED` error message now hints at the `retries` option — the most common source of confusion | [#92](https://github.com/moxystudio/node-proper-lockfile/issues/92) |\n| TypeScript type definitions included | — |\n| Updated dependencies, CI on Node 18/20/22, original test suite preserved (76 tests) + race regression tests | — |\n\n### The race, in short\n\nUpstream reclaims a stale lock with `rmdir` + `mkdir`. If process A detects a stale lock but stalls before its `rmdir`, process B can reclaim the lock and create a fresh one — which A's late `rmdir` then silently deletes, and both processes believe they own the lock. This fork claims stale locks by atomically **renaming** them to a unique path (only one process can win a rename) and verifies the claimed directory is still the stale one it saw. A reproduction script and regression tests are in [`test/fork.test.js`](test/fork.test.js).\n\n## Install\n\n```sh\nnpm install @bybrave/proper-lockfile2\n```\n\n## Usage\n\n```js\nconst lockfile = require('@bybrave/proper-lockfile2');\n\nconst release = await lockfile.lock('some/file');\n// do your critical work...\nawait release();\n```\n\nWait for a held lock instead of failing:\n\n```js\nconst release = await lockfile.lock('some/file', {\n  retries: { retries: 5, maxTimeout: 1000 },\n});\n```\n\nRun crash recovery when a stale lock (left by a dead process) is reclaimed:\n\n```js\nconst release = await lockfile.lock('some/file', {\n  onReclaimed: () => runRecovery(),\n});\n```\n\nSync API: `lockSync`, `unlockSync`, `checkSync` (retries are not supported in sync mode).\n\n## API\n\n### lock(file, [options]) → Promise&lt;release&gt;\n\nAcquires a lock on `file`, resolving with a `release()` function. Rejects with `ELOCKED` if the lock is held (and not stale).\n\n| Option | Default | Description |\n|---|---|---|\n| `stale` | `10000` | Ms after which a non-updated lock is considered stale (min `2000`) |\n| `update` | `stale/2` | Interval of lockfile mtime refresh (min `1000`, max `stale/2`) |\n| `retries` | `0` | Number of retries (or a [node-retry](https://github.com/tim-kos/node-retry) options object) while acquiring a held lock |\n| `realpath` | `true` | Resolve symlinks; set `false` to lock the symlink itself (also allows locking non-existing paths) |\n| `onCompromised` | `(err) => { throw err; }` | Called when the lock can no longer be guaranteed |\n| `onReclaimed` | — | Called when the lock was acquired by reclaiming a stale lockfile |\n| `lockfilePath` | `${file}.lock` | Custom lockfile location |\n| `fs` | `graceful-fs` | Custom fs implementation |\n\n### unlock(file, [options]) / check(file, [options]) → Promise\n\nSame semantics as the original: `unlock` releases a lock acquired in this process, `check` resolves with whether the file is currently locked. Options: `stale` (check only), `realpath`, `lockfilePath`, `fs`.\n\nFull conceptual documentation (how mtime-based locking works, its guarantees and caveats) is in the [original README](https://github.com/moxystudio/node-proper-lockfile#readme) — the design is unchanged.\n\n## Migrating from proper-lockfile\n\nIt is a drop-in replacement:\n\n```diff\n- const lockfile = require('proper-lockfile');\n+ const lockfile = require('@bybrave/proper-lockfile2');\n```\n\nNo API was removed or changed; `onReclaimed` is the only new option.\n\n## Support\n\nIf this package saves you time, you can support maintenance:\n\n[![Ko-fi](https://img.shields.io/badge/Ko--fi-buy%20me%20a%20coffee-FF5E5B?logo=kofi&logoColor=white)](https://ko-fi.com/bybrave)\n[![Bitcoin](https://img.shields.io/badge/Bitcoin-BTC-F7931A?logo=bitcoin&logoColor=white)](#support)\n\nBitcoin (BTC): `bc1q37557q5jpeaxqydzwvf3jgj7zhnfpn2td3q40q`\n\n## Credits & license\n\nMIT. Based on [proper-lockfile](https://github.com/moxystudio/node-proper-lockfile) by André Cruz / MOXY.\n","readmeFilename":"README.md","_rev":"1-9187be0349e0f336c6d83ee45c01e9b3"}