@openclaw/fs-safe 0.14.0 → 0.15.0

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.
Files changed (235) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +10 -4
  3. package/dist/advanced.d.ts +1 -1
  4. package/dist/advanced.d.ts.map +1 -1
  5. package/dist/advanced.js +1 -1
  6. package/dist/archive-merge.d.ts.map +1 -1
  7. package/dist/archive-merge.js +113 -46
  8. package/dist/archive-read.d.ts.map +1 -1
  9. package/dist/archive-read.js +4 -4
  10. package/dist/archive-zip-directory.d.ts +4 -0
  11. package/dist/archive-zip-directory.d.ts.map +1 -1
  12. package/dist/archive-zip-directory.js +2 -0
  13. package/dist/archive-zip-entry.d.ts +6 -2
  14. package/dist/archive-zip-entry.d.ts.map +1 -1
  15. package/dist/archive-zip-entry.js +23 -8
  16. package/dist/archive-zip-integrity.d.ts.map +1 -1
  17. package/dist/archive-zip-integrity.js +3 -4
  18. package/dist/archive-zip-loader.d.ts.map +1 -1
  19. package/dist/archive-zip-loader.js +107 -31
  20. package/dist/archive-zip-names.d.ts +1 -0
  21. package/dist/archive-zip-names.d.ts.map +1 -1
  22. package/dist/archive-zip-names.js +6 -0
  23. package/dist/archive.js +6 -5
  24. package/dist/bounded-read-stream.d.ts +0 -1
  25. package/dist/bounded-read-stream.d.ts.map +1 -1
  26. package/dist/bounded-read-stream.js +0 -6
  27. package/dist/copy-publication.d.ts +6 -0
  28. package/dist/copy-publication.d.ts.map +1 -1
  29. package/dist/copy-publication.js +3 -0
  30. package/dist/copy-tree-portable.d.ts.map +1 -1
  31. package/dist/copy-tree-portable.js +44 -24
  32. package/dist/copy.d.ts.map +1 -1
  33. package/dist/copy.js +29 -11
  34. package/dist/directory-mode-owner.js +5 -5
  35. package/dist/file-handle-transfer.d.ts +2 -0
  36. package/dist/file-handle-transfer.d.ts.map +1 -1
  37. package/dist/file-handle-transfer.js +57 -2
  38. package/dist/file-identity.d.ts.map +1 -1
  39. package/dist/file-identity.js +18 -4
  40. package/dist/file-lock-sync-admission.d.ts +19 -0
  41. package/dist/file-lock-sync-admission.d.ts.map +1 -0
  42. package/dist/file-lock-sync-admission.js +93 -0
  43. package/dist/file-lock-sync-root-acquire.d.ts +4 -0
  44. package/dist/file-lock-sync-root-acquire.d.ts.map +1 -0
  45. package/dist/file-lock-sync-root-acquire.js +370 -0
  46. package/dist/file-lock-sync-root-arbitration.d.ts +18 -0
  47. package/dist/file-lock-sync-root-arbitration.d.ts.map +1 -0
  48. package/dist/file-lock-sync-root-arbitration.js +66 -0
  49. package/dist/file-lock-sync-root-held.d.ts +34 -0
  50. package/dist/file-lock-sync-root-held.d.ts.map +1 -0
  51. package/dist/file-lock-sync-root-held.js +393 -0
  52. package/dist/file-lock-sync-root-io.d.ts +44 -0
  53. package/dist/file-lock-sync-root-io.d.ts.map +1 -0
  54. package/dist/file-lock-sync-root-io.js +209 -0
  55. package/dist/file-lock-sync-root-mutation.d.ts +17 -0
  56. package/dist/file-lock-sync-root-mutation.d.ts.map +1 -0
  57. package/dist/file-lock-sync-root-mutation.js +277 -0
  58. package/dist/file-lock-sync-root-options.d.ts +20 -0
  59. package/dist/file-lock-sync-root-options.d.ts.map +1 -0
  60. package/dist/file-lock-sync-root-options.js +58 -0
  61. package/dist/file-lock-sync-root-registration.d.ts +2 -0
  62. package/dist/file-lock-sync-root-registration.d.ts.map +1 -0
  63. package/dist/file-lock-sync-root-registration.js +90 -0
  64. package/dist/file-lock-sync-root.d.ts +36 -0
  65. package/dist/file-lock-sync-root.d.ts.map +1 -0
  66. package/dist/file-lock-sync-root.js +361 -0
  67. package/dist/file-lock-sync-stale-admission.d.ts +24 -0
  68. package/dist/file-lock-sync-stale-admission.d.ts.map +1 -0
  69. package/dist/file-lock-sync-stale-admission.js +205 -0
  70. package/dist/file-lock-sync.d.ts.map +1 -1
  71. package/dist/file-lock-sync.js +245 -205
  72. package/dist/file-store-prune.d.ts.map +1 -1
  73. package/dist/file-store-prune.js +5 -1
  74. package/dist/file-store-sync-write.js +3 -3
  75. package/dist/file-store.d.ts.map +1 -1
  76. package/dist/file-store.js +47 -12
  77. package/dist/json-document-store.d.ts.map +1 -1
  78. package/dist/json-document-store.js +22 -15
  79. package/dist/json-durable-queue-ownership.d.ts +0 -1
  80. package/dist/json-durable-queue-ownership.d.ts.map +1 -1
  81. package/dist/json-durable-queue-ownership.js +0 -6
  82. package/dist/native-binding.d.ts +2 -0
  83. package/dist/native-binding.d.ts.map +1 -1
  84. package/dist/native-parent-admission.d.ts +3 -2
  85. package/dist/native-parent-admission.d.ts.map +1 -1
  86. package/dist/native-parent-admission.js +24 -5
  87. package/dist/native-pinned-write-windows.d.ts.map +1 -1
  88. package/dist/native-pinned-write-windows.js +7 -7
  89. package/dist/native-pinned-write.d.ts.map +1 -1
  90. package/dist/native-pinned-write.js +7 -11
  91. package/dist/native-policy-parent-windows.d.ts +14 -0
  92. package/dist/native-policy-parent-windows.d.ts.map +1 -0
  93. package/dist/native-policy-parent-windows.js +200 -0
  94. package/dist/native-rename-outcome.d.ts +4 -0
  95. package/dist/native-rename-outcome.d.ts.map +1 -0
  96. package/dist/native-rename-outcome.js +8 -0
  97. package/dist/native-staged-file.d.ts +2 -2
  98. package/dist/native-staged-file.d.ts.map +1 -1
  99. package/dist/native-staged-file.js +42 -40
  100. package/dist/output.d.ts.map +1 -1
  101. package/dist/output.js +12 -8
  102. package/dist/path-prefix.d.ts.map +1 -1
  103. package/dist/path-prefix.js +30 -8
  104. package/dist/path-suffix-aliases.d.ts +2 -0
  105. package/dist/path-suffix-aliases.d.ts.map +1 -1
  106. package/dist/path-suffix-aliases.js +25 -17
  107. package/dist/permission-exec.d.ts +2 -0
  108. package/dist/permission-exec.d.ts.map +1 -1
  109. package/dist/permission-exec.js +150 -21
  110. package/dist/permissions-windows.js +1 -1
  111. package/dist/pinned-mutation-admission.d.ts.map +1 -1
  112. package/dist/pinned-mutation-admission.js +10 -5
  113. package/dist/pinned-mutation-observation.d.ts +0 -1
  114. package/dist/pinned-mutation-observation.d.ts.map +1 -1
  115. package/dist/pinned-mutation-observation.js +0 -19
  116. package/dist/pinned-mutation-shared-route.d.ts +1 -0
  117. package/dist/pinned-mutation-shared-route.d.ts.map +1 -1
  118. package/dist/pinned-mutation-shared-route.js +1 -1
  119. package/dist/pinned-write-types.d.ts +2 -0
  120. package/dist/pinned-write-types.d.ts.map +1 -1
  121. package/dist/private-temp-workspace.d.ts.map +1 -1
  122. package/dist/private-temp-workspace.js +75 -121
  123. package/dist/regular-file.d.ts.map +1 -1
  124. package/dist/regular-file.js +1 -15
  125. package/dist/replace-directory.d.ts.map +1 -1
  126. package/dist/replace-directory.js +256 -18
  127. package/dist/replace-file-copy-fallback.d.ts.map +1 -1
  128. package/dist/replace-file-copy-fallback.js +62 -70
  129. package/dist/replace-file-copy-source.d.ts.map +1 -1
  130. package/dist/replace-file-copy-source.js +10 -12
  131. package/dist/replace-file-temp-owner.d.ts +5 -2
  132. package/dist/replace-file-temp-owner.d.ts.map +1 -1
  133. package/dist/replace-file-temp-owner.js +65 -30
  134. package/dist/replace-file.js +6 -6
  135. package/dist/retained-directory-replacement.d.ts +26 -0
  136. package/dist/retained-directory-replacement.d.ts.map +1 -0
  137. package/dist/retained-directory-replacement.js +193 -0
  138. package/dist/root-boundary.d.ts +1 -0
  139. package/dist/root-boundary.d.ts.map +1 -1
  140. package/dist/root-boundary.js +4 -0
  141. package/dist/root-context.d.ts +0 -8
  142. package/dist/root-context.d.ts.map +1 -1
  143. package/dist/root-context.js +0 -3
  144. package/dist/root-create-input.d.ts +6 -0
  145. package/dist/root-create-input.d.ts.map +1 -1
  146. package/dist/root-create-input.js +5 -1
  147. package/dist/root-directory-list.d.ts +1 -0
  148. package/dist/root-directory-list.d.ts.map +1 -1
  149. package/dist/root-directory-list.js +1 -0
  150. package/dist/root-impl.d.ts.map +1 -1
  151. package/dist/root-impl.js +18 -10
  152. package/dist/root-move-noreplace.d.ts.map +1 -1
  153. package/dist/root-move-noreplace.js +2 -2
  154. package/dist/root-path-errors.d.ts +1 -0
  155. package/dist/root-path-errors.d.ts.map +1 -1
  156. package/dist/root-path-errors.js +11 -2
  157. package/dist/root-path-existing.d.ts.map +1 -1
  158. package/dist/root-path-existing.js +11 -35
  159. package/dist/root-path.js +1 -13
  160. package/dist/root-remove.d.ts +1 -0
  161. package/dist/root-remove.d.ts.map +1 -1
  162. package/dist/root-remove.js +4 -0
  163. package/dist/root-walk.d.ts +1 -1
  164. package/dist/root-walk.d.ts.map +1 -1
  165. package/dist/root-walk.js +17 -2
  166. package/dist/root-write-admission.d.ts +0 -2
  167. package/dist/root-write-admission.d.ts.map +1 -1
  168. package/dist/root-write-admission.js +1 -15
  169. package/dist/root-write-complete-parent.d.ts.map +1 -1
  170. package/dist/root-write-complete-parent.js +7 -23
  171. package/dist/root-write-verification.d.ts.map +1 -1
  172. package/dist/root-write-verification.js +29 -42
  173. package/dist/secret-file.d.ts.map +1 -1
  174. package/dist/secret-file.js +2 -24
  175. package/dist/secret-read-async.d.ts.map +1 -1
  176. package/dist/secret-read-async.js +3 -24
  177. package/dist/secret-read-policy.d.ts +6 -2
  178. package/dist/secret-read-policy.d.ts.map +1 -1
  179. package/dist/secret-read-policy.js +26 -2
  180. package/dist/sibling-temp.d.ts.map +1 -1
  181. package/dist/sibling-temp.js +23 -12
  182. package/dist/sidecar-lock-acquire.d.ts +2 -28
  183. package/dist/sidecar-lock-acquire.d.ts.map +1 -1
  184. package/dist/sidecar-lock-acquire.js +288 -199
  185. package/dist/sidecar-lock-admission-context.d.ts +19 -0
  186. package/dist/sidecar-lock-admission-context.d.ts.map +1 -0
  187. package/dist/sidecar-lock-admission-context.js +60 -0
  188. package/dist/sidecar-lock-admission-parser.d.ts +43 -0
  189. package/dist/sidecar-lock-admission-parser.d.ts.map +1 -0
  190. package/dist/sidecar-lock-admission-parser.js +113 -0
  191. package/dist/sidecar-lock-admission.d.ts +35 -0
  192. package/dist/sidecar-lock-admission.d.ts.map +1 -0
  193. package/dist/sidecar-lock-admission.js +7 -0
  194. package/dist/sidecar-lock-reclaim.d.ts +9 -4
  195. package/dist/sidecar-lock-reclaim.d.ts.map +1 -1
  196. package/dist/sidecar-lock-reclaim.js +80 -25
  197. package/dist/sidecar-lock-stale-admission.d.ts +39 -0
  198. package/dist/sidecar-lock-stale-admission.d.ts.map +1 -0
  199. package/dist/sidecar-lock-stale-admission.js +232 -0
  200. package/dist/sidecar-lock-target.d.ts +8 -0
  201. package/dist/sidecar-lock-target.d.ts.map +1 -0
  202. package/dist/sidecar-lock-target.js +55 -0
  203. package/dist/sidecar-lock.d.ts.map +1 -1
  204. package/dist/sidecar-lock.js +100 -16
  205. package/dist/temp-workspace-descriptor.d.ts.map +1 -1
  206. package/dist/temp-workspace-descriptor.js +9 -27
  207. package/dist/temp-workspace-owner.d.ts.map +1 -1
  208. package/dist/temp-workspace-owner.js +8 -8
  209. package/dist/walk.d.ts +5 -1
  210. package/dist/walk.d.ts.map +1 -1
  211. package/dist/walk.js +19 -6
  212. package/dist/windows-owner.d.ts.map +1 -1
  213. package/dist/windows-owner.js +2 -2
  214. package/docs/advanced.md +1 -1
  215. package/docs/archive.md +36 -9
  216. package/docs/atomic.md +85 -8
  217. package/docs/copy.md +35 -0
  218. package/docs/file-store.md +19 -0
  219. package/docs/json-store.md +5 -0
  220. package/docs/native-helper.md +10 -3
  221. package/docs/output.md +6 -0
  222. package/docs/path-prefix.md +10 -0
  223. package/docs/path-suffix-aliases.md +51 -6
  224. package/docs/permissions.md +13 -0
  225. package/docs/public-api.md +3 -2
  226. package/docs/root.md +22 -3
  227. package/docs/sidecar-lock.md +109 -4
  228. package/docs/staged-file.md +7 -3
  229. package/docs/temp.md +20 -3
  230. package/docs/walk.md +67 -1
  231. package/docs/writing.md +5 -1
  232. package/package.json +10 -10
  233. package/dist/darwin-acl.d.ts +0 -4
  234. package/dist/darwin-acl.d.ts.map +0 -1
  235. package/dist/darwin-acl.js +0 -24
