atomic-lockfile 0.0.1-security → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of atomic-lockfile might be problematic. Click here for more details.
- package/CHANGELOG.md +35 -0
- package/LICENSE +21 -0
- package/README.md +207 -3
- package/dist/esm/adapters/atomic.js +42 -0
- package/dist/esm/adapters/atomic.js.map +1 -0
- package/dist/esm/adapters/fs.js +29 -0
- package/dist/esm/adapters/fs.js.map +1 -0
- package/dist/esm/adapters/index.js +27 -0
- package/dist/esm/adapters/index.js.map +1 -0
- package/dist/esm/adapters/mkdir.js +31 -0
- package/dist/esm/adapters/mkdir.js.map +1 -0
- package/dist/esm/adapters/symlink.js +29 -0
- package/dist/esm/adapters/symlink.js.map +1 -0
- package/dist/esm/async/check.js +11 -0
- package/dist/esm/async/check.js.map +1 -0
- package/dist/esm/async/index.js +4 -0
- package/dist/esm/async/index.js.map +1 -0
- package/dist/esm/async/lock.js +13 -0
- package/dist/esm/async/lock.js.map +1 -0
- package/dist/esm/async/unlock.js +8 -0
- package/dist/esm/async/unlock.js.map +1 -0
- package/dist/esm/cli/commands/cleanup.js +28 -0
- package/dist/esm/cli/commands/cleanup.js.map +1 -0
- package/dist/esm/cli/commands/list.js +26 -0
- package/dist/esm/cli/commands/list.js.map +1 -0
- package/dist/esm/cli/commands/lock.js +26 -0
- package/dist/esm/cli/commands/lock.js.map +1 -0
- package/dist/esm/cli/commands/status.js +27 -0
- package/dist/esm/cli/commands/status.js.map +1 -0
- package/dist/esm/cli/commands/unlock.js +20 -0
- package/dist/esm/cli/commands/unlock.js.map +1 -0
- package/dist/esm/cli/formatters/index.js +14 -0
- package/dist/esm/cli/formatters/index.js.map +1 -0
- package/dist/esm/cli/formatters/json.js +15 -0
- package/dist/esm/cli/formatters/json.js.map +1 -0
- package/dist/esm/cli/formatters/table.js +18 -0
- package/dist/esm/cli/formatters/table.js.map +1 -0
- package/dist/esm/cli/formatters/text.js +20 -0
- package/dist/esm/cli/formatters/text.js.map +1 -0
- package/dist/esm/cli/index.js +56 -0
- package/dist/esm/cli/index.js.map +1 -0
- package/dist/esm/compat/cjs.js +11 -0
- package/dist/esm/compat/cjs.js.map +1 -0
- package/dist/esm/compat/esm.js +11 -0
- package/dist/esm/compat/esm.js.map +1 -0
- package/dist/esm/compat/index.js +4 -0
- package/dist/esm/compat/index.js.map +1 -0
- package/dist/esm/compat/v1.js +23 -0
- package/dist/esm/compat/v1.js.map +1 -0
- package/dist/esm/config/defaults.js +12 -0
- package/dist/esm/config/defaults.js.map +1 -0
- package/dist/esm/config/index.js +17 -0
- package/dist/esm/config/index.js.map +1 -0
- package/dist/esm/config/schema.js +55 -0
- package/dist/esm/config/schema.js.map +1 -0
- package/dist/esm/constants/defaults.js +15 -0
- package/dist/esm/constants/defaults.js.map +1 -0
- package/dist/esm/constants/errors.js +37 -0
- package/dist/esm/constants/errors.js.map +1 -0
- package/dist/esm/constants/index.js +14 -0
- package/dist/esm/constants/index.js.map +1 -0
- package/dist/esm/constants/signals.js +21 -0
- package/dist/esm/constants/signals.js.map +1 -0
- package/dist/esm/constants/timeouts.js +16 -0
- package/dist/esm/constants/timeouts.js.map +1 -0
- package/dist/esm/core/acquire.js +51 -0
- package/dist/esm/core/acquire.js.map +1 -0
- package/dist/esm/core/buildLockData.js +23 -0
- package/dist/esm/core/buildLockData.js.map +1 -0
- package/dist/esm/core/check.js +62 -0
- package/dist/esm/core/check.js.map +1 -0
- package/dist/esm/core/cleanup.js +45 -0
- package/dist/esm/core/cleanup.js.map +1 -0
- package/dist/esm/core/handle.js +43 -0
- package/dist/esm/core/handle.js.map +1 -0
- package/dist/esm/core/index.js +8 -0
- package/dist/esm/core/index.js.map +1 -0
- package/dist/esm/core/list.js +38 -0
- package/dist/esm/core/list.js.map +1 -0
- package/dist/esm/core/release.js +21 -0
- package/dist/esm/core/release.js.map +1 -0
- package/dist/esm/errors/AbortError.js +18 -0
- package/dist/esm/errors/AbortError.js.map +1 -0
- package/dist/esm/errors/ConflictError.js +20 -0
- package/dist/esm/errors/ConflictError.js.map +1 -0
- package/dist/esm/errors/IOError.js +24 -0
- package/dist/esm/errors/IOError.js.map +1 -0
- package/dist/esm/errors/LockError.js +30 -0
- package/dist/esm/errors/LockError.js.map +1 -0
- package/dist/esm/errors/PermissionError.js +21 -0
- package/dist/esm/errors/PermissionError.js.map +1 -0
- package/dist/esm/errors/StaleError.js +27 -0
- package/dist/esm/errors/StaleError.js.map +1 -0
- package/dist/esm/errors/TimeoutError.js +21 -0
- package/dist/esm/errors/TimeoutError.js.map +1 -0
- package/dist/esm/errors/ValidationError.js +21 -0
- package/dist/esm/errors/ValidationError.js.map +1 -0
- package/dist/esm/errors/index.js +24 -0
- package/dist/esm/errors/index.js.map +1 -0
- package/dist/esm/events/emitter.js +41 -0
- package/dist/esm/events/emitter.js.map +1 -0
- package/dist/esm/events/index.js +3 -0
- package/dist/esm/events/index.js.map +1 -0
- package/dist/esm/events/types.js +15 -0
- package/dist/esm/events/types.js.map +1 -0
- package/dist/esm/hooks/afterLock.js +18 -0
- package/dist/esm/hooks/afterLock.js.map +1 -0
- package/dist/esm/hooks/afterUnlock.js +18 -0
- package/dist/esm/hooks/afterUnlock.js.map +1 -0
- package/dist/esm/hooks/beforeLock.js +18 -0
- package/dist/esm/hooks/beforeLock.js.map +1 -0
- package/dist/esm/hooks/beforeUnlock.js +18 -0
- package/dist/esm/hooks/beforeUnlock.js.map +1 -0
- package/dist/esm/hooks/index.js +24 -0
- package/dist/esm/hooks/index.js.map +1 -0
- package/dist/esm/hooks/onError.js +18 -0
- package/dist/esm/hooks/onError.js.map +1 -0
- package/dist/esm/hooks/onStale.js +18 -0
- package/dist/esm/hooks/onStale.js.map +1 -0
- package/dist/esm/hooks/onTimeout.js +18 -0
- package/dist/esm/hooks/onTimeout.js.map +1 -0
- package/dist/esm/index.js +21 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/logger/console.js +38 -0
- package/dist/esm/logger/console.js.map +1 -0
- package/dist/esm/logger/debug.js +26 -0
- package/dist/esm/logger/debug.js.map +1 -0
- package/dist/esm/logger/index.js +15 -0
- package/dist/esm/logger/index.js.map +1 -0
- package/dist/esm/logger/noop.js +12 -0
- package/dist/esm/logger/noop.js.map +1 -0
- package/dist/esm/meta/index.js +3 -0
- package/dist/esm/meta/index.js.map +1 -0
- package/dist/esm/meta/package.js +27 -0
- package/dist/esm/meta/package.js.map +1 -0
- package/dist/esm/meta/version.js +27 -0
- package/dist/esm/meta/version.js.map +1 -0
- package/dist/esm/middleware/index.js +11 -0
- package/dist/esm/middleware/index.js.map +1 -0
- package/dist/esm/middleware/logging.js +20 -0
- package/dist/esm/middleware/logging.js.map +1 -0
- package/dist/esm/middleware/metrics.js +32 -0
- package/dist/esm/middleware/metrics.js.map +1 -0
- package/dist/esm/middleware/retry.js +22 -0
- package/dist/esm/middleware/retry.js.map +1 -0
- package/dist/esm/middleware/timeout.js +28 -0
- package/dist/esm/middleware/timeout.js.map +1 -0
- package/dist/esm/platform/darwin.js +17 -0
- package/dist/esm/platform/darwin.js.map +1 -0
- package/dist/esm/platform/index.js +6 -0
- package/dist/esm/platform/index.js.map +1 -0
- package/dist/esm/platform/linux.js +31 -0
- package/dist/esm/platform/linux.js.map +1 -0
- package/dist/esm/platform/unix.js +34 -0
- package/dist/esm/platform/unix.js.map +1 -0
- package/dist/esm/platform/windows.js +22 -0
- package/dist/esm/platform/windows.js.map +1 -0
- package/dist/esm/plugins/cleanup.js +39 -0
- package/dist/esm/plugins/cleanup.js.map +1 -0
- package/dist/esm/plugins/heartbeat.js +31 -0
- package/dist/esm/plugins/heartbeat.js.map +1 -0
- package/dist/esm/plugins/index.js +6 -0
- package/dist/esm/plugins/index.js.map +1 -0
- package/dist/esm/plugins/pid.js +25 -0
- package/dist/esm/plugins/pid.js.map +1 -0
- package/dist/esm/plugins/stale.js +21 -0
- package/dist/esm/plugins/stale.js.map +1 -0
- package/dist/esm/plugins/ttl.js +28 -0
- package/dist/esm/plugins/ttl.js.map +1 -0
- package/dist/esm/promise/index.js +3 -0
- package/dist/esm/promise/index.js.map +1 -0
- package/dist/esm/promise/lock.js +13 -0
- package/dist/esm/promise/lock.js.map +1 -0
- package/dist/esm/promise/withLock.js +22 -0
- package/dist/esm/promise/withLock.js.map +1 -0
- package/dist/esm/registry/global.js +29 -0
- package/dist/esm/registry/global.js.map +1 -0
- package/dist/esm/registry/index.js +3 -0
- package/dist/esm/registry/index.js.map +1 -0
- package/dist/esm/registry/local.js +28 -0
- package/dist/esm/registry/local.js.map +1 -0
- package/dist/esm/strategies/advisory.js +19 -0
- package/dist/esm/strategies/advisory.js.map +1 -0
- package/dist/esm/strategies/exclusive.js +19 -0
- package/dist/esm/strategies/exclusive.js.map +1 -0
- package/dist/esm/strategies/index.js +27 -0
- package/dist/esm/strategies/index.js.map +1 -0
- package/dist/esm/strategies/optimistic.js +22 -0
- package/dist/esm/strategies/optimistic.js.map +1 -0
- package/dist/esm/strategies/shared.js +19 -0
- package/dist/esm/strategies/shared.js.map +1 -0
- package/dist/esm/sync/check.js +39 -0
- package/dist/esm/sync/check.js.map +1 -0
- package/dist/esm/sync/index.js +4 -0
- package/dist/esm/sync/index.js.map +1 -0
- package/dist/esm/sync/lock.js +39 -0
- package/dist/esm/sync/lock.js.map +1 -0
- package/dist/esm/sync/unlock.js +21 -0
- package/dist/esm/sync/unlock.js.map +1 -0
- package/dist/esm/types/adapter.js +2 -0
- package/dist/esm/types/adapter.js.map +1 -0
- package/dist/esm/types/events.js +2 -0
- package/dist/esm/types/events.js.map +1 -0
- package/dist/esm/types/index.js +2 -0
- package/dist/esm/types/index.js.map +1 -0
- package/dist/esm/types/lock.js +2 -0
- package/dist/esm/types/lock.js.map +1 -0
- package/dist/esm/types/logger.js +2 -0
- package/dist/esm/types/logger.js.map +1 -0
- package/dist/esm/types/options.js +2 -0
- package/dist/esm/types/options.js.map +1 -0
- package/dist/esm/types/state.js +2 -0
- package/dist/esm/types/state.js.map +1 -0
- package/dist/esm/types/strategy.js +2 -0
- package/dist/esm/types/strategy.js.map +1 -0
- package/dist/esm/utils/backoff.js +40 -0
- package/dist/esm/utils/backoff.js.map +1 -0
- package/dist/esm/utils/fs.js +88 -0
- package/dist/esm/utils/fs.js.map +1 -0
- package/dist/esm/utils/hash.js +20 -0
- package/dist/esm/utils/hash.js.map +1 -0
- package/dist/esm/utils/hostname.js +28 -0
- package/dist/esm/utils/hostname.js.map +1 -0
- package/dist/esm/utils/index.js +14 -0
- package/dist/esm/utils/index.js.map +1 -0
- package/dist/esm/utils/parse.js +44 -0
- package/dist/esm/utils/parse.js.map +1 -0
- package/dist/esm/utils/path.js +35 -0
- package/dist/esm/utils/path.js.map +1 -0
- package/dist/esm/utils/pid.js +35 -0
- package/dist/esm/utils/pid.js.map +1 -0
- package/dist/esm/utils/platform.js +35 -0
- package/dist/esm/utils/platform.js.map +1 -0
- package/dist/esm/utils/random.js +26 -0
- package/dist/esm/utils/random.js.map +1 -0
- package/dist/esm/utils/retry.js +37 -0
- package/dist/esm/utils/retry.js.map +1 -0
- package/dist/esm/utils/serialize.js +27 -0
- package/dist/esm/utils/serialize.js.map +1 -0
- package/dist/esm/utils/time.js +44 -0
- package/dist/esm/utils/time.js.map +1 -0
- package/dist/esm/utils/validate.js +42 -0
- package/dist/esm/utils/validate.js.map +1 -0
- package/dist/types/adapters/atomic.d.ts +3 -0
- package/dist/types/adapters/atomic.d.ts.map +1 -0
- package/dist/types/adapters/fs.d.ts +3 -0
- package/dist/types/adapters/fs.d.ts.map +1 -0
- package/dist/types/adapters/index.d.ts +9 -0
- package/dist/types/adapters/index.d.ts.map +1 -0
- package/dist/types/adapters/mkdir.d.ts +3 -0
- package/dist/types/adapters/mkdir.d.ts.map +1 -0
- package/dist/types/adapters/symlink.d.ts +3 -0
- package/dist/types/adapters/symlink.d.ts.map +1 -0
- package/dist/types/async/check.d.ts +6 -0
- package/dist/types/async/check.d.ts.map +1 -0
- package/dist/types/async/index.d.ts +4 -0
- package/dist/types/async/index.d.ts.map +1 -0
- package/dist/types/async/lock.d.ts +5 -0
- package/dist/types/async/lock.d.ts.map +1 -0
- package/dist/types/async/unlock.d.ts +5 -0
- package/dist/types/async/unlock.d.ts.map +1 -0
- package/dist/types/cli/commands/cleanup.d.ts +2 -0
- package/dist/types/cli/commands/cleanup.d.ts.map +1 -0
- package/dist/types/cli/commands/list.d.ts +2 -0
- package/dist/types/cli/commands/list.d.ts.map +1 -0
- package/dist/types/cli/commands/lock.d.ts +2 -0
- package/dist/types/cli/commands/lock.d.ts.map +1 -0
- package/dist/types/cli/commands/status.d.ts +2 -0
- package/dist/types/cli/commands/status.d.ts.map +1 -0
- package/dist/types/cli/commands/unlock.d.ts +2 -0
- package/dist/types/cli/commands/unlock.d.ts.map +1 -0
- package/dist/types/cli/formatters/index.d.ts +7 -0
- package/dist/types/cli/formatters/index.d.ts.map +1 -0
- package/dist/types/cli/formatters/json.d.ts +5 -0
- package/dist/types/cli/formatters/json.d.ts.map +1 -0
- package/dist/types/cli/formatters/table.d.ts +3 -0
- package/dist/types/cli/formatters/table.d.ts.map +1 -0
- package/dist/types/cli/formatters/text.d.ts +6 -0
- package/dist/types/cli/formatters/text.d.ts.map +1 -0
- package/dist/types/cli/index.d.ts +3 -0
- package/dist/types/cli/index.d.ts.map +1 -0
- package/dist/types/compat/cjs.d.ts +11 -0
- package/dist/types/compat/cjs.d.ts.map +1 -0
- package/dist/types/compat/esm.d.ts +11 -0
- package/dist/types/compat/esm.d.ts.map +1 -0
- package/dist/types/compat/index.d.ts +4 -0
- package/dist/types/compat/index.d.ts.map +1 -0
- package/dist/types/compat/v1.d.ts +15 -0
- package/dist/types/compat/v1.d.ts.map +1 -0
- package/dist/types/config/defaults.d.ts +3 -0
- package/dist/types/config/defaults.d.ts.map +1 -0
- package/dist/types/config/index.d.ts +9 -0
- package/dist/types/config/index.d.ts.map +1 -0
- package/dist/types/config/schema.d.ts +12 -0
- package/dist/types/config/schema.d.ts.map +1 -0
- package/dist/types/constants/defaults.d.ts +15 -0
- package/dist/types/constants/defaults.d.ts.map +1 -0
- package/dist/types/constants/errors.d.ts +21 -0
- package/dist/types/constants/errors.d.ts.map +1 -0
- package/dist/types/constants/index.d.ts +14 -0
- package/dist/types/constants/index.d.ts.map +1 -0
- package/dist/types/constants/signals.d.ts +6 -0
- package/dist/types/constants/signals.d.ts.map +1 -0
- package/dist/types/constants/timeouts.d.ts +16 -0
- package/dist/types/constants/timeouts.d.ts.map +1 -0
- package/dist/types/core/acquire.d.ts +4 -0
- package/dist/types/core/acquire.d.ts.map +1 -0
- package/dist/types/core/buildLockData.d.ts +4 -0
- package/dist/types/core/buildLockData.d.ts.map +1 -0
- package/dist/types/core/check.d.ts +6 -0
- package/dist/types/core/check.d.ts.map +1 -0
- package/dist/types/core/cleanup.d.ts +14 -0
- package/dist/types/core/cleanup.d.ts.map +1 -0
- package/dist/types/core/handle.d.ts +4 -0
- package/dist/types/core/handle.d.ts.map +1 -0
- package/dist/types/core/index.d.ts +9 -0
- package/dist/types/core/index.d.ts.map +1 -0
- package/dist/types/core/list.d.ts +4 -0
- package/dist/types/core/list.d.ts.map +1 -0
- package/dist/types/core/release.d.ts +4 -0
- package/dist/types/core/release.d.ts.map +1 -0
- package/dist/types/errors/AbortError.d.ts +8 -0
- package/dist/types/errors/AbortError.d.ts.map +1 -0
- package/dist/types/errors/ConflictError.d.ts +9 -0
- package/dist/types/errors/ConflictError.d.ts.map +1 -0
- package/dist/types/errors/IOError.d.ts +10 -0
- package/dist/types/errors/IOError.d.ts.map +1 -0
- package/dist/types/errors/LockError.d.ts +12 -0
- package/dist/types/errors/LockError.d.ts.map +1 -0
- package/dist/types/errors/PermissionError.d.ts +9 -0
- package/dist/types/errors/PermissionError.d.ts.map +1 -0
- package/dist/types/errors/StaleError.d.ts +11 -0
- package/dist/types/errors/StaleError.d.ts.map +1 -0
- package/dist/types/errors/TimeoutError.d.ts +9 -0
- package/dist/types/errors/TimeoutError.d.ts.map +1 -0
- package/dist/types/errors/ValidationError.d.ts +9 -0
- package/dist/types/errors/ValidationError.d.ts.map +1 -0
- package/dist/types/errors/index.d.ts +14 -0
- package/dist/types/errors/index.d.ts.map +1 -0
- package/dist/types/events/emitter.d.ts +12 -0
- package/dist/types/events/emitter.d.ts.map +1 -0
- package/dist/types/events/index.d.ts +3 -0
- package/dist/types/events/index.d.ts.map +1 -0
- package/dist/types/events/types.d.ts +3 -0
- package/dist/types/events/types.d.ts.map +1 -0
- package/dist/types/hooks/afterLock.d.ts +7 -0
- package/dist/types/hooks/afterLock.d.ts.map +1 -0
- package/dist/types/hooks/afterUnlock.d.ts +7 -0
- package/dist/types/hooks/afterUnlock.d.ts.map +1 -0
- package/dist/types/hooks/beforeLock.d.ts +7 -0
- package/dist/types/hooks/beforeLock.d.ts.map +1 -0
- package/dist/types/hooks/beforeUnlock.d.ts +7 -0
- package/dist/types/hooks/beforeUnlock.d.ts.map +1 -0
- package/dist/types/hooks/index.d.ts +9 -0
- package/dist/types/hooks/index.d.ts.map +1 -0
- package/dist/types/hooks/onError.d.ts +6 -0
- package/dist/types/hooks/onError.d.ts.map +1 -0
- package/dist/types/hooks/onStale.d.ts +7 -0
- package/dist/types/hooks/onStale.d.ts.map +1 -0
- package/dist/types/hooks/onTimeout.d.ts +6 -0
- package/dist/types/hooks/onTimeout.d.ts.map +1 -0
- package/dist/types/index.d.ts +22 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/logger/console.d.ts +3 -0
- package/dist/types/logger/console.d.ts.map +1 -0
- package/dist/types/logger/debug.d.ts +3 -0
- package/dist/types/logger/debug.d.ts.map +1 -0
- package/dist/types/logger/index.d.ts +8 -0
- package/dist/types/logger/index.d.ts.map +1 -0
- package/dist/types/logger/noop.d.ts +3 -0
- package/dist/types/logger/noop.d.ts.map +1 -0
- package/dist/types/meta/index.d.ts +3 -0
- package/dist/types/meta/index.d.ts.map +1 -0
- package/dist/types/meta/package.d.ts +8 -0
- package/dist/types/meta/package.d.ts.map +1 -0
- package/dist/types/meta/version.d.ts +14 -0
- package/dist/types/meta/version.d.ts.map +1 -0
- package/dist/types/middleware/index.d.ts +10 -0
- package/dist/types/middleware/index.d.ts.map +1 -0
- package/dist/types/middleware/logging.d.ts +3 -0
- package/dist/types/middleware/logging.d.ts.map +1 -0
- package/dist/types/middleware/metrics.d.ts +13 -0
- package/dist/types/middleware/metrics.d.ts.map +1 -0
- package/dist/types/middleware/retry.d.ts +5 -0
- package/dist/types/middleware/retry.d.ts.map +1 -0
- package/dist/types/middleware/timeout.d.ts +7 -0
- package/dist/types/middleware/timeout.d.ts.map +1 -0
- package/dist/types/platform/darwin.d.ts +5 -0
- package/dist/types/platform/darwin.d.ts.map +1 -0
- package/dist/types/platform/index.d.ts +6 -0
- package/dist/types/platform/index.d.ts.map +1 -0
- package/dist/types/platform/linux.d.ts +6 -0
- package/dist/types/platform/linux.d.ts.map +1 -0
- package/dist/types/platform/unix.d.ts +8 -0
- package/dist/types/platform/unix.d.ts.map +1 -0
- package/dist/types/platform/windows.d.ts +7 -0
- package/dist/types/platform/windows.d.ts.map +1 -0
- package/dist/types/plugins/cleanup.d.ts +4 -0
- package/dist/types/plugins/cleanup.d.ts.map +1 -0
- package/dist/types/plugins/heartbeat.d.ts +7 -0
- package/dist/types/plugins/heartbeat.d.ts.map +1 -0
- package/dist/types/plugins/index.d.ts +8 -0
- package/dist/types/plugins/index.d.ts.map +1 -0
- package/dist/types/plugins/pid.d.ts +5 -0
- package/dist/types/plugins/pid.d.ts.map +1 -0
- package/dist/types/plugins/stale.d.ts +9 -0
- package/dist/types/plugins/stale.d.ts.map +1 -0
- package/dist/types/plugins/ttl.d.ts +7 -0
- package/dist/types/plugins/ttl.d.ts.map +1 -0
- package/dist/types/promise/index.d.ts +3 -0
- package/dist/types/promise/index.d.ts.map +1 -0
- package/dist/types/promise/lock.d.ts +6 -0
- package/dist/types/promise/lock.d.ts.map +1 -0
- package/dist/types/promise/withLock.d.ts +7 -0
- package/dist/types/promise/withLock.d.ts.map +1 -0
- package/dist/types/registry/global.d.ts +15 -0
- package/dist/types/registry/global.d.ts.map +1 -0
- package/dist/types/registry/index.d.ts +3 -0
- package/dist/types/registry/index.d.ts.map +1 -0
- package/dist/types/registry/local.d.ts +10 -0
- package/dist/types/registry/local.d.ts.map +1 -0
- package/dist/types/strategies/advisory.d.ts +4 -0
- package/dist/types/strategies/advisory.d.ts.map +1 -0
- package/dist/types/strategies/exclusive.d.ts +4 -0
- package/dist/types/strategies/exclusive.d.ts.map +1 -0
- package/dist/types/strategies/index.d.ts +9 -0
- package/dist/types/strategies/index.d.ts.map +1 -0
- package/dist/types/strategies/optimistic.d.ts +8 -0
- package/dist/types/strategies/optimistic.d.ts.map +1 -0
- package/dist/types/strategies/shared.d.ts +4 -0
- package/dist/types/strategies/shared.d.ts.map +1 -0
- package/dist/types/sync/check.d.ts +4 -0
- package/dist/types/sync/check.d.ts.map +1 -0
- package/dist/types/sync/index.d.ts +4 -0
- package/dist/types/sync/index.d.ts.map +1 -0
- package/dist/types/sync/lock.d.ts +7 -0
- package/dist/types/sync/lock.d.ts.map +1 -0
- package/dist/types/sync/unlock.d.ts +3 -0
- package/dist/types/sync/unlock.d.ts.map +1 -0
- package/dist/types/types/adapter.d.ts +21 -0
- package/dist/types/types/adapter.d.ts.map +1 -0
- package/dist/types/types/events.d.ts +37 -0
- package/dist/types/types/events.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +8 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/dist/types/types/lock.d.ts +38 -0
- package/dist/types/types/lock.d.ts.map +1 -0
- package/dist/types/types/logger.d.ts +21 -0
- package/dist/types/types/logger.d.ts.map +1 -0
- package/dist/types/types/options.d.ts +52 -0
- package/dist/types/types/options.d.ts.map +1 -0
- package/dist/types/types/state.d.ts +34 -0
- package/dist/types/types/state.d.ts.map +1 -0
- package/dist/types/types/strategy.d.ts +24 -0
- package/dist/types/types/strategy.d.ts.map +1 -0
- package/dist/types/utils/backoff.d.ts +6 -0
- package/dist/types/utils/backoff.d.ts.map +1 -0
- package/dist/types/utils/fs.d.ts +12 -0
- package/dist/types/utils/fs.d.ts.map +1 -0
- package/dist/types/utils/hash.d.ts +7 -0
- package/dist/types/utils/hash.d.ts.map +1 -0
- package/dist/types/utils/hostname.d.ts +9 -0
- package/dist/types/utils/hostname.d.ts.map +1 -0
- package/dist/types/utils/index.d.ts +14 -0
- package/dist/types/utils/index.d.ts.map +1 -0
- package/dist/types/utils/parse.d.ts +7 -0
- package/dist/types/utils/parse.d.ts.map +1 -0
- package/dist/types/utils/path.d.ts +10 -0
- package/dist/types/utils/path.d.ts.map +1 -0
- package/dist/types/utils/pid.d.ts +11 -0
- package/dist/types/utils/pid.d.ts.map +1 -0
- package/dist/types/utils/platform.d.ts +12 -0
- package/dist/types/utils/platform.d.ts.map +1 -0
- package/dist/types/utils/random.d.ts +7 -0
- package/dist/types/utils/random.d.ts.map +1 -0
- package/dist/types/utils/retry.d.ts +10 -0
- package/dist/types/utils/retry.d.ts.map +1 -0
- package/dist/types/utils/serialize.d.ts +7 -0
- package/dist/types/utils/serialize.d.ts.map +1 -0
- package/dist/types/utils/time.d.ts +12 -0
- package/dist/types/utils/time.d.ts.map +1 -0
- package/dist/types/utils/validate.d.ts +5 -0
- package/dist/types/utils/validate.d.ts.map +1 -0
- package/package.json +132 -3
- package/src/adapters/atomic.ts +39 -0
- package/src/adapters/fs.ts +30 -0
- package/src/adapters/index.ts +31 -0
- package/src/adapters/mkdir.ts +32 -0
- package/src/adapters/symlink.ts +30 -0
- package/src/async/check.ts +15 -0
- package/src/async/index.ts +3 -0
- package/src/async/lock.ts +15 -0
- package/src/async/unlock.ts +11 -0
- package/src/cli/commands/cleanup.ts +28 -0
- package/src/cli/commands/list.ts +27 -0
- package/src/cli/commands/lock.ts +27 -0
- package/src/cli/commands/status.ts +26 -0
- package/src/cli/commands/unlock.ts +20 -0
- package/src/cli/formatters/index.ts +18 -0
- package/src/cli/formatters/json.ts +18 -0
- package/src/cli/formatters/table.ts +26 -0
- package/src/cli/formatters/text.ts +22 -0
- package/src/cli/index.ts +61 -0
- package/src/compat/cjs.ts +11 -0
- package/src/compat/esm.ts +11 -0
- package/src/compat/index.ts +3 -0
- package/src/compat/v1.ts +35 -0
- package/src/config/defaults.ts +20 -0
- package/src/config/index.ts +24 -0
- package/src/config/schema.ts +66 -0
- package/src/constants/defaults.ts +14 -0
- package/src/constants/errors.ts +39 -0
- package/src/constants/index.ts +14 -0
- package/src/constants/signals.ts +26 -0
- package/src/constants/timeouts.ts +18 -0
- package/src/core/acquire.ts +54 -0
- package/src/core/buildLockData.ts +25 -0
- package/src/core/check.ts +66 -0
- package/src/core/cleanup.ts +53 -0
- package/src/core/handle.ts +62 -0
- package/src/core/index.ts +8 -0
- package/src/core/list.ts +38 -0
- package/src/core/release.ts +35 -0
- package/src/errors/AbortError.ts +25 -0
- package/src/errors/ConflictError.ts +28 -0
- package/src/errors/IOError.ts +39 -0
- package/src/errors/LockError.ts +39 -0
- package/src/errors/PermissionError.ts +35 -0
- package/src/errors/StaleError.ts +41 -0
- package/src/errors/TimeoutError.ts +28 -0
- package/src/errors/ValidationError.ts +28 -0
- package/src/errors/index.ts +28 -0
- package/src/events/emitter.ts +50 -0
- package/src/events/index.ts +2 -0
- package/src/events/types.ts +16 -0
- package/src/hooks/afterLock.ts +24 -0
- package/src/hooks/afterUnlock.ts +24 -0
- package/src/hooks/beforeLock.ts +28 -0
- package/src/hooks/beforeUnlock.ts +24 -0
- package/src/hooks/deps +0 -0
- package/src/hooks/index.ts +25 -0
- package/src/hooks/onError.ts +22 -0
- package/src/hooks/onStale.ts +24 -0
- package/src/hooks/onTimeout.ts +27 -0
- package/src/index.ts +25 -0
- package/src/logger/console.ts +39 -0
- package/src/logger/debug.ts +29 -0
- package/src/logger/index.ts +20 -0
- package/src/logger/noop.ts +13 -0
- package/src/meta/index.ts +2 -0
- package/src/meta/package.ts +29 -0
- package/src/meta/version.ts +26 -0
- package/src/middleware/index.ts +18 -0
- package/src/middleware/logging.ts +21 -0
- package/src/middleware/metrics.ts +44 -0
- package/src/middleware/retry.ts +25 -0
- package/src/middleware/timeout.ts +34 -0
- package/src/platform/darwin.ts +19 -0
- package/src/platform/index.ts +6 -0
- package/src/platform/linux.ts +32 -0
- package/src/platform/unix.ts +36 -0
- package/src/platform/windows.ts +26 -0
- package/src/plugins/cleanup.ts +45 -0
- package/src/plugins/heartbeat.ts +42 -0
- package/src/plugins/index.ts +7 -0
- package/src/plugins/pid.ts +26 -0
- package/src/plugins/stale.ts +33 -0
- package/src/plugins/ttl.ts +27 -0
- package/src/promise/index.ts +2 -0
- package/src/promise/lock.ts +23 -0
- package/src/promise/withLock.ts +30 -0
- package/src/registry/global.ts +39 -0
- package/src/registry/index.ts +11 -0
- package/src/registry/local.ts +37 -0
- package/src/strategies/advisory.ts +21 -0
- package/src/strategies/exclusive.ts +21 -0
- package/src/strategies/index.ts +31 -0
- package/src/strategies/optimistic.ts +29 -0
- package/src/strategies/shared.ts +23 -0
- package/src/sync/check.ts +43 -0
- package/src/sync/index.ts +3 -0
- package/src/sync/lock.ts +38 -0
- package/src/sync/unlock.ts +19 -0
- package/src/types/adapter.ts +23 -0
- package/src/types/events.ts +63 -0
- package/src/types/index.ts +24 -0
- package/src/types/lock.ts +40 -0
- package/src/types/logger.ts +23 -0
- package/src/types/options.ts +57 -0
- package/src/types/state.ts +36 -0
- package/src/types/strategy.ts +31 -0
- package/src/utils/backoff.ts +52 -0
- package/src/utils/fs.ts +93 -0
- package/src/utils/hash.ts +25 -0
- package/src/utils/hostname.ts +31 -0
- package/src/utils/index.ts +13 -0
- package/src/utils/parse.ts +43 -0
- package/src/utils/path.ts +43 -0
- package/src/utils/pid.ts +36 -0
- package/src/utils/platform.ts +45 -0
- package/src/utils/random.ts +31 -0
- package/src/utils/retry.ts +59 -0
- package/src/utils/serialize.ts +31 -0
- package/src/utils/time.ts +51 -0
- package/src/utils/validate.ts +45 -0
package/src/utils/fs.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { promises as fsp, constants as fsConstants, accessSync, statSync } from 'node:fs';
|
|
2
|
+
import { IOError } from '../errors/IOError.js';
|
|
3
|
+
|
|
4
|
+
export async function fileExists(filePath: string): Promise<boolean> {
|
|
5
|
+
try {
|
|
6
|
+
await fsp.access(filePath, fsConstants.F_OK);
|
|
7
|
+
return true;
|
|
8
|
+
} catch {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function fileExistsSync(filePath: string): boolean {
|
|
14
|
+
try {
|
|
15
|
+
accessSync(filePath, fsConstants.F_OK);
|
|
16
|
+
return true;
|
|
17
|
+
} catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function isReadable(filePath: string): Promise<boolean> {
|
|
23
|
+
try {
|
|
24
|
+
await fsp.access(filePath, fsConstants.R_OK);
|
|
25
|
+
return true;
|
|
26
|
+
} catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function isWritable(filePath: string): Promise<boolean> {
|
|
32
|
+
try {
|
|
33
|
+
await fsp.access(filePath, fsConstants.W_OK);
|
|
34
|
+
return true;
|
|
35
|
+
} catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function readFileSafe(filePath: string, path: string, lockPath: string): Promise<string> {
|
|
41
|
+
try {
|
|
42
|
+
return await fsp.readFile(filePath, 'utf-8');
|
|
43
|
+
} catch (err) {
|
|
44
|
+
throw new IOError(path, lockPath, 'read', err as Error);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function writeFileSafe(
|
|
49
|
+
filePath: string,
|
|
50
|
+
content: string,
|
|
51
|
+
path: string,
|
|
52
|
+
lockPath: string,
|
|
53
|
+
): Promise<void> {
|
|
54
|
+
try {
|
|
55
|
+
await fsp.writeFile(filePath, content, { encoding: 'utf-8', flag: 'wx' });
|
|
56
|
+
} catch (err) {
|
|
57
|
+
throw new IOError(path, lockPath, 'write', err as Error);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export async function unlinkSafe(filePath: string): Promise<void> {
|
|
62
|
+
try {
|
|
63
|
+
await fsp.unlink(filePath);
|
|
64
|
+
} catch (err) {
|
|
65
|
+
const e = err as NodeJS.ErrnoException;
|
|
66
|
+
if (e.code !== 'ENOENT') throw err;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export async function getFileMtimeMs(filePath: string): Promise<number | null> {
|
|
71
|
+
try {
|
|
72
|
+
const stat = await fsp.stat(filePath);
|
|
73
|
+
return stat.mtimeMs;
|
|
74
|
+
} catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function getFileMtimeMsSync(filePath: string): number | null {
|
|
80
|
+
try {
|
|
81
|
+
return statSync(filePath).mtimeMs;
|
|
82
|
+
} catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export async function ensureDir(dirPath: string): Promise<void> {
|
|
88
|
+
await fsp.mkdir(dirPath, { recursive: true });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export async function renameSafe(oldPath: string, newPath: string): Promise<void> {
|
|
92
|
+
await fsp.rename(oldPath, newPath);
|
|
93
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
export function sha256(input: string): string {
|
|
4
|
+
return createHash('sha256').update(input).digest('hex');
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function md5(input: string): string {
|
|
8
|
+
return createHash('md5').update(input).digest('hex');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function sha1(input: string): string {
|
|
12
|
+
return createHash('sha1').update(input).digest('hex');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function hashLockPath(lockPath: string): string {
|
|
16
|
+
return sha256(lockPath).slice(0, 12);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function hashContent(content: string): string {
|
|
20
|
+
return sha256(content);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function buildLockFingerprint(pid: number, hostname: string, nonce: string): string {
|
|
24
|
+
return sha256(`${pid}:${hostname}:${nonce}`).slice(0, 16);
|
|
25
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { hostname as osHostname } from 'node:os';
|
|
2
|
+
|
|
3
|
+
let cachedHostname: string | undefined;
|
|
4
|
+
|
|
5
|
+
export function getHostname(): string {
|
|
6
|
+
if (cachedHostname === undefined) {
|
|
7
|
+
cachedHostname = osHostname();
|
|
8
|
+
}
|
|
9
|
+
return cachedHostname;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function clearHostnameCache(): void {
|
|
13
|
+
cachedHostname = undefined;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function isSameHost(hostname: string): boolean {
|
|
17
|
+
return hostname === getHostname();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function formatHostPid(hostname: string, pid: number): string {
|
|
21
|
+
return `${hostname}:${pid}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function parseHostPid(formatted: string): { hostname: string; pid: number } | null {
|
|
25
|
+
const idx = formatted.lastIndexOf(':');
|
|
26
|
+
if (idx === -1) return null;
|
|
27
|
+
const hostname = formatted.slice(0, idx);
|
|
28
|
+
const pid = parseInt(formatted.slice(idx + 1), 10);
|
|
29
|
+
if (isNaN(pid)) return null;
|
|
30
|
+
return { hostname, pid };
|
|
31
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './path.js';
|
|
2
|
+
export * from './fs.js';
|
|
3
|
+
export * from './pid.js';
|
|
4
|
+
export * from './time.js';
|
|
5
|
+
export * from './retry.js';
|
|
6
|
+
export * from './backoff.js';
|
|
7
|
+
export * from './random.js';
|
|
8
|
+
export * from './hash.js';
|
|
9
|
+
export * from './hostname.js';
|
|
10
|
+
export * from './platform.js';
|
|
11
|
+
export * from './validate.js';
|
|
12
|
+
export * from './serialize.js';
|
|
13
|
+
export * from './parse.js';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { LockData } from '../types/lock.js';
|
|
2
|
+
import { safeDeserializeLockData } from './serialize.js';
|
|
3
|
+
|
|
4
|
+
export function parseLockFile(raw: string): LockData | null {
|
|
5
|
+
if (!raw || !raw.trim()) return null;
|
|
6
|
+
return safeDeserializeLockData(raw);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function parseRetries(value: unknown, fallback: number): number {
|
|
10
|
+
const n = Number(value);
|
|
11
|
+
return isNaN(n) || n < 0 ? fallback : Math.floor(n);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function parseMs(value: unknown, fallback: number): number {
|
|
15
|
+
const n = Number(value);
|
|
16
|
+
return isNaN(n) || n <= 0 ? fallback : n;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function parseBool(value: unknown, fallback: boolean): boolean {
|
|
20
|
+
if (typeof value === 'boolean') return value;
|
|
21
|
+
if (value === 'true') return true;
|
|
22
|
+
if (value === 'false') return false;
|
|
23
|
+
return fallback;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function parseCliArgs(args: string[]): Record<string, string | boolean> {
|
|
27
|
+
const result: Record<string, string | boolean> = {};
|
|
28
|
+
for (let i = 0; i < args.length; i++) {
|
|
29
|
+
const arg = args[i];
|
|
30
|
+
if (!arg) continue;
|
|
31
|
+
if (arg.startsWith('--')) {
|
|
32
|
+
const key = arg.slice(2);
|
|
33
|
+
const next = args[i + 1];
|
|
34
|
+
if (next && !next.startsWith('--')) {
|
|
35
|
+
result[key] = next;
|
|
36
|
+
i++;
|
|
37
|
+
} else {
|
|
38
|
+
result[key] = true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { resolve, dirname, basename, extname, join } from 'node:path';
|
|
2
|
+
import { DEFAULT_LOCK_EXTENSION } from '../constants/defaults.js';
|
|
3
|
+
|
|
4
|
+
export function resolveLockPath(filePath: string, extension = DEFAULT_LOCK_EXTENSION): string {
|
|
5
|
+
return resolve(filePath) + extension;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function getLockDir(lockPath: string): string {
|
|
9
|
+
return dirname(lockPath);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function getLockBasename(lockPath: string): string {
|
|
13
|
+
return basename(lockPath);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function stripLockExtension(lockPath: string, extension = DEFAULT_LOCK_EXTENSION): string {
|
|
17
|
+
if (lockPath.endsWith(extension)) {
|
|
18
|
+
return lockPath.slice(0, -extension.length);
|
|
19
|
+
}
|
|
20
|
+
return lockPath;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function isAbsolutePath(filePath: string): boolean {
|
|
24
|
+
return filePath.startsWith('/') || /^[A-Za-z]:[\\/]/.test(filePath);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function toAbsolutePath(filePath: string): string {
|
|
28
|
+
return isAbsolutePath(filePath) ? filePath : resolve(process.cwd(), filePath);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function buildTmpPath(lockPath: string, nonce: string): string {
|
|
32
|
+
const dir = dirname(lockPath);
|
|
33
|
+
const base = basename(lockPath);
|
|
34
|
+
return join(dir, `.atomic-${nonce}-${base}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function getFileExtension(filePath: string): string {
|
|
38
|
+
return extname(filePath);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function sanitizePath(filePath: string): string {
|
|
42
|
+
return filePath.replace(/\0/g, '').trim();
|
|
43
|
+
}
|
package/src/utils/pid.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export function getCurrentPid(): number {
|
|
2
|
+
return process.pid;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function isProcessAlive(pid: number): boolean {
|
|
6
|
+
if (pid <= 0) return false;
|
|
7
|
+
try {
|
|
8
|
+
process.kill(pid, 0);
|
|
9
|
+
return true;
|
|
10
|
+
} catch (err) {
|
|
11
|
+
const e = err as NodeJS.ErrnoException;
|
|
12
|
+
if (e.code === 'EPERM') return true;
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isSamePid(pid: number): boolean {
|
|
18
|
+
return pid === process.pid;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function isOrphanedPid(pid: number): boolean {
|
|
22
|
+
return !isProcessAlive(pid);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function getPidInfo(pid: number): { alive: boolean; owned: boolean; orphaned: boolean } {
|
|
26
|
+
const alive = isProcessAlive(pid);
|
|
27
|
+
return {
|
|
28
|
+
alive,
|
|
29
|
+
owned: pid === process.pid,
|
|
30
|
+
orphaned: !alive,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function formatPid(pid: number): string {
|
|
35
|
+
return `PID:${pid}`;
|
|
36
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export type Platform = 'linux' | 'darwin' | 'win32' | 'freebsd' | 'openbsd' | 'unknown';
|
|
2
|
+
|
|
3
|
+
export function getPlatform(): Platform {
|
|
4
|
+
const p = process.platform;
|
|
5
|
+
if (p === 'linux' || p === 'darwin' || p === 'win32' || p === 'freebsd' || p === 'openbsd') {
|
|
6
|
+
return p;
|
|
7
|
+
}
|
|
8
|
+
return 'unknown';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function isWindows(): boolean {
|
|
12
|
+
return process.platform === 'win32';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function isMacOS(): boolean {
|
|
16
|
+
return process.platform === 'darwin';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function isLinux(): boolean {
|
|
20
|
+
return process.platform === 'linux';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function isUnix(): boolean {
|
|
24
|
+
return !isWindows();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function supportsHardLinks(): boolean {
|
|
28
|
+
return isUnix();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function supportsSymlinks(): boolean {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function getPathSeparator(): string {
|
|
36
|
+
return isWindows() ? '\\' : '/';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function getUid(): number | null {
|
|
40
|
+
return typeof process.getuid === 'function' ? process.getuid() : null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function getGid(): number | null {
|
|
44
|
+
return typeof process.getgid === 'function' ? process.getgid() : null;
|
|
45
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { randomBytes, randomUUID as nodeRandomUUID } from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
export function generateNonce(byteLength = 16): string {
|
|
4
|
+
return randomBytes(byteLength).toString('hex');
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function randomJitter(maxMs: number): number {
|
|
8
|
+
return Math.floor(Math.random() * maxMs);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function randomInt(min: number, max: number): number {
|
|
12
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function randomUUID(): string {
|
|
16
|
+
return nodeRandomUUID();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function randomChoice<T>(arr: readonly T[]): T {
|
|
20
|
+
const index = Math.floor(Math.random() * arr.length);
|
|
21
|
+
return arr[index] as T;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function shuffleArray<T>(arr: T[]): T[] {
|
|
25
|
+
const copy = [...arr];
|
|
26
|
+
for (let i = copy.length - 1; i > 0; i--) {
|
|
27
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
28
|
+
[copy[i], copy[j]] = [copy[j] as T, copy[i] as T];
|
|
29
|
+
}
|
|
30
|
+
return copy;
|
|
31
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { sleep } from './time.js';
|
|
2
|
+
import { computeBackoffDelay } from './backoff.js';
|
|
3
|
+
import type { AcquireOptions } from '../types/options.js';
|
|
4
|
+
|
|
5
|
+
export interface RetryState {
|
|
6
|
+
attempt: number;
|
|
7
|
+
totalElapsedMs: number;
|
|
8
|
+
lastError: Error | null;
|
|
9
|
+
startedAt: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function withRetry<T>(
|
|
13
|
+
fn: () => Promise<T>,
|
|
14
|
+
options: Pick<AcquireOptions, 'retries' | 'retryDelay' | 'retryBackoff' | 'retryMaxDelay' | 'timeout' | 'signal' | 'onRetry'>,
|
|
15
|
+
): Promise<T> {
|
|
16
|
+
const maxAttempts = (options.retries ?? 5) + 1;
|
|
17
|
+
const startedAt = Date.now();
|
|
18
|
+
const timeout = options.timeout;
|
|
19
|
+
let lastError: Error = new Error('Unknown error');
|
|
20
|
+
|
|
21
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
22
|
+
if (options.signal?.aborted) {
|
|
23
|
+
throw new Error('Aborted');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (timeout !== undefined && Date.now() - startedAt >= timeout) {
|
|
27
|
+
throw new Error(`Timeout after ${timeout}ms`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
return await fn();
|
|
32
|
+
} catch (err) {
|
|
33
|
+
lastError = err as Error;
|
|
34
|
+
|
|
35
|
+
if (attempt < maxAttempts - 1) {
|
|
36
|
+
const delay = computeBackoffDelay(
|
|
37
|
+
attempt,
|
|
38
|
+
options.retryDelay ?? 100,
|
|
39
|
+
options.retryBackoff ?? 'exponential',
|
|
40
|
+
options.retryMaxDelay ?? 5000,
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
options.onRetry?.(attempt + 1, lastError);
|
|
44
|
+
await sleep(delay, options.signal);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
throw lastError;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function createRetryState(): RetryState {
|
|
53
|
+
return {
|
|
54
|
+
attempt: 0,
|
|
55
|
+
totalElapsedMs: 0,
|
|
56
|
+
lastError: null,
|
|
57
|
+
startedAt: Date.now(),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { LockData } from '../types/lock.js';
|
|
2
|
+
import { LOCK_FILE_MAGIC } from '../constants/index.js';
|
|
3
|
+
|
|
4
|
+
export function serializeLockData(data: LockData): string {
|
|
5
|
+
return JSON.stringify({ _magic: LOCK_FILE_MAGIC, ...data }, null, 2);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function deserializeLockData(raw: string): LockData {
|
|
9
|
+
const parsed = JSON.parse(raw) as Record<string, unknown>;
|
|
10
|
+
if (parsed['_magic'] !== LOCK_FILE_MAGIC) {
|
|
11
|
+
throw new Error(`Invalid lock file: missing or wrong magic header`);
|
|
12
|
+
}
|
|
13
|
+
const { _magic: _m, ...data } = parsed;
|
|
14
|
+
return data as unknown as LockData;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function safeDeserializeLockData(raw: string): LockData | null {
|
|
18
|
+
try {
|
|
19
|
+
return deserializeLockData(raw);
|
|
20
|
+
} catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function serializeToBase64(data: LockData): string {
|
|
26
|
+
return Buffer.from(serializeLockData(data)).toString('base64');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function deserializeFromBase64(encoded: string): LockData {
|
|
30
|
+
return deserializeLockData(Buffer.from(encoded, 'base64').toString('utf-8'));
|
|
31
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export function now(): number {
|
|
2
|
+
return Date.now();
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function hrNow(): bigint {
|
|
6
|
+
return process.hrtime.bigint();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function elapsedMs(startMs: number): number {
|
|
10
|
+
return Date.now() - startMs;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function elapsedHrMs(startNs: bigint): number {
|
|
14
|
+
return Number(process.hrtime.bigint() - startNs) / 1_000_000;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isExpired(createdAt: number, ttlMs: number): boolean {
|
|
18
|
+
return Date.now() - createdAt > ttlMs;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function isStale(updatedAt: number, staleAgeMs: number): boolean {
|
|
22
|
+
return Date.now() - updatedAt > staleAgeMs;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function ageMs(timestamp: number): number {
|
|
26
|
+
return Date.now() - timestamp;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function expiresAt(createdAt: number, ttlMs: number): number {
|
|
30
|
+
return createdAt + ttlMs;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function remainingTtlMs(createdAt: number, ttlMs: number): number {
|
|
34
|
+
return Math.max(0, expiresAt(createdAt, ttlMs) - Date.now());
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function sleep(ms: number, signal?: AbortSignal): Promise<void> {
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
|
+
const timeout = setTimeout(resolve, ms);
|
|
40
|
+
signal?.addEventListener('abort', () => {
|
|
41
|
+
clearTimeout(timeout);
|
|
42
|
+
reject(new Error('Aborted'));
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function formatDuration(ms: number): string {
|
|
48
|
+
if (ms < 1000) return `${ms}ms`;
|
|
49
|
+
if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`;
|
|
50
|
+
return `${(ms / 60_000).toFixed(1)}m`;
|
|
51
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ValidationError } from '../errors/ValidationError.js';
|
|
2
|
+
import type { AcquireOptions } from '../types/options.js';
|
|
3
|
+
|
|
4
|
+
export function validatePath(filePath: string, lockPath: string): void {
|
|
5
|
+
if (!filePath || typeof filePath !== 'string') {
|
|
6
|
+
throw new ValidationError(filePath, lockPath, 'path', filePath, 'must be a non-empty string');
|
|
7
|
+
}
|
|
8
|
+
if (filePath.includes('\0')) {
|
|
9
|
+
throw new ValidationError(filePath, lockPath, 'path', filePath, 'must not contain null bytes');
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function validateOptions(path: string, lockPath: string, opts: AcquireOptions): void {
|
|
14
|
+
if (opts.retries !== undefined && (opts.retries < 0 || !Number.isInteger(opts.retries))) {
|
|
15
|
+
throw new ValidationError(path, lockPath, 'retries', opts.retries, 'must be a non-negative integer');
|
|
16
|
+
}
|
|
17
|
+
if (opts.retryDelay !== undefined && opts.retryDelay < 0) {
|
|
18
|
+
throw new ValidationError(path, lockPath, 'retryDelay', opts.retryDelay, 'must be >= 0');
|
|
19
|
+
}
|
|
20
|
+
if (opts.timeout !== undefined && opts.timeout <= 0) {
|
|
21
|
+
throw new ValidationError(path, lockPath, 'timeout', opts.timeout, 'must be > 0');
|
|
22
|
+
}
|
|
23
|
+
if (opts.ttl !== undefined && opts.ttl <= 0) {
|
|
24
|
+
throw new ValidationError(path, lockPath, 'ttl', opts.ttl, 'must be > 0');
|
|
25
|
+
}
|
|
26
|
+
if (opts.staleAge !== undefined && opts.staleAge <= 0) {
|
|
27
|
+
throw new ValidationError(path, lockPath, 'staleAge', opts.staleAge, 'must be > 0');
|
|
28
|
+
}
|
|
29
|
+
if (opts.heartbeatInterval !== undefined && opts.heartbeatInterval <= 0) {
|
|
30
|
+
throw new ValidationError(path, lockPath, 'heartbeatInterval', opts.heartbeatInterval, 'must be > 0');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function validateLockData(path: string, lockPath: string, data: unknown): void {
|
|
35
|
+
if (!data || typeof data !== 'object') {
|
|
36
|
+
throw new ValidationError(path, lockPath, 'lockData', data, 'must be an object');
|
|
37
|
+
}
|
|
38
|
+
const d = data as Record<string, unknown>;
|
|
39
|
+
if (typeof d['pid'] !== 'number') {
|
|
40
|
+
throw new ValidationError(path, lockPath, 'lockData.pid', d['pid'], 'must be a number');
|
|
41
|
+
}
|
|
42
|
+
if (typeof d['hostname'] !== 'string') {
|
|
43
|
+
throw new ValidationError(path, lockPath, 'lockData.hostname', d['hostname'], 'must be a string');
|
|
44
|
+
}
|
|
45
|
+
}
|