@lickle/lock 0.0.1-alpha.0 → 0.0.1-alpha.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.
- package/README.md +182 -76
- package/cjs.js +583 -0
- package/dist/cjs/core/guard.d.ts +50 -0
- package/dist/cjs/core/guard.d.ts.map +1 -0
- package/dist/cjs/core/guard.js +91 -0
- package/dist/cjs/core/guard.js.map +1 -0
- package/dist/cjs/core/index.d.ts +8 -0
- package/dist/cjs/core/index.d.ts.map +1 -0
- package/dist/cjs/core/index.js +41 -0
- package/dist/cjs/core/index.js.map +1 -0
- package/dist/cjs/core/locking.d.ts +23 -0
- package/dist/cjs/core/locking.d.ts.map +1 -0
- package/dist/cjs/core/locking.js +93 -0
- package/dist/cjs/core/locking.js.map +1 -0
- package/dist/cjs/core/node.d.ts +19 -0
- package/dist/cjs/core/node.d.ts.map +1 -0
- package/dist/cjs/core/node.js +69 -0
- package/dist/cjs/core/node.js.map +1 -0
- package/dist/cjs/core/types.d.ts +49 -0
- package/dist/cjs/core/types.d.ts.map +1 -0
- package/dist/cjs/core/types.js +13 -0
- package/dist/cjs/core/types.js.map +1 -0
- package/dist/cjs/index.d.ts +63 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +110 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/esm/core/guard.d.ts +50 -0
- package/dist/esm/core/guard.d.ts.map +1 -0
- package/dist/esm/core/guard.js +86 -0
- package/dist/esm/core/guard.js.map +1 -0
- package/dist/esm/core/index.d.ts +8 -0
- package/dist/esm/core/index.d.ts.map +1 -0
- package/dist/esm/core/index.js +21 -0
- package/dist/esm/core/index.js.map +1 -0
- package/dist/esm/core/locking.d.ts +23 -0
- package/dist/esm/core/locking.d.ts.map +1 -0
- package/dist/esm/core/locking.js +56 -0
- package/dist/esm/core/locking.js.map +1 -0
- package/dist/esm/core/node.d.ts +19 -0
- package/dist/esm/core/node.d.ts.map +1 -0
- package/dist/esm/core/node.js +61 -0
- package/dist/esm/core/node.js.map +1 -0
- package/dist/esm/core/types.d.ts +49 -0
- package/dist/esm/core/types.d.ts.map +1 -0
- package/dist/esm/core/types.js +9 -0
- package/dist/esm/core/types.js.map +1 -0
- package/dist/esm/index.d.ts +63 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +88 -0
- package/dist/esm/index.js.map +1 -0
- package/esm.js +587 -0
- package/index.d.ts +40 -0
- package/package.json +6 -6
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileLockGuard = exports.LockGuard = void 0;
|
|
4
|
+
const types_js_1 = require("./types.js");
|
|
5
|
+
/**
|
|
6
|
+
* Guard that holds a lock without owning the file handle.
|
|
7
|
+
* Releasing the guard unlocks the file but does not close it.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const guard = await lock(handle, Lock.Exclusive)
|
|
11
|
+
* try { /* work *\/ } finally { await guard.drop() }
|
|
12
|
+
*/
|
|
13
|
+
class LockGuard {
|
|
14
|
+
locking;
|
|
15
|
+
range;
|
|
16
|
+
_dropped;
|
|
17
|
+
/** The file descriptor number. */
|
|
18
|
+
fd;
|
|
19
|
+
constructor(locking, handle, range) {
|
|
20
|
+
this.locking = locking;
|
|
21
|
+
this.range = range;
|
|
22
|
+
this.fd = (0, types_js_1.resolveFd)(handle);
|
|
23
|
+
}
|
|
24
|
+
/** True if the lock has been released. */
|
|
25
|
+
get dropped() {
|
|
26
|
+
return !!this._dropped;
|
|
27
|
+
}
|
|
28
|
+
/** Release the lock. Safe to call multiple times. */
|
|
29
|
+
drop() {
|
|
30
|
+
if (!this._dropped)
|
|
31
|
+
this._dropped = this.locking.unlock(this.fd, this.range);
|
|
32
|
+
return this._dropped;
|
|
33
|
+
}
|
|
34
|
+
[Symbol.asyncDispose]() {
|
|
35
|
+
return this.drop();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.LockGuard = LockGuard;
|
|
39
|
+
/**
|
|
40
|
+
* RAII guard that holds a file lock. Unlocks and closes the file on drop.
|
|
41
|
+
* Supports `await using` via `Symbol.asyncDispose`.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* await using guard = await exclusive('/tmp/my.lock')
|
|
45
|
+
* // lock is released when guard goes out of scope
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* const guard = await exclusive('/tmp/my.lock')
|
|
49
|
+
* try { /* work *\/ } finally { await guard.drop() }
|
|
50
|
+
*/
|
|
51
|
+
class FileLockGuard {
|
|
52
|
+
guard;
|
|
53
|
+
hndl;
|
|
54
|
+
_dropped;
|
|
55
|
+
/** The file descriptor number. */
|
|
56
|
+
fd;
|
|
57
|
+
constructor(guard, hndl) {
|
|
58
|
+
this.guard = guard;
|
|
59
|
+
this.hndl = hndl;
|
|
60
|
+
this.fd = hndl.fd;
|
|
61
|
+
}
|
|
62
|
+
/** The underlying file handle. Throws if the guard has been dropped. */
|
|
63
|
+
get handle() {
|
|
64
|
+
if (this._dropped)
|
|
65
|
+
throw new Error('FileGuard has been dropped');
|
|
66
|
+
return this.hndl;
|
|
67
|
+
}
|
|
68
|
+
/** True if the lock has been released. */
|
|
69
|
+
get dropped() {
|
|
70
|
+
return !!this._dropped;
|
|
71
|
+
}
|
|
72
|
+
/** Release the lock and close the file. Safe to call multiple times. */
|
|
73
|
+
drop() {
|
|
74
|
+
if (!this._dropped) {
|
|
75
|
+
this._dropped = (async () => {
|
|
76
|
+
try {
|
|
77
|
+
await this.guard.drop();
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
await this.hndl.close();
|
|
81
|
+
}
|
|
82
|
+
})();
|
|
83
|
+
}
|
|
84
|
+
return this._dropped;
|
|
85
|
+
}
|
|
86
|
+
[Symbol.asyncDispose]() {
|
|
87
|
+
return this.drop();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
exports.FileLockGuard = FileLockGuard;
|
|
91
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../../lib/core/guard.ts"],"names":[],"mappings":";;;AAAA,yCAAyG;AAEzG;;;;;;;GAOG;AACH,MAAa,SAAS;IAMV;IAEA;IAPF,QAAQ,CAA2B;IAC3C,kCAAkC;IAClB,EAAE,CAAQ;IAE1B,YACU,OAAe,EACvB,MAAS,EACD,KAAiB;QAFjB,YAAO,GAAP,OAAO,CAAQ;QAEf,UAAK,GAAL,KAAK,CAAY;QAEzB,IAAI,CAAC,EAAE,GAAG,IAAA,oBAAS,EAAC,MAAM,CAAC,CAAA;IAC7B,CAAC;IAED,0CAA0C;IAC1C,IAAI,OAAO;QACT,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAA;IACxB,CAAC;IAED,qDAAqD;IACrD,IAAI;QACF,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAA;QAC5E,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAED,CAAC,MAAM,CAAC,YAAY,CAAC;QACnB,OAAO,IAAI,CAAC,IAAI,EAAE,CAAA;IACpB,CAAC;CACF;AA3BD,8BA2BC;AAED;;;;;;;;;;;GAWG;AACH,MAAa,aAAa;IAMd;IACA;IANF,QAAQ,CAA2B;IAC3C,kCAAkC;IAClB,EAAE,CAAQ;IAE1B,YACU,KAAmB,EACnB,IAAO;QADP,UAAK,GAAL,KAAK,CAAc;QACnB,SAAI,GAAJ,IAAI,CAAG;QAEf,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAA;IACnB,CAAC;IAED,wEAAwE;IACxE,IAAI,MAAM;QACR,IAAI,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAA;QAChE,OAAO,IAAI,CAAC,IAAI,CAAA;IAClB,CAAC;IAED,0CAA0C;IAC1C,IAAI,OAAO;QACT,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAA;IACxB,CAAC;IAED,wEAAwE;IACxE,IAAI;QACF,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,GAAG,CAAC,KAAK,IAAI,EAAE;gBAC1B,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAA;gBACzB,CAAC;wBAAS,CAAC;oBACT,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA;gBACzB,CAAC;YACH,CAAC,CAAC,EAAE,CAAA;QACN,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAED,CAAC,MAAM,CAAC,YAAY,CAAC;QACnB,OAAO,IAAI,CAAC,IAAI,EAAE,CAAA;IACpB,CAAC;CACF;AAxCD,sCAwCC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Locker, type Fs } from './types.js';
|
|
2
|
+
export { type Fs as Backend, type LockRange, type PollOptions, Lock, type FileDescriptor, type FileHandle, type Locker, type Fs, } from './types.js';
|
|
3
|
+
export * from './locking.js';
|
|
4
|
+
export * from './guard.js';
|
|
5
|
+
export * from './node.js';
|
|
6
|
+
export declare const defaultFs: () => Fs<import("node:fs/promises").FileHandle>;
|
|
7
|
+
export declare const defaultLocking: () => Locker;
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/core/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,YAAY,CAAA;AAG5C,OAAO,EACL,KAAK,EAAE,IAAI,OAAO,EAClB,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,IAAI,EACJ,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,MAAM,EACX,KAAK,EAAE,GACR,MAAM,YAAY,CAAA;AACnB,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AAIzB,eAAO,MAAM,SAAS,iDAGrB,CAAA;AAID,eAAO,MAAM,cAAc,cAG1B,CAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.defaultLocking = exports.defaultFs = exports.Lock = void 0;
|
|
18
|
+
const node_js_1 = require("./node.js");
|
|
19
|
+
const locking_js_1 = require("./locking.js");
|
|
20
|
+
var types_js_1 = require("./types.js");
|
|
21
|
+
Object.defineProperty(exports, "Lock", { enumerable: true, get: function () { return types_js_1.Lock; } });
|
|
22
|
+
__exportStar(require("./locking.js"), exports);
|
|
23
|
+
__exportStar(require("./guard.js"), exports);
|
|
24
|
+
__exportStar(require("./node.js"), exports);
|
|
25
|
+
/** Lazily create and return the shared default Node.js filesystem singleton. */
|
|
26
|
+
let _defaultFs;
|
|
27
|
+
const defaultFs = () => {
|
|
28
|
+
if (!_defaultFs)
|
|
29
|
+
_defaultFs = (0, node_js_1.createNodeFs)();
|
|
30
|
+
return _defaultFs;
|
|
31
|
+
};
|
|
32
|
+
exports.defaultFs = defaultFs;
|
|
33
|
+
/** Lazily create and return the shared default native locker singleton. */
|
|
34
|
+
let _defaultLocking;
|
|
35
|
+
const defaultLocking = () => {
|
|
36
|
+
if (!_defaultLocking)
|
|
37
|
+
_defaultLocking = (0, locking_js_1.createLocker)(new node_js_1.NodeLockHooks());
|
|
38
|
+
return _defaultLocking;
|
|
39
|
+
};
|
|
40
|
+
exports.defaultLocking = defaultLocking;
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../lib/core/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,uCAA4E;AAE5E,6CAA2C;AAE3C,uCASmB;AALjB,gGAAA,IAAI,OAAA;AAMN,+CAA4B;AAC5B,6CAA0B;AAC1B,4CAAyB;AAEzB,gFAAgF;AAChF,IAAI,UAA0C,CAAA;AACvC,MAAM,SAAS,GAAG,GAAG,EAAE;IAC5B,IAAI,CAAC,UAAU;QAAE,UAAU,GAAG,IAAA,sBAAY,GAAE,CAAA;IAC5C,OAAO,UAAU,CAAA;AACnB,CAAC,CAAA;AAHY,QAAA,SAAS,aAGrB;AAED,2EAA2E;AAC3E,IAAI,eAAmC,CAAA;AAChC,MAAM,cAAc,GAAG,GAAG,EAAE;IACjC,IAAI,CAAC,eAAe;QAAE,eAAe,GAAG,IAAA,yBAAY,EAAC,IAAI,uBAAa,EAAE,CAAC,CAAA;IACzE,OAAO,eAAe,CAAA;AACxB,CAAC,CAAA;AAHY,QAAA,cAAc,kBAG1B"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type FileDescriptor, type Locker } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Lifecycle hooks called when locks are acquired and released.
|
|
4
|
+
* Used by backends to track active locks for cleanup on exit or signals.
|
|
5
|
+
*/
|
|
6
|
+
export interface LockHooks {
|
|
7
|
+
/** Called after a lock is successfully acquired. */
|
|
8
|
+
register: (fd: FileDescriptor) => Promise<void>;
|
|
9
|
+
/** Called when a lock is released (even if unlock itself fails). */
|
|
10
|
+
unregister: (fd: FileDescriptor) => Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Create a {@link Locker} backed by native OS locks.
|
|
14
|
+
*
|
|
15
|
+
* Whole-file locks use `flock(2)` on Unix and `LockFileEx` on Windows.
|
|
16
|
+
* Range locks use `fcntl(2)` OFD locks on Linux, POSIX record locks on
|
|
17
|
+
* macOS/BSD, and ranged `LockFileEx` on Windows.
|
|
18
|
+
*
|
|
19
|
+
* If `hooks` are provided they are called after lock acquisition and on
|
|
20
|
+
* release, allowing backends to track active locks for cleanup.
|
|
21
|
+
*/
|
|
22
|
+
export declare const createLocker: (hooks?: LockHooks) => Locker;
|
|
23
|
+
//# sourceMappingURL=locking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locking.d.ts","sourceRoot":"","sources":["../../../lib/core/locking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,cAAc,EAAE,KAAK,MAAM,EAAmB,MAAM,YAAY,CAAA;AAGhH;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,QAAQ,EAAE,CAAC,EAAE,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/C,oEAAoE;IACpE,UAAU,EAAE,CAAC,EAAE,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAClD;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,QAAQ,SAAS,KAAG,MAqC/C,CAAA"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.createLocker = void 0;
|
|
37
|
+
const types_js_1 = require("./types.js");
|
|
38
|
+
const native = __importStar(require("#native"));
|
|
39
|
+
/**
|
|
40
|
+
* Create a {@link Locker} backed by native OS locks.
|
|
41
|
+
*
|
|
42
|
+
* Whole-file locks use `flock(2)` on Unix and `LockFileEx` on Windows.
|
|
43
|
+
* Range locks use `fcntl(2)` OFD locks on Linux, POSIX record locks on
|
|
44
|
+
* macOS/BSD, and ranged `LockFileEx` on Windows.
|
|
45
|
+
*
|
|
46
|
+
* If `hooks` are provided they are called after lock acquisition and on
|
|
47
|
+
* release, allowing backends to track active locks for cleanup.
|
|
48
|
+
*/
|
|
49
|
+
const createLocker = (hooks) => ({
|
|
50
|
+
async lock(fd, type, range, options) {
|
|
51
|
+
const d = (0, types_js_1.resolveFd)(fd);
|
|
52
|
+
await native.lock(d, toNativeLock(type), range, options);
|
|
53
|
+
try {
|
|
54
|
+
await hooks?.register(d);
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
try {
|
|
58
|
+
native.lockSync(d, native.Lock.Unlock, range);
|
|
59
|
+
}
|
|
60
|
+
catch { }
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
async tryLock(fd, type, range) {
|
|
65
|
+
const d = (0, types_js_1.resolveFd)(fd);
|
|
66
|
+
const locked = await native.tryLock(d, toNativeLock(type), range);
|
|
67
|
+
if (!locked)
|
|
68
|
+
return false;
|
|
69
|
+
try {
|
|
70
|
+
await hooks?.register(d);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
try {
|
|
75
|
+
native.lockSync(d, native.Lock.Unlock, range);
|
|
76
|
+
}
|
|
77
|
+
catch { }
|
|
78
|
+
throw err;
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
async unlock(fd, range) {
|
|
82
|
+
const d = (0, types_js_1.resolveFd)(fd);
|
|
83
|
+
try {
|
|
84
|
+
native.lockSync(d, native.Lock.Unlock, range);
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
await hooks?.unregister(d);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
exports.createLocker = createLocker;
|
|
92
|
+
const toNativeLock = (type) => (type === types_js_1.Lock.Exclusive ? native.Lock.Exclusive : native.Lock.Shared);
|
|
93
|
+
//# sourceMappingURL=locking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locking.js","sourceRoot":"","sources":["../../../lib/core/locking.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yCAAgH;AAChH,gDAAiC;AAajC;;;;;;;;;GASG;AACI,MAAM,YAAY,GAAG,CAAC,KAAiB,EAAU,EAAE,CAAC,CAAC;IAC1D,KAAK,CAAC,IAAI,CAAC,EAAkB,EAAE,IAAU,EAAE,KAAiB,EAAE,OAAqB;QACjF,MAAM,CAAC,GAAG,IAAA,oBAAS,EAAC,EAAE,CAAC,CAAA;QACvB,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAA;QACxD,IAAI,CAAC;YACH,MAAM,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAA;QAC1B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;YAC/C,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YACV,MAAM,GAAG,CAAA;QACX,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAkB,EAAE,IAAU,EAAE,KAAiB;QAC7D,MAAM,CAAC,GAAG,IAAA,oBAAS,EAAC,EAAE,CAAC,CAAA;QACvB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAA;QACjE,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAA;QACzB,IAAI,CAAC;YACH,MAAM,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAA;YACxB,OAAO,IAAI,CAAA;QACb,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;YAC/C,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YACV,MAAM,GAAG,CAAA;QACX,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAkB,EAAE,KAAiB;QAChD,MAAM,CAAC,GAAG,IAAA,oBAAS,EAAC,EAAE,CAAC,CAAA;QACvB,IAAI,CAAC;YACH,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QAC/C,CAAC;gBAAS,CAAC;YACT,MAAM,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;QAC5B,CAAC;IACH,CAAC;CACF,CAAC,CAAA;AArCW,QAAA,YAAY,gBAqCvB;AAEF,MAAM,YAAY,GAAG,CAAC,IAAU,EAAe,EAAE,CAAC,CAAC,IAAI,KAAK,eAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { type Fs, FileDescriptor } from './types.js';
|
|
3
|
+
import { type LockHooks } from './locking.js';
|
|
4
|
+
/** Node.js file handle type alias. */
|
|
5
|
+
export type NodeFileHandle = fs.promises.FileHandle;
|
|
6
|
+
/** Create a Node.js filesystem that opens files with appropriate flags for the lock type. */
|
|
7
|
+
export declare const createNodeFs: () => Fs<NodeFileHandle>;
|
|
8
|
+
/**
|
|
9
|
+
* Track active locks by file descriptor and ensure they are released on process exit.
|
|
10
|
+
*/
|
|
11
|
+
export declare class NodeLockHooks implements LockHooks {
|
|
12
|
+
private _active;
|
|
13
|
+
register(fd: FileDescriptor): Promise<void>;
|
|
14
|
+
unregister(fd: FileDescriptor): Promise<void>;
|
|
15
|
+
private _listen;
|
|
16
|
+
private _unlisten;
|
|
17
|
+
private _onExit;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../lib/core/node.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,SAAS,CAAA;AAExB,OAAO,EAAE,KAAK,EAAE,EAAQ,cAAc,EAAa,MAAM,YAAY,CAAA;AACrE,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,sCAAsC;AACtC,MAAM,MAAM,cAAc,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAA;AAEnD,6FAA6F;AAC7F,eAAO,MAAM,YAAY,QAAO,EAAE,CAAC,cAAc,CAQhD,CAAA;AAED;;GAEG;AACH,qBAAa,aAAc,YAAW,SAAS;IAC7C,OAAO,CAAC,OAAO,CAA4B;IAErC,QAAQ,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3C,UAAU,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAWnD,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,OAAO,CASd;CACF"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.NodeLockHooks = exports.createNodeFs = void 0;
|
|
7
|
+
const node_worker_threads_1 = require("node:worker_threads");
|
|
8
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
+
const types_js_1 = require("./types.js");
|
|
10
|
+
/** Create a Node.js filesystem that opens files with appropriate flags for the lock type. */
|
|
11
|
+
const createNodeFs = () => {
|
|
12
|
+
return {
|
|
13
|
+
async open(file, type) {
|
|
14
|
+
const flags = type === types_js_1.Lock.Exclusive ? node_fs_1.default.constants.O_CREAT | node_fs_1.default.constants.O_RDWR : node_fs_1.default.constants.O_RDONLY;
|
|
15
|
+
const handle = await node_fs_1.default.promises.open(file, flags);
|
|
16
|
+
return handle;
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
exports.createNodeFs = createNodeFs;
|
|
21
|
+
/**
|
|
22
|
+
* Track active locks by file descriptor and ensure they are released on process exit.
|
|
23
|
+
*/
|
|
24
|
+
class NodeLockHooks {
|
|
25
|
+
_active = new Map();
|
|
26
|
+
async register(fd) {
|
|
27
|
+
if (this._active.size === 0)
|
|
28
|
+
this._listen();
|
|
29
|
+
const d = (0, types_js_1.resolveFd)(fd);
|
|
30
|
+
this._active.set(d, (this._active.get(d) ?? 0) + 1);
|
|
31
|
+
}
|
|
32
|
+
async unregister(fd) {
|
|
33
|
+
const d = (0, types_js_1.resolveFd)(fd);
|
|
34
|
+
const count = this._active.get(d);
|
|
35
|
+
if (count !== undefined) {
|
|
36
|
+
if (count <= 1)
|
|
37
|
+
this._active.delete(d);
|
|
38
|
+
else
|
|
39
|
+
this._active.set(d, count - 1);
|
|
40
|
+
}
|
|
41
|
+
if (this._active.size === 0)
|
|
42
|
+
this._unlisten();
|
|
43
|
+
}
|
|
44
|
+
_listen() {
|
|
45
|
+
if (node_worker_threads_1.isMainThread)
|
|
46
|
+
process.on('exit', this._onExit);
|
|
47
|
+
else
|
|
48
|
+
node_worker_threads_1.parentPort?.on('close', this._onExit);
|
|
49
|
+
}
|
|
50
|
+
_unlisten() {
|
|
51
|
+
if (node_worker_threads_1.isMainThread)
|
|
52
|
+
process.off('exit', this._onExit);
|
|
53
|
+
else
|
|
54
|
+
node_worker_threads_1.parentPort?.off('close', this._onExit);
|
|
55
|
+
}
|
|
56
|
+
_onExit = () => {
|
|
57
|
+
for (const fd of Array.from(this._active.keys()).reverse()) {
|
|
58
|
+
try {
|
|
59
|
+
node_fs_1.default.closeSync(fd);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// EBADF expected if already closed
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
this._active.clear();
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
exports.NodeLockHooks = NodeLockHooks;
|
|
69
|
+
//# sourceMappingURL=node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../../lib/core/node.ts"],"names":[],"mappings":";;;;;;AAAA,6DAA8D;AAC9D,sDAAwB;AAExB,yCAAqE;AAMrE,6FAA6F;AACtF,MAAM,YAAY,GAAG,GAAuB,EAAE;IACnD,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,IAAY,EAAE,IAAU;YACjC,MAAM,KAAK,GAAG,IAAI,KAAK,eAAI,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAE,CAAC,SAAS,CAAC,OAAO,GAAG,iBAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,iBAAE,CAAC,SAAS,CAAC,QAAQ,CAAA;YAC1G,MAAM,MAAM,GAAG,MAAM,iBAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;YAClD,OAAO,MAAM,CAAA;QACf,CAAC;KACF,CAAA;AACH,CAAC,CAAA;AARY,QAAA,YAAY,gBAQxB;AAED;;GAEG;AACH,MAAa,aAAa;IAChB,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAA;IAE3C,KAAK,CAAC,QAAQ,CAAC,EAAkB;QAC/B,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC;YAAE,IAAI,CAAC,OAAO,EAAE,CAAA;QAC3C,MAAM,CAAC,GAAG,IAAA,oBAAS,EAAC,EAAE,CAAC,CAAA;QACvB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACrD,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAkB;QACjC,MAAM,CAAC,GAAG,IAAA,oBAAS,EAAC,EAAE,CAAC,CAAA;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QACjC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,IAAI,KAAK,IAAI,CAAC;gBAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;;gBACjC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAA;QACrC,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC;YAAE,IAAI,CAAC,SAAS,EAAE,CAAA;IAC/C,CAAC;IAEO,OAAO;QACb,IAAI,kCAAY;YAAE,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;;YAC7C,gCAAU,EAAE,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IAC5C,CAAC;IAEO,SAAS;QACf,IAAI,kCAAY;YAAE,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;;YAC9C,gCAAU,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IAC7C,CAAC;IAEO,OAAO,GAAG,GAAS,EAAE;QAC3B,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;YAC3D,IAAI,CAAC;gBACH,iBAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;YAClB,CAAC;YAAC,MAAM,CAAC;gBACP,mCAAmC;YACrC,CAAC;QACH,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;IACtB,CAAC,CAAA;CACF;AAxCD,sCAwCC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** Filesystem abstraction for opening lock files. */
|
|
2
|
+
export interface Fs<H extends FileHandle> {
|
|
3
|
+
/** Open (or create) the lock file and return a handle. */
|
|
4
|
+
open(file: string, type: Lock): Promise<H>;
|
|
5
|
+
}
|
|
6
|
+
/** Lock/unlock operations, separated from file opening for composability. */
|
|
7
|
+
export interface Locker {
|
|
8
|
+
/** Acquire a lock, polling until available or timeout is reached. */
|
|
9
|
+
lock: (fd: FileDescriptor, type: Lock, range?: LockRange, options?: PollOptions) => Promise<void>;
|
|
10
|
+
/** Try to acquire a lock without waiting. Return true if acquired. */
|
|
11
|
+
tryLock: (fd: FileDescriptor, type: Lock, range?: LockRange) => Promise<boolean>;
|
|
12
|
+
/** Release a previously acquired lock. */
|
|
13
|
+
unlock: (fd: FileDescriptor, range?: LockRange) => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
/** Lock mode: exclusive (write) or shared (read). */
|
|
16
|
+
export declare enum Lock {
|
|
17
|
+
Exclusive = 0,
|
|
18
|
+
Shared = 1
|
|
19
|
+
}
|
|
20
|
+
/** Options for polling lock acquisition. */
|
|
21
|
+
export interface PollOptions {
|
|
22
|
+
/** Polling interval in milliseconds. */
|
|
23
|
+
pollMs?: number;
|
|
24
|
+
/** Maximum wait time in milliseconds. */
|
|
25
|
+
timeout?: number;
|
|
26
|
+
/** Multiplier applied to pollMs after each failed attempt (e.g. 2 = exponential backoff). */
|
|
27
|
+
backoff?: number;
|
|
28
|
+
}
|
|
29
|
+
/** Byte range within a file to lock. Used for range-level locking. */
|
|
30
|
+
export interface LockRange {
|
|
31
|
+
/** Starting byte offset. */
|
|
32
|
+
offset: number;
|
|
33
|
+
/** Number of bytes to lock. */
|
|
34
|
+
length: number;
|
|
35
|
+
}
|
|
36
|
+
/** An open file handle with a descriptor and a close method. */
|
|
37
|
+
export interface FileHandle {
|
|
38
|
+
/** The numeric file descriptor. */
|
|
39
|
+
fd: number;
|
|
40
|
+
/** Close the file handle. */
|
|
41
|
+
close: () => Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
/** File descriptor or file descriptor object. */
|
|
44
|
+
export type FileDescriptor = {
|
|
45
|
+
fd: number;
|
|
46
|
+
} | number;
|
|
47
|
+
/** @internal */
|
|
48
|
+
export declare const resolveFd: (fd: FileDescriptor) => number;
|
|
49
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../lib/core/types.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,MAAM,WAAW,EAAE,CAAC,CAAC,SAAS,UAAU;IACtC,0DAA0D;IAC1D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;CAC3C;AAED,6EAA6E;AAC7E,MAAM,WAAW,MAAM;IACrB,qEAAqE;IACrE,IAAI,EAAE,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjG,sEAAsE;IACtE,OAAO,EAAE,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,SAAS,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAChF,0CAA0C;IAC1C,MAAM,EAAE,CAAC,EAAE,EAAE,cAAc,EAAE,KAAK,CAAC,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACjE;AAED,qDAAqD;AACrD,oBAAY,IAAI;IACd,SAAS,IAAA;IACT,MAAM,IAAA;CACP;AAED,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6FAA6F;IAC7F,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,sEAAsE;AACtE,MAAM,WAAW,SAAS;IACxB,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAA;CACf;AAED,gEAAgE;AAChE,MAAM,WAAW,UAAU;IACzB,mCAAmC;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,6BAA6B;IAC7B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B;AAED,iDAAiD;AACjD,MAAM,MAAM,cAAc,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAA;AAEpD,gBAAgB;AAChB,eAAO,MAAM,SAAS,GAAI,IAAI,cAAc,KAAG,MAA+C,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveFd = exports.Lock = void 0;
|
|
4
|
+
/** Lock mode: exclusive (write) or shared (read). */
|
|
5
|
+
var Lock;
|
|
6
|
+
(function (Lock) {
|
|
7
|
+
Lock[Lock["Exclusive"] = 0] = "Exclusive";
|
|
8
|
+
Lock[Lock["Shared"] = 1] = "Shared";
|
|
9
|
+
})(Lock || (exports.Lock = Lock = {}));
|
|
10
|
+
/** @internal */
|
|
11
|
+
const resolveFd = (fd) => (typeof fd === 'number' ? fd : fd.fd);
|
|
12
|
+
exports.resolveFd = resolveFd;
|
|
13
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../lib/core/types.ts"],"names":[],"mappings":";;;AAgBA,qDAAqD;AACrD,IAAY,IAGX;AAHD,WAAY,IAAI;IACd,yCAAS,CAAA;IACT,mCAAM,CAAA;AACR,CAAC,EAHW,IAAI,oBAAJ,IAAI,QAGf;AA+BD,gBAAgB;AACT,MAAM,SAAS,GAAG,CAAC,EAAkB,EAAU,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;AAAjF,QAAA,SAAS,aAAwE"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type NodeFileHandle, type LockRange, type PollOptions, type Lock, type FileHandle, type FileDescriptor, type Fs, type Locker, FileLockGuard, LockGuard } from './core/index.js';
|
|
2
|
+
export * from './core/index.js';
|
|
3
|
+
/** Options for specifying a custom locker and/or byte range. */
|
|
4
|
+
export interface LockingOptions {
|
|
5
|
+
/** Custom locker implementation. Uses the default native locker if omitted. */
|
|
6
|
+
locking?: Locker;
|
|
7
|
+
/** Byte range to lock. Locks the entire file if omitted. */
|
|
8
|
+
range?: LockRange;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Acquire a lock on an already-open file handle.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* import fs from 'node:fs/promises'
|
|
15
|
+
* const handle = await fs.open('/tmp/my.lock', 'r+')
|
|
16
|
+
* await using guard = await lock(handle, Lock.Exclusive)
|
|
17
|
+
*/
|
|
18
|
+
export declare const lock: <H extends FileHandle = NodeFileHandle>(handle: H, type: Lock, options?: LockingOptions & PollOptions) => Promise<LockGuard<H>>;
|
|
19
|
+
/**
|
|
20
|
+
* Try to acquire a lock on an already-open file handle without waiting.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* import fs from 'node:fs/promises'
|
|
24
|
+
* const handle = await fs.open('/tmp/my.lock', 'r+')
|
|
25
|
+
* const guard = await tryLock(handle, Lock.Exclusive)
|
|
26
|
+
* if (guard) { /* acquired *\/ }
|
|
27
|
+
*/
|
|
28
|
+
export declare const tryLock: <H extends FileDescriptor>(handle: H, type: Lock, options?: LockingOptions & PollOptions) => Promise<LockGuard<H> | undefined>;
|
|
29
|
+
/**
|
|
30
|
+
* Release a lock on a file descriptor or file handle.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* import fs from 'node:fs/promises'
|
|
34
|
+
* const handle = await fs.open('/tmp/my.lock', 'r+')
|
|
35
|
+
* await lock(handle, Lock.Exclusive)
|
|
36
|
+
* // ... critical section ...
|
|
37
|
+
* await unlock(handle)
|
|
38
|
+
*/
|
|
39
|
+
export declare const unlock: <H extends FileDescriptor>(handle: H, options?: LockingOptions) => Promise<void>;
|
|
40
|
+
/** Options for open-and-lock functions that manage the file lifecycle. */
|
|
41
|
+
export interface OpenLockOptions<H extends FileHandle> extends LockingOptions {
|
|
42
|
+
/** Custom filesystem for opening files. Uses the default Node.js fs if omitted. */
|
|
43
|
+
fs?: Fs<H>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Open a file and acquire a lock, polling until available. Closes the file on failure.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* await using guard = await openLock('/tmp/my.lock', Lock.Exclusive)
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* await using guard = await openLock('/tmp/my.lock', Lock.Shared, { timeout: 5000 })
|
|
53
|
+
*/
|
|
54
|
+
export declare const openLock: <H extends FileHandle = NodeFileHandle>(file: string, type: Lock, options?: OpenLockOptions<H> & PollOptions) => Promise<FileLockGuard<H>>;
|
|
55
|
+
/**
|
|
56
|
+
* Open a file and try to acquire a lock without waiting. Closes the file if not acquired.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* const guard = await tryOpenLock('/tmp/my.lock', Lock.Exclusive)
|
|
60
|
+
* if (guard) { /* acquired *\/ }
|
|
61
|
+
*/
|
|
62
|
+
export declare const tryOpenLock: <H extends FileHandle = NodeFileHandle>(file: string, type: Lock, options?: OpenLockOptions<H>) => Promise<FileLockGuard<H> | undefined>;
|
|
63
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,IAAI,EACT,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,EAAE,EACP,KAAK,MAAM,EACX,aAAa,EACb,SAAS,EAGV,MAAM,iBAAiB,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAE/B,gEAAgE;AAChE,MAAM,WAAW,cAAc;IAC7B,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,GAAU,CAAC,SAAS,UAAU,GAAG,cAAc,EAC9D,QAAQ,CAAC,EACT,MAAM,IAAI,EACV,UAAU,cAAc,GAAG,WAAW,KACrC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAItB,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,GAAU,CAAC,SAAS,cAAc,EACpD,QAAQ,CAAC,EACT,MAAM,IAAI,EACV,UAAU,cAAc,GAAG,WAAW,KACrC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAKlC,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM,GAAU,CAAC,SAAS,cAAc,EAAE,QAAQ,CAAC,EAAE,UAAU,cAAc,KAAG,OAAO,CAAC,IAAI,CAGxG,CAAA;AAED,0EAA0E;AAC1E,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,UAAU,CAAE,SAAQ,cAAc;IAC3E,mFAAmF;IACnF,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAA;CACX;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,QAAQ,GAAU,CAAC,SAAS,UAAU,GAAG,cAAc,EAClE,MAAM,MAAM,EACZ,MAAM,IAAI,EACV,UAAU,eAAe,CAAC,CAAC,CAAC,GAAG,WAAW,KACzC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAS1B,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,GAAU,CAAC,SAAS,UAAU,GAAG,cAAc,EACrE,MAAM,MAAM,EACZ,MAAM,IAAI,EACV,UAAU,eAAe,CAAC,CAAC,CAAC,KAC3B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,SAAS,CAYtC,CAAA"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.tryOpenLock = exports.openLock = exports.unlock = exports.tryLock = exports.lock = void 0;
|
|
18
|
+
const index_js_1 = require("./core/index.js");
|
|
19
|
+
__exportStar(require("./core/index.js"), exports);
|
|
20
|
+
/**
|
|
21
|
+
* Acquire a lock on an already-open file handle.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* import fs from 'node:fs/promises'
|
|
25
|
+
* const handle = await fs.open('/tmp/my.lock', 'r+')
|
|
26
|
+
* await using guard = await lock(handle, Lock.Exclusive)
|
|
27
|
+
*/
|
|
28
|
+
const lock = async (handle, type, options) => {
|
|
29
|
+
const { locking = (0, index_js_1.defaultLocking)() } = options ?? {};
|
|
30
|
+
await locking.lock(handle, type, options?.range, options);
|
|
31
|
+
return new index_js_1.LockGuard(locking, handle, options?.range);
|
|
32
|
+
};
|
|
33
|
+
exports.lock = lock;
|
|
34
|
+
/**
|
|
35
|
+
* Try to acquire a lock on an already-open file handle without waiting.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* import fs from 'node:fs/promises'
|
|
39
|
+
* const handle = await fs.open('/tmp/my.lock', 'r+')
|
|
40
|
+
* const guard = await tryLock(handle, Lock.Exclusive)
|
|
41
|
+
* if (guard) { /* acquired *\/ }
|
|
42
|
+
*/
|
|
43
|
+
const tryLock = async (handle, type, options) => {
|
|
44
|
+
const { locking = (0, index_js_1.defaultLocking)() } = options ?? {};
|
|
45
|
+
const result = await locking.tryLock(handle, type, options?.range);
|
|
46
|
+
if (result)
|
|
47
|
+
return new index_js_1.LockGuard(locking, handle, options?.range);
|
|
48
|
+
return undefined;
|
|
49
|
+
};
|
|
50
|
+
exports.tryLock = tryLock;
|
|
51
|
+
/**
|
|
52
|
+
* Release a lock on a file descriptor or file handle.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* import fs from 'node:fs/promises'
|
|
56
|
+
* const handle = await fs.open('/tmp/my.lock', 'r+')
|
|
57
|
+
* await lock(handle, Lock.Exclusive)
|
|
58
|
+
* // ... critical section ...
|
|
59
|
+
* await unlock(handle)
|
|
60
|
+
*/
|
|
61
|
+
const unlock = async (handle, options) => {
|
|
62
|
+
const { locking = (0, index_js_1.defaultLocking)() } = options ?? {};
|
|
63
|
+
await locking.unlock(handle, options?.range);
|
|
64
|
+
};
|
|
65
|
+
exports.unlock = unlock;
|
|
66
|
+
/**
|
|
67
|
+
* Open a file and acquire a lock, polling until available. Closes the file on failure.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* await using guard = await openLock('/tmp/my.lock', Lock.Exclusive)
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* await using guard = await openLock('/tmp/my.lock', Lock.Shared, { timeout: 5000 })
|
|
74
|
+
*/
|
|
75
|
+
const openLock = async (file, type, options) => {
|
|
76
|
+
const { fs = (0, index_js_1.defaultFs)() } = options ?? {};
|
|
77
|
+
const handle = await fs.open(file, type);
|
|
78
|
+
try {
|
|
79
|
+
return new index_js_1.FileLockGuard(await (0, exports.lock)(handle, type, options), handle);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
await handle.close();
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
exports.openLock = openLock;
|
|
87
|
+
/**
|
|
88
|
+
* Open a file and try to acquire a lock without waiting. Closes the file if not acquired.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* const guard = await tryOpenLock('/tmp/my.lock', Lock.Exclusive)
|
|
92
|
+
* if (guard) { /* acquired *\/ }
|
|
93
|
+
*/
|
|
94
|
+
const tryOpenLock = async (file, type, options) => {
|
|
95
|
+
const { fs = (0, index_js_1.defaultFs)() } = options ?? {};
|
|
96
|
+
const handle = await fs.open(file, type);
|
|
97
|
+
try {
|
|
98
|
+
const result = await (0, exports.tryLock)(handle, type, options);
|
|
99
|
+
if (result)
|
|
100
|
+
return new index_js_1.FileLockGuard(result, handle);
|
|
101
|
+
await handle.close();
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
await handle.close();
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
exports.tryOpenLock = tryOpenLock;
|
|
110
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../lib/index.ts"],"names":[],"mappings":"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"}
|