@@ -1,24 +1,17 @@
1
1
  import fs from "node:fs";
2
+ import { acquireFileLockSyncWithRoot } from "./file-lock-sync-root-acquire.js";
3
+ import { isRootSyncHeldLockHandle, withRootSyncHeldLockHandle } from "./file-lock-sync-root-held.js";
2
4
  import path from "node:path";
3
- import { FsSafeError } from "./errors.js";
4
- import { readSidecarLockSnapshotSync, readSidecarLockRawSnapshotSync, parseSidecarLockSnapshot, relativeSidecarLockPath, removeSidecarLockIfUnchangedSync, serializeSidecarLockPayload, sidecarLockSnapshotMatches, } from "./sidecar-lock-reclaim.js";
5
- import { computeSidecarLockDelayMs, isTransientLockFileDenial, maxTransientLockDenials, sidecarLockPayloadCreatedAtMs, validateSidecarLockStaleMs, validateSidecarLockCompromiseCheckIntervalMs, validateSidecarLockRetryOptions, validateSidecarLockTimeoutMs, } from "./sidecar-lock-policy.js";
5
+ import { readSidecarLockSnapshotSync, removeSidecarLockIfUnchangedSync, serializeSidecarLockPayload, sidecarLockSnapshotMatches, } from "./sidecar-lock-reclaim.js";
6
+ import { computeSidecarLockDelayMs, isTransientLockFileDenial, maxTransientLockDenials, validateSidecarLockStaleMs, validateSidecarLockCompromiseCheckIntervalMs, validateSidecarLockRetryOptions, validateSidecarLockTimeoutMs, } from "./sidecar-lock-policy.js";
6
7
  import { getFsSafeLockConfig } from "./lock-config.js";
