@oh-my-pi/pi-utils 18.1.17 → 18.1.19
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/CHANGELOG.md +10 -0
- package/dist/types/file-lock.d.ts +6 -0
- package/package.json +2 -2
- package/src/env.ts +1 -1
- package/src/file-lock.ts +8 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.1.19] - 2026-09-12
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added public `acquireFileLock()` and `FileLockHandle` APIs for holding and explicitly releasing exclusive OS-backed file locks.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Child-shell environment filtering now tolerates a removed process working directory by retaining the resolved project directory ([#11828](https://github.com/can1357/oh-my-pi/issues/11828)).
|
|
14
|
+
|
|
5
15
|
## [18.1.16] - 2026-09-09
|
|
6
16
|
|
|
7
17
|
### Fixed
|
|
@@ -6,8 +6,14 @@ export interface FileLockOptions {
|
|
|
6
6
|
/** Delay between acquisition attempts. */
|
|
7
7
|
retryDelayMs?: number;
|
|
8
8
|
}
|
|
9
|
+
/** An exclusive OS-backed lease. Releasing an already released handle is safe. */
|
|
10
|
+
export interface FileLockHandle {
|
|
11
|
+
release(): void;
|
|
12
|
+
}
|
|
9
13
|
declare function getLockPath(filePath: string): string;
|
|
10
14
|
declare function tryAcquireLock(lockPath: string): NativeFileLock | null;
|
|
15
|
+
/** Acquire an exclusive lease; callers must release it when their operation ends. */
|
|
16
|
+
export declare function acquireFileLock(filePath: string, options?: FileLockOptions): Promise<FileLockHandle>;
|
|
11
17
|
/** Run `fn` while holding an OS-backed exclusive lock for `filePath`. */
|
|
12
18
|
export declare function withFileLock<T>(filePath: string, fn: () => Promise<T>, options?: FileLockOptions): Promise<T>;
|
|
13
19
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-utils",
|
|
3
|
-
"version": "18.1.
|
|
3
|
+
"version": "18.1.19",
|
|
4
4
|
"description": "Shared utilities for pi packages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@oh-my-pi/pi-natives": "18.1.
|
|
57
|
+
"@oh-my-pi/pi-natives": "18.1.19"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@types/bun": "^1.3.14"
|
package/src/env.ts
CHANGED
|
@@ -110,7 +110,7 @@ function expandDotenvValues(values: Record<string, string>, env: Record<string,
|
|
|
110
110
|
/** Filters process env for child shells without launch-cwd dotenv values. */
|
|
111
111
|
export function filterChildShellEnv(
|
|
112
112
|
env: Record<string, string | undefined>,
|
|
113
|
-
cwd: string =
|
|
113
|
+
cwd: string = getProjectDir(),
|
|
114
114
|
): Record<string, string> {
|
|
115
115
|
const runtimeLaunchEnvValues = env === Bun.env || env === process.env ? launchEnvValues : undefined;
|
|
116
116
|
const result = filterProcessEnv(env);
|
package/src/file-lock.ts
CHANGED
|
@@ -15,6 +15,11 @@ export interface FileLockOptions {
|
|
|
15
15
|
retryDelayMs?: number;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/** An exclusive OS-backed lease. Releasing an already released handle is safe. */
|
|
19
|
+
export interface FileLockHandle {
|
|
20
|
+
release(): void;
|
|
21
|
+
}
|
|
22
|
+
|
|
18
23
|
const DEFAULT_OPTIONS: Required<FileLockOptions> = {
|
|
19
24
|
retries: 50,
|
|
20
25
|
retryDelayMs: 100,
|
|
@@ -29,7 +34,8 @@ function tryAcquireLock(lockPath: string): NativeFileLock | null {
|
|
|
29
34
|
return lock.acquired ? lock : null;
|
|
30
35
|
}
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
/** Acquire an exclusive lease; callers must release it when their operation ends. */
|
|
38
|
+
export async function acquireFileLock(filePath: string, options: FileLockOptions = {}): Promise<FileLockHandle> {
|
|
33
39
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
34
40
|
const lockPath = getLockPath(filePath);
|
|
35
41
|
|
|
@@ -48,7 +54,7 @@ export async function withFileLock<T>(
|
|
|
48
54
|
fn: () => Promise<T>,
|
|
49
55
|
options: FileLockOptions = {},
|
|
50
56
|
): Promise<T> {
|
|
51
|
-
const lock = await
|
|
57
|
+
const lock = await acquireFileLock(filePath, options);
|
|
52
58
|
try {
|
|
53
59
|
return await fn();
|
|
54
60
|
} finally {
|