7
8
  import { sleepSync } from "./timing.js";
8
9
  import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
9
10
  import { realpathSync } from "./realpath.js";
10
11
  import { recursiveMkdirPath } from "./recursive-mkdir-path.js";
11
12
  import { createSuppressedError } from "./suppressed-error.js";
12
- const SYNC_HELD_LOCKS_KEY = Symbol.for("fsSafe.syncSidecarLocks");
13
- const SYNC_CLEANUP_REGISTERED_KEY = Symbol.for("fsSafe.syncSidecarLockCleanupRegistered");
14
- const SYNC_CLEANUP_HANDLER_KEY = Symbol.for("fsSafe.syncSidecarLockCleanupHandler");
15
- function getSyncHeldLocks() {
16
- const globalWithState = globalThis;
17
- if (!globalWithState[SYNC_HELD_LOCKS_KEY]) {
18
- globalWithState[SYNC_HELD_LOCKS_KEY] = new Map();
19
- }
20
- return globalWithState[SYNC_HELD_LOCKS_KEY];
21
- }
13
+ import { ensureSyncLockExitCleanupRegistered, getSyncHeldLocks, foreignSyncHeldLock, getSyncLockAdmissions, syncReclaimGuardExists, syncLockTimeout, } from "./file-lock-sync-admission.js";
14
+ import { handleSyncStaleAdmission, } from "./file-lock-sync-stale-admission.js";
22
15
  function releaseAllSyncHeldLocks() {
23
16
  const heldLocks = getSyncHeldLocks();
24
17
  for (const [normalizedTargetPath, held] of heldLocks) {
@@ -41,14 +34,7 @@ function releaseAllSyncHeldLocks() {
41
34
  }
42
35
  heldLocks.delete(normalizedTargetPath);
43
36
  }
44
- }
45
- function ensureSyncExitCleanupRegistered() {
46
- const globalWithCleanup = globalThis;
47
- if (globalWithCleanup[SYNC_CLEANUP_REGISTERED_KEY])
48
- return;
49
- globalWithCleanup[SYNC_CLEANUP_REGISTERED_KEY] = true;
50
- globalWithCleanup[SYNC_CLEANUP_HANDLER_KEY] = releaseAllSyncHeldLocks;
51
- process.on("exit", releaseAllSyncHeldLocks);
37
+ getSyncLockAdmissions().clear();
52
38
  }
53
39
  function verifySyncHeldLock(held) {
54
40
  const current = readSidecarLockSnapshotSync(held.lockPath, held.parsePayload);
@@ -113,42 +99,10 @@ function normalizeTargetPath(targetPath) {
113
99
  assertNoWindowsPathAlias(normalized);
114
100
  return normalized;
115
101
  }
116
- function boundedLockPath(lockPath, lockRoot) {
117
- const resolved = path.resolve(lockPath);
118
- assertNoWindowsPathAlias(resolved);
119
- if (!lockRoot)
120
- return resolved;
121
- relativeSidecarLockPath(lockRoot, resolved);
122
- const parent = path.dirname(resolved);
123
- const parentReal = canonicalLockParentSync(parent);
124
- assertNoWindowsPathAlias(parentReal);
125
- const parentRelative = path.relative(lockRoot.rootReal, parentReal);
126
- if (parentRelative === ".." || parentRelative.startsWith(`..${path.sep}`) || path.isAbsolute(parentRelative)) {
127
- throw new FsSafeError("outside-workspace", "sidecar lock parent is outside lockRoot");
128
- }
129
- const bounded = path.join(parentReal, path.basename(resolved));
130
- assertNoWindowsPathAlias(bounded);
131
- return bounded;
132
- }
133
- function defaultShouldReclaim(snapshot, staleMs, nowMs) {
134
- const createdAtMs = sidecarLockPayloadCreatedAtMs(snapshot.payload);
135
- if (createdAtMs !== null)
136
- return nowMs - createdAtMs > staleMs;
137
- // A cooperating holder can unlink after the snapshot; use its observed age.
138
- return !snapshot.stat || nowMs - snapshot.stat.mtimeMs > staleMs;
139
- }
140
- function reclaimGuardExists(reclaimGuardPath) {
141
- try {
142
- fs.lstatSync(reclaimGuardPath);
143
- return true;
144
- }
145
- catch (error) {
146
- if (error.code === "ENOENT")
147
- return false;
148
- throw error;
149
- }
150
- }
151
102
  export function acquireFileLockSync(targetPath, options) {
103
+ const lockRoot = options.lockRoot;
104
+ if (lockRoot)
105
+ return acquireFileLockSyncWithRoot(targetPath, options, lockRoot);
152
106
  const defaults = getFsSafeLockConfig();
153
107
  const retry = options.retry ?? defaults.retry ?? {};
154
108
  const timeoutMs = options.timeoutMs ?? defaults.timeoutMs;
@@ -156,38 +110,54 @@ export function acquireFileLockSync(targetPath, options) {
156
110
  validateSidecarLockTimeoutMs(timeoutMs);
157
111
  const staleMs = options.staleMs ?? defaults.staleMs ?? 30_000;
158
112
  validateSidecarLockStaleMs(staleMs);
159
- validateSidecarLockCompromiseCheckIntervalMs(options.compromiseCheckIntervalMs);
113
+ const compromiseCheckIntervalMs = options.compromiseCheckIntervalMs;
114
+ validateSidecarLockCompromiseCheckIntervalMs(compromiseCheckIntervalMs);
160
115
  const explicitLockPath = options.lockPath;
161
116
  assertNoWindowsPathAlias(targetPath);
162
117
  if (explicitLockPath !== undefined)
163
118
  assertNoWindowsPathAlias(explicitLockPath);
164
119
  const normalizedTargetPath = normalizeTargetPath(targetPath);
165
- const lockPath = boundedLockPath(explicitLockPath ?? `${normalizedTargetPath}.lock`, options.lockRoot);
120
+ const lockPath = path.resolve(explicitLockPath ?? `${normalizedTargetPath}.lock`);
121
+ assertNoWindowsPathAlias(lockPath);
122
+ const requestedReentrantOwner = options.reentrantOwner;
166
123
  const heldLocks = getSyncHeldLocks();
167
- const held = heldLocks.get(normalizedTargetPath);
168
- if (held &&
169
- options.reentrantOwner !== undefined &&
170
- held.reentrantOwner !== undefined &&
171
- options.reentrantOwner === held.reentrantOwner) {
172
- held.refCount += 1;
173
- return createSyncHeldLockHandle(held);
124
+ const currentTargetHolder = () => heldLocks.get(normalizedTargetPath) ??
125
+ foreignSyncHeldLock("raw", normalizedTargetPath);
126
+ const initiallyHeld = heldLocks.get(normalizedTargetPath);
127
+ if (initiallyHeld && !foreignSyncHeldLock("raw", normalizedTargetPath) &&
128
+ requestedReentrantOwner !== undefined &&
129
+ initiallyHeld.reentrantOwner !== undefined &&
130
+ requestedReentrantOwner === initiallyHeld.reentrantOwner) {
131
+ initiallyHeld.refCount += 1;
132
+ return createSyncHeldLockHandle(initiallyHeld);
174
133
  }
175
- // Process defaults fill the same fields here as withLockDefaults() fills for
176
- // the asynchronous manager, so both acquirers honor configureFsSafeLocks().
177
- const staleRecovery = options.staleRecovery ?? defaults.staleRecovery;
134
+ const admissions = getSyncLockAdmissions();
135
+ const admissionToken = {};
136
+ let ownsAdmission = false;
137
+ const hasAdmissionToken = () => admissions.get(normalizedTargetPath) === admissionToken;
138
+ const releaseAdmission = () => {
139
+ if (ownsAdmission && hasAdmissionToken())
140
+ admissions.delete(normalizedTargetPath);
141
+ ownsAdmission = false;
142
+ };
143
+ let payloadCallback;
144
+ let onCompromised = undefined;
145
+ let onCompromisedObserved = false;
146
+ let parsePayload = undefined;
147
+ let parsePayloadObserved = false;
148
+ let staleRecovery = undefined;
149
+ let staleRecoveryObserved = false;
150
+ const staleOptions = {};
178
151
  const startedAt = Date.now();
179
152
  let attempt = 0;
180
153
  let transientDenials = 0;
181
154
  const reclaimGuardPath = `${lockPath}.reclaim`;
182
155
  const waitForRetry = () => {
156
+ releaseAdmission();
183
157
  const elapsed = Date.now() - startedAt;
184
158
  const timedOut = timeoutMs !== undefined && elapsed >= timeoutMs;
185
159
  if (timedOut || (retry.retries !== undefined && attempt >= retry.retries)) {
186
- throw Object.assign(new Error(`file lock timeout for ${normalizedTargetPath}`), {
187
- code: "file_lock_timeout",
188
- lockPath,
189
- normalizedTargetPath,
190
- });
160
+ throw syncLockTimeout(lockPath, normalizedTargetPath);
191
161
  }
192
162
  const remaining = timeoutMs === undefined || timeoutMs === Number.POSITIVE_INFINITY
193
163
  ? Number.POSITIVE_INFINITY
@@ -210,170 +180,240 @@ export function acquireFileLockSync(targetPath, options) {
210
180
  }
211
181
  return true;
212
182
  };
213
- while (true) {
214
- if (reclaimGuardExists(reclaimGuardPath)) {
215
- waitForRetry();
216
- continue;
217
- }
218
- let fd;
219
- const payload = options.payload();
220
- const { raw, ownershipToken } = serializeSidecarLockPayload(payload);
221
- let lockFileCreateDenied = false;
183
+ const assertAdmissionToken = () => {
184
+ if (!hasAdmissionToken())
185
+ throw syncLockTimeout(lockPath, normalizedTargetPath);
186
+ };
187
+ const runAdmissionBoundary = (callback) => {
188
+ assertAdmissionToken();
222
189
  try {
223
- const noFollow = process.platform !== "win32" && typeof fs.constants.O_NOFOLLOW === "number"
224
- ? fs.constants.O_NOFOLLOW
225
- : 0;
226
- try {
227
- fd = fs.openSync(lockPath, fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL | noFollow, 0o600);
228
- }
229
- catch (error) {
230
- lockFileCreateDenied = isTransientLockFileDenial(error, lockPath);
231
- throw error;
232
- }
233
- fs.writeFileSync(fd, raw, "utf8");
234
- fs.fsyncSync(fd);
235
- const snapshot = {
236
- raw,
237
- payload,
238
- stat: fs.fstatSync(fd),
239
- ownershipToken,
240
- };
241
- const createdHeld = {
242
- fd,
243
- lockPath,
244
- normalizedTargetPath,
245
- parsePayload: options.parsePayload,
246
- refCount: 1,
247
- reentrantOwner: options.reentrantOwner,
248
- snapshot,
249
- };
250
- heldLocks.set(normalizedTargetPath, createdHeld);
251
- ensureSyncExitCleanupRegistered();
252
- const returnedHandle = createSyncHeldLockHandle(createdHeld);
253
- if (options.onCompromised && (options.compromiseCheckIntervalMs ?? 0) > 0) {
254
- createdHeld.timer = setInterval(() => {
255
- let stillHeld;
256
- try {
257
- stillHeld = returnedHandle.verifyStillHeld();
258
- }
259
- catch {
260
- stillHeld = false;
261
- }
262
- if (!stillHeld && createdHeld.timer) {
263
- clearInterval(createdHeld.timer);
264
- createdHeld.timer = undefined;
265
- options.onCompromised?.({ lockPath, normalizedTargetPath });
266
- }
267
- }, options.compromiseCheckIntervalMs);
268
- createdHeld.timer.unref();
269
- }
270
- fd = undefined;
271
- return returnedHandle;
190
+ return callback();
272
191
  }
273
- catch (error) {
274
- if (fd !== undefined) {
275
- const failed = { payload: null };
276
- try {
277
- failed.stat = fs.fstatSync(fd);
192
+ finally {
193
+ assertAdmissionToken();
194
+ }
195
+ };
196
+ try {
197
+ while (true) {
198
+ if (!ownsAdmission) {
199
+ const held = heldLocks.get(normalizedTargetPath);
200
+ if (held && !foreignSyncHeldLock("raw", normalizedTargetPath) &&
201
+ requestedReentrantOwner !== undefined &&
202
+ held.reentrantOwner !== undefined &&
203
+ requestedReentrantOwner === held.reentrantOwner) {
204
+ held.refCount += 1;
205
+ return createSyncHeldLockHandle(held);
278
206
  }
279
- catch {
280
- // Missing identity leaves the sidecar in place, but must not skip close.
207
+ if (admissions.has(normalizedTargetPath)) {
208
+ // The owner can only finish after this synchronous callback unwinds.
209
+ throw syncLockTimeout(lockPath, normalizedTargetPath);
281
210
  }
282
- const failedFd = fd;
283
- // A close error may still free the number; consume ownership before closing.
284
- fd = undefined;
285
- try {
286
- fs.closeSync(failedFd);
287
- if (failed.stat)
288
- removeSidecarLockIfUnchangedSync(lockPath, failed);
289
- }
290
- catch (cleanupError) {
291
- throw createSuppressedError(error, cleanupError, "file lock acquisition and cleanup both failed");
211
+ admissions.set(normalizedTargetPath, admissionToken);
212
+ ownsAdmission = true;
213
+ }
214
+ const attemptHeld = currentTargetHolder();
215
+ const holderWasReplaced = () => {
216
+ const current = currentTargetHolder();
217
+ return current !== undefined && current !== attemptHeld;
218
+ };
219
+ if (!staleRecoveryObserved) {
220
+ staleRecovery = runAdmissionBoundary(() => options.staleRecovery ?? defaults.staleRecovery);
221
+ staleRecoveryObserved = true;
222
+ if (holderWasReplaced()) {
223
+ waitForRetry();
224
+ continue;
292
225
  }
293
226
  }
294
- if (lockFileCreateDenied && retryLockFileDenial(error))
227
+ const reclaimGuardExists = syncReclaimGuardExists(reclaimGuardPath);
228
+ if (!hasAdmissionToken())
229
+ throw syncLockTimeout(lockPath, normalizedTargetPath);
230
+ if (holderWasReplaced()) {
231
+ waitForRetry();
295
232
  continue;
296
- if (error.code !== "EEXIST")
297
- throw error;
298
- if (heldLocks.has(normalizedTargetPath)) {
233
+ }
234
+ if (reclaimGuardExists) {
299
235
  waitForRetry();
300
236
  continue;
301
237
  }
302
- let rawSnapshot;
303
- let lockFileOpenDenied = false;
304
- try {
305
- rawSnapshot = readSidecarLockRawSnapshotSync(lockPath, {
306
- rejectNonFile: true,
307
- onOpenFailure: (error) => { lockFileOpenDenied = isTransientLockFileDenial(error, lockPath); },
308
- });
238
+ let fd;
239
+ let createdHeld;
240
+ let createdSnapshot;
241
+ if (!payloadCallback)
242
+ payloadCallback = runAdmissionBoundary(() => options.payload);
243
+ if (holderWasReplaced()) {
244
+ waitForRetry();
245
+ continue;
309
246
  }
310
- catch (readError) {
311
- if (lockFileOpenDenied && retryLockFileDenial(readError))
312
- continue;
313
- throw readError;
247
+ const payload = runAdmissionBoundary(() => Reflect.apply(payloadCallback, options, []));
248
+ if (holderWasReplaced()) {
249
+ waitForRetry();
250
+ continue;
251
+ }
252
+ const { raw, ownershipToken } = runAdmissionBoundary(() => serializeSidecarLockPayload(payload));
253
+ if (holderWasReplaced()) {
254
+ waitForRetry();
255
+ continue;
314
256
  }
315
- const snapshot = parseSidecarLockSnapshot(rawSnapshot, options.parsePayload);
316
- if (!snapshot) {
257
+ if (currentTargetHolder() !== undefined) {
317
258
  waitForRetry();
318
259
  continue;
319
260
  }
320
- const nowMs = Date.now();
321
- const reclaim = options.shouldReclaim
322
- ? options.shouldReclaim({
261
+ if (!onCompromisedObserved) {
262
+ onCompromised = runAdmissionBoundary(() => options.onCompromised);
263
+ onCompromisedObserved = true;
264
+ if (currentTargetHolder() !== undefined) {
265
+ waitForRetry();
266
+ continue;
267
+ }
268
+ }
269
+ if (!parsePayloadObserved) {
270
+ parsePayload = runAdmissionBoundary(() => options.parsePayload);
271
+ parsePayloadObserved = true;
272
+ if (currentTargetHolder() !== undefined) {
273
+ waitForRetry();
274
+ continue;
275
+ }
276
+ }
277
+ let lockFileCreateDenied = false;
278
+ let exclusiveCreateConflict = false;
279
+ try {
280
+ const noFollow = process.platform !== "win32" && typeof fs.constants.O_NOFOLLOW === "number"
281
+ ? fs.constants.O_NOFOLLOW
282
+ : 0;
283
+ try {
284
+ fd = fs.openSync(lockPath, fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL | noFollow, 0o600);
285
+ }
286
+ catch (error) {
287
+ lockFileCreateDenied = isTransientLockFileDenial(error, lockPath);
288
+ exclusiveCreateConflict = error.code === "EEXIST";
289
+ throw error;
290
+ }
291
+ fs.writeFileSync(fd, raw, "utf8");
292
+ fs.fsyncSync(fd);
293
+ createdSnapshot = {
294
+ raw,
295
+ payload,
296
+ stat: fs.fstatSync(fd),
297
+ ownershipToken,
298
+ };
299
+ createdHeld = {
300
+ fd,
323
301
  lockPath,
324
302
  normalizedTargetPath,
325
- payload: snapshot.payload,
326
- staleMs,
327
- nowMs,
328
- heldByThisProcess: false,
329
- })
330
- : defaultShouldReclaim(snapshot, staleMs, nowMs);
331
- if (reclaim) {
332
- if (staleRecovery === "remove-if-unchanged" &&
333
- snapshot.raw !== undefined &&
334
- options.shouldRemoveStaleLock?.({
335
- lockPath,
336
- normalizedTargetPath,
337
- raw: snapshot.raw,
338
- payload: snapshot.payload,
339
- })) {
340
- let ownsReclaimGuard = false;
303
+ parsePayload,
304
+ refCount: 1,
305
+ reentrantOwner: requestedReentrantOwner,
306
+ snapshot: createdSnapshot,
307
+ };
308
+ const candidateHeld = createdHeld;
309
+ ensureSyncLockExitCleanupRegistered(releaseAllSyncHeldLocks, lockPath, normalizedTargetPath);
310
+ if (!hasAdmissionToken() || currentTargetHolder() !== undefined) {
311
+ throw syncLockTimeout(lockPath, normalizedTargetPath);
312
+ }
313
+ const returnedHandle = createSyncHeldLockHandle(candidateHeld);
314
+ if (onCompromised && (compromiseCheckIntervalMs ?? 0) > 0) {
315
+ const compromisedCallback = onCompromised;
316
+ candidateHeld.timer = setInterval(() => {
317
+ let stillHeld;
318
+ try {
319
+ stillHeld = returnedHandle.verifyStillHeld();
320
+ }
321
+ catch {
322
+ stillHeld = false;
323
+ }
324
+ if (!stillHeld && candidateHeld.timer) {
325
+ clearInterval(candidateHeld.timer);
326
+ candidateHeld.timer = undefined;
327
+ Reflect.apply(compromisedCallback, options, [{ lockPath, normalizedTargetPath }]);
328
+ }
329
+ }, compromiseCheckIntervalMs);
330
+ candidateHeld.timer.unref();
331
+ }
332
+ if (!hasAdmissionToken() ||
333
+ currentTargetHolder() !== undefined) {
334
+ throw syncLockTimeout(lockPath, normalizedTargetPath);
335
+ }
336
+ heldLocks.set(normalizedTargetPath, candidateHeld);
337
+ releaseAdmission();
338
+ fd = undefined;
339
+ return returnedHandle;
340
+ }
341
+ catch (error) {
342
+ if (createdHeld?.timer) {
343
+ clearInterval(createdHeld.timer);
344
+ createdHeld.timer = undefined;
345
+ }
346
+ if (createdHeld && heldLocks.get(normalizedTargetPath) === createdHeld) {
347
+ heldLocks.delete(normalizedTargetPath);
348
+ }
349
+ if (fd !== undefined) {
350
+ const failed = createdSnapshot ?? { payload: null };
351
+ if (!failed.stat) {
352
+ try {
353
+ failed.stat = fs.fstatSync(fd);
354
+ }
355
+ catch {
356
+ // Missing identity leaves the sidecar in place, but must not skip close.
357
+ }
358
+ }
359
+ const failedFd = fd;
360
+ fd = undefined;
361
+ if (createdHeld)
362
+ createdHeld.fd = undefined;
341
363
  try {
342
- fs.mkdirSync(reclaimGuardPath);
343
- ownsReclaimGuard = true;
344
- if (removeSidecarLockIfUnchangedSync(lockPath, snapshot))
345
- continue;
364
+ fs.closeSync(failedFd);
365
+ if (failed.stat)
366
+ removeSidecarLockIfUnchangedSync(lockPath, failed);
346
367
  }
347
- catch (reclaimError) {
348
- if (reclaimError.code !== "EEXIST") {
349
- throw reclaimError;
350
- }
368
+ catch (cleanupError) {
369
+ throw createSuppressedError(error, cleanupError, "file lock acquisition and cleanup both failed");
370
+ }
371
+ }
372
+ if (lockFileCreateDenied) {
373
+ if (!hasAdmissionToken())
374
+ throw syncLockTimeout(lockPath, normalizedTargetPath);
375
+ if (currentTargetHolder() !== undefined) {
351
376
  waitForRetry();
352
377
  continue;
353
378
  }
354
- finally {
355
- if (ownsReclaimGuard) {
356
- try {
357
- fs.rmdirSync(reclaimGuardPath);
358
- }
359
- catch {
360
- // A surviving reclaim guard fails closed.
361
- }
362
- }
363
- }
379
+ if (retryLockFileDenial(error))
380
+ continue;
381
+ throw error;
382
+ }
383
+ if (!exclusiveCreateConflict)
384
+ throw error;
385
+ if (!hasAdmissionToken())
386
+ throw syncLockTimeout(lockPath, normalizedTargetPath);
387
+ if (currentTargetHolder() !== undefined) {
388
+ waitForRetry();
389
+ continue;
364
390
  }
365
- throw Object.assign(new Error(`file lock stale for ${normalizedTargetPath}`), {
366
- code: "file_lock_stale",
391
+ handleSyncStaleAdmission({
392
+ hasToken: hasAdmissionToken,
393
+ currentHeld: currentTargetHolder,
367
394
  lockPath,
368
395
  normalizedTargetPath,
396
+ options,
397
+ parsePayload,
398
+ reclaimGuardPath,
399
+ retryLockFileDenial,
400
+ staleMs,
401
+ staleOptions,
402
+ staleRecovery,
403
+ waitForRetry,
369
404
  });
405
+ continue;
370
406
  }
371
- waitForRetry();
372
407
  }
373
408
  }
409
+ finally {
410
+ releaseAdmission();
411
+ }
374
412
  }
375
413
  export function withFileLockSync(targetPath, options, fn) {
376
414
  const lock = acquireFileLockSync(targetPath, options);
415
+ if (isRootSyncHeldLockHandle(lock))
416
+ return withRootSyncHeldLockHandle(lock, fn);
377
417
  try {
378
418
  return fn();
379
419
  }
@@ -1 +1 @@
1
- {"version":3,"file":"file-store-prune.d.ts","sourceRoot":"","sources":["../src/file-store-prune.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,qBAAqB,CAAC;CAChC,GAAG,OAAO,CAAC,IAAI,CAAC,CA8FhB"}
1
+ {"version":3,"file":"file-store-prune.d.ts","sourceRoot":"","sources":["../src/file-store-prune.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAQF,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,qBAAqB,CAAC;CAChC,GAAG,OAAO,CAAC,IAAI,CAAC,CA8FhB"}
@@ -6,7 +6,11 @@ import { isPathInside } from "./path.js";
6
6
  import { realpathSync } from "./realpath.js";
7
7
  import { recursiveMkdirPath } from "./recursive-mkdir-path.js";
8
8
  import { root } from "./root.js";
9
+ import { nonrecursiveRemovalKind } from "./root-remove.js";
9
10
  import { getFsSafeTestHooks } from "./test-hooks.js";
11
+ const REMOVE_EMPTY_DIRECTORY_OPTIONS = Object.freeze({
12
+ [nonrecursiveRemovalKind]: "directory",
13
+ });
10
14
  export async function pruneExpiredStoreEntries(params) {
11
15
  const now = Date.now();
12
16
  const recursive = params.options.recursive ?? false;
@@ -70,7 +74,7 @@ export async function pruneExpiredStoreEntries(params) {
70
74
  await assertRootGuard();
71
75
  // Keep empty-dir pruning on the same root-bounded remove path as files;
72
76
  // the Root fallback handles empty directories without recursive delete.
73
- await scopedRoot.remove(relativePath).catch(() => undefined);
77
+ await scopedRoot.remove(relativePath, REMOVE_EMPTY_DIRECTORY_OPTIONS).catch(() => undefined);
74
78
  }
75
79
  continue;
76
80
  }
@@ -76,7 +76,7 @@ export function writeFileSyncAtomic(params) {
76
76
  }
77
77
  const tempPath = path.join(parentGuard?.dir ?? path.dirname(filePath), `.fs-safe-${process.pid}-${randomUUID()}.tmp`);
78
78
  const owner = new SyncAtomicTempOwner(tempPath);
79
- let originalError;
79
+ let originalFailure;
80
80
  try {
81
81
  getFsSafeTestHooks()?.beforeFileStoreSyncPrivateWrite?.(filePath);
82
82
  if (parentGuard) {
@@ -133,10 +133,10 @@ export function writeFileSyncAtomic(params) {
133
133
  return filePath;
134
134
  }
135
135
  catch (error) {
136
- originalError = error;
136
+ originalFailure = { error };
137
137
  throw error;
138
138
  }
139
139
  finally {
140
- owner.finish({ fsModule: fs, originalError, throwOnCleanupError: false });
140
+ owner.finish({ fsModule: fs, originalFailure, throwOnCleanupError: false });
141
141
  }
142
142
  }
@@ -1 +1 @@
1
- {"version":3,"file":"file-store.d.ts","sourceRoot":"","sources":["../src/file-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file-store.d.ts","sourceRoot":"","sources":["../src/file-store.ts"],"names":[],"mappings":"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"}