@openclaw/fs-safe 0.16.0 → 0.17.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 (180) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +8 -1
  3. package/dist/absolute-path.d.ts.map +1 -1
  4. package/dist/absolute-path.js +2 -8
  5. package/dist/advanced.d.ts +2 -0
  6. package/dist/advanced.d.ts.map +1 -1
  7. package/dist/advanced.js +2 -0
  8. package/dist/archive-deadline.d.ts.map +1 -1
  9. package/dist/archive-deadline.js +22 -23
  10. package/dist/archive-merge.d.ts +1 -0
  11. package/dist/archive-merge.d.ts.map +1 -1
  12. package/dist/archive-merge.js +4 -4
  13. package/dist/archive-native.d.ts +1 -0
  14. package/dist/archive-native.d.ts.map +1 -1
  15. package/dist/archive-native.js +1 -0
  16. package/dist/archive-options.d.ts +2 -0
  17. package/dist/archive-options.d.ts.map +1 -1
  18. package/dist/archive-parser.wasm +0 -0
  19. package/dist/archive-zip-count.d.ts.map +1 -1
  20. package/dist/archive-zip-count.js +21 -1
  21. package/dist/archive-zip-directory.d.ts.map +1 -1
  22. package/dist/archive-zip-directory.js +23 -1
  23. package/dist/archive-zip-loader.d.ts +2 -0
  24. package/dist/archive-zip-loader.d.ts.map +1 -1
  25. package/dist/archive-zip-loader.js +7 -0
  26. package/dist/archive-zip-names.d.ts.map +1 -1
  27. package/dist/archive-zip-names.js +7 -2
  28. package/dist/archive.d.ts.map +1 -1
  29. package/dist/archive.js +9 -3
  30. package/dist/byte-view.d.ts +3 -0
  31. package/dist/byte-view.d.ts.map +1 -0
  32. package/dist/byte-view.js +13 -0
  33. package/dist/creation-darwin.d.ts +0 -1
  34. package/dist/creation-darwin.d.ts.map +1 -1
  35. package/dist/creation-darwin.js +0 -9
  36. package/dist/directory-durability.d.ts +6 -6
  37. package/dist/directory-durability.d.ts.map +1 -1
  38. package/dist/directory-receipt.d.ts +2 -2
  39. package/dist/directory-receipt.d.ts.map +1 -1
  40. package/dist/directory-receipt.js +15 -19
  41. package/dist/file-cleanup.d.ts +1 -0
  42. package/dist/file-cleanup.d.ts.map +1 -1
  43. package/dist/file-cleanup.js +7 -4
  44. package/dist/file-contents.d.ts +6 -0
  45. package/dist/file-contents.d.ts.map +1 -0
  46. package/dist/file-contents.js +40 -0
  47. package/dist/file-hash.d.ts.map +1 -1
  48. package/dist/file-hash.js +16 -4
  49. package/dist/file-lock-sync-root-acquire.d.ts.map +1 -1
  50. package/dist/file-lock-sync-root-acquire.js +3 -0
  51. package/dist/file-lock-sync-root-held.d.ts +1 -2
  52. package/dist/file-lock-sync-root-held.d.ts.map +1 -1
  53. package/dist/file-lock-sync-root-held.js +7 -5
  54. package/dist/file-lock-sync-stale-admission.d.ts.map +1 -1
  55. package/dist/file-lock-sync-stale-admission.js +3 -0
  56. package/dist/file-lock-sync.d.ts.map +1 -1
  57. package/dist/file-lock-sync.js +8 -11
  58. package/dist/file-store.js +3 -3
  59. package/dist/guarded-mkdir.d.ts.map +1 -1
  60. package/dist/guarded-mkdir.js +6 -27
  61. package/dist/install-path.d.ts.map +1 -1
  62. package/dist/install-path.js +2 -5
  63. package/dist/json-durable-queue-ownership.d.ts.map +1 -1
  64. package/dist/json-durable-queue-ownership.js +2 -6
  65. package/dist/json-durable-queue-paths.d.ts.map +1 -1
  66. package/dist/json-durable-queue-paths.js +2 -24
  67. package/dist/json-durable-queue.d.ts.map +1 -1
  68. package/dist/json-durable-queue.js +10 -9
  69. package/dist/json.d.ts.map +1 -1
  70. package/dist/json.js +32 -75
  71. package/dist/local-roots.d.ts.map +1 -1
  72. package/dist/local-roots.js +19 -21
  73. package/dist/move-path-cleanup.d.ts +5 -19
  74. package/dist/move-path-cleanup.d.ts.map +1 -1
  75. package/dist/move-path-cleanup.js +57 -21
  76. package/dist/move-path.d.ts.map +1 -1
  77. package/dist/move-path.js +62 -39
  78. package/dist/native-staged-file.d.ts +2 -1
  79. package/dist/native-staged-file.d.ts.map +1 -1
  80. package/dist/native-staged-file.js +8 -5
  81. package/dist/native.js +2 -2
  82. package/dist/opened-realpath.d.ts.map +1 -1
  83. package/dist/opened-realpath.js +11 -2
  84. package/dist/path.d.ts.map +1 -1
  85. package/dist/path.js +2 -1
  86. package/dist/permissions.d.ts.map +1 -1
  87. package/dist/permissions.js +3 -17
  88. package/dist/pinned-write-input.d.ts.map +1 -1
  89. package/dist/pinned-write-input.js +11 -1
  90. package/dist/pinned-write-mode.d.ts +3 -3
  91. package/dist/pinned-write-mode.d.ts.map +1 -1
  92. package/dist/pinned-write-mode.js +15 -8
  93. package/dist/pinned-write-staged.d.ts.map +1 -1
  94. package/dist/pinned-write-staged.js +10 -11
  95. package/dist/pinned-write.d.ts.map +1 -1
  96. package/dist/pinned-write.js +17 -13
  97. package/dist/publish-file.d.ts +2 -2
  98. package/dist/publish-file.d.ts.map +1 -1
  99. package/dist/publish-file.js +56 -96
  100. package/dist/regular-file.d.ts.map +1 -1
  101. package/dist/regular-file.js +35 -44
  102. package/dist/replace-file-copy-fallback.d.ts.map +1 -1
  103. package/dist/replace-file-copy-fallback.js +28 -26
  104. package/dist/replace-file-copy-source.d.ts.map +1 -1
  105. package/dist/replace-file-copy-source.js +13 -22
  106. package/dist/replace-file-descriptor.d.ts.map +1 -1
  107. package/dist/replace-file-descriptor.js +10 -16
  108. package/dist/replace-file-temp-owner.js +6 -6
  109. package/dist/replace-file.d.ts.map +1 -1
  110. package/dist/replace-file.js +9 -13
  111. package/dist/root-directory-list.d.ts.map +1 -1
  112. package/dist/root-directory-list.js +20 -3
  113. package/dist/root-file-final-admission.d.ts +1 -1
  114. package/dist/root-file-final-admission.d.ts.map +1 -1
  115. package/dist/root-file-final-admission.js +5 -2
  116. package/dist/root-file.d.ts.map +1 -1
  117. package/dist/root-file.js +3 -2
  118. package/dist/root-impl.d.ts.map +1 -1
  119. package/dist/root-impl.js +50 -20
  120. package/dist/root-move-noreplace.d.ts +2 -0
  121. package/dist/root-move-noreplace.d.ts.map +1 -1
  122. package/dist/root-move-noreplace.js +2 -2
  123. package/dist/root-read-admission.d.ts.map +1 -1
  124. package/dist/root-read-admission.js +7 -2
  125. package/dist/root-remove.d.ts.map +1 -1
  126. package/dist/root-remove.js +15 -1
  127. package/dist/sidecar-lock-acquire.d.ts.map +1 -1
  128. package/dist/sidecar-lock-acquire.js +4 -6
  129. package/dist/sidecar-lock-handle.d.ts +3 -0
  130. package/dist/sidecar-lock-handle.d.ts.map +1 -1
  131. package/dist/sidecar-lock-handle.js +6 -0
  132. package/dist/sidecar-lock-reclaim.d.ts +1 -1
  133. package/dist/sidecar-lock-reclaim.d.ts.map +1 -1
  134. package/dist/sidecar-lock-reclaim.js +11 -8
  135. package/dist/sidecar-lock.d.ts.map +1 -1
  136. package/dist/sidecar-lock.js +3 -5
  137. package/dist/staged-directory.d.ts +2 -2
  138. package/dist/staged-directory.d.ts.map +1 -1
  139. package/dist/strict-file-identity.d.ts +1 -1
  140. package/dist/strict-file-identity.d.ts.map +1 -1
  141. package/dist/strict-file-identity.js +9 -9
  142. package/dist/symlink-parents.d.ts.map +1 -1
  143. package/dist/symlink-parents.js +2 -27
  144. package/dist/temp-workspace-owner.js +4 -4
  145. package/dist/unicode-path.d.ts.map +1 -1
  146. package/dist/unicode-path.js +3 -0
  147. package/dist/walk.d.ts.map +1 -1
  148. package/dist/walk.js +4 -2
  149. package/dist/write-file-handle.d.ts +7 -0
  150. package/dist/write-file-handle.d.ts.map +1 -1
  151. package/dist/write-file-handle.js +23 -0
  152. package/dist/write-open-flags.d.ts.map +1 -1
  153. package/dist/write-open-flags.js +1 -8
  154. package/dist/write-queue.d.ts.map +1 -1
  155. package/dist/write-queue.js +1 -4
  156. package/docs/advanced.md +68 -1
  157. package/docs/archive.md +41 -2
  158. package/docs/atomic.md +29 -5
  159. package/docs/contributing.md +4 -0
  160. package/docs/creation.md +8 -4
  161. package/docs/durability.md +35 -0
  162. package/docs/file-contents.md +68 -0
  163. package/docs/json.md +5 -4
  164. package/docs/local-roots.md +2 -0
  165. package/docs/mutation-policy-proof.md +5 -3
  166. package/docs/native.md +9 -8
  167. package/docs/path.md +4 -4
  168. package/docs/public-api.md +5 -0
  169. package/docs/quickstart.md +1 -1
  170. package/docs/reading.md +2 -2
  171. package/docs/regular-file.md +3 -0
  172. package/docs/root.md +9 -0
  173. package/docs/sidecar-lock.md +9 -1
  174. package/docs/staged-file.md +4 -3
  175. package/docs/store.md +3 -1
  176. package/docs/temp.md +4 -1
  177. package/docs/types.md +18 -2
  178. package/docs/walk.md +7 -0
  179. package/docs/writing.md +9 -2
  180. package/package.json +8 -8
@@ -220,13 +220,21 @@ async function removeOne(root, targetPath, options, receipts) {
220
220
  throw normalizeRemoveGuardError(error);
221
221
  }
222
222
  try {
223
- const isDirectory = fsSync.lstatSync(targetPath).isDirectory();
223
+ const identity = options.assertBeforeMutation
224
+ ? inspectFileIdentitySync(() => fsSync.lstatSync(targetPath, { bigint: true })) : undefined;
225
+ const isDirectory = (identity ?? fsSync.lstatSync(targetPath)).isDirectory();
224
226
  if (!isDirectory && options[nonrecursiveRemovalKind] === "directory") {
225
227
  throw new FsSafeError("path-mismatch", "store entry is no longer a directory");
226
228
  }
227
229
  assertFinalSymlinkRejected(targetPath, options.mutationSymlinks !== undefined);
228
230
  assertNotAborted(options.signal);
229
231
  options.assertBeforeMutation?.();
232
+ if (identity) {
233
+ assertNotAborted(options.signal);
234
+ admission.assertCurrent();
235
+ inspectFileIdentitySync(() => fsSync.lstatSync(targetPath, { bigint: true }), identity);
236
+ assertFinalSymlinkRejected(targetPath, options.mutationSymlinks !== undefined);
237
+ }
230
238
  await (isDirectory ? fs.rmdir(targetPath) : fs.unlink(targetPath));
231
239
  }
232
240
  catch (error) {
@@ -436,6 +444,12 @@ export async function removePathInRootFallback(root, targetPath, options, receip
436
444
  assertFinalSymlinkRejected(target, options.mutationSymlinks !== undefined, details(target, "remove"));
437
445
  assertNotAborted(options.signal);
438
446
  options.assertBeforeMutation?.();
447
+ if (options.assertBeforeMutation) {
448
+ assertNotAborted(options.signal);
449
+ if (!inspect(target, initial))
450
+ return;
451
+ assertFinalSymlinkRejected(target, options.mutationSymlinks !== undefined, details(target, "remove"));
452
+ }
439
453
  try {
440
454
  await (initial.isDirectory() ? fs.rmdir(target) : fs.unlink(target));
441
455
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sidecar-lock-acquire.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-acquire.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAM5F,OAAO,EAA4C,KAAK,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAM3H,YAAY,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,wBAAsB,kBAAkB,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/E,OAAO,EAAE,yBAAyB,CAAC,QAAQ,CAAC,EAC5C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,iBAAiB,CAAC,CA0b5B"}
1
+ {"version":3,"file":"sidecar-lock-acquire.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-acquire.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAM5F,OAAO,EAA4C,KAAK,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAO3H,YAAY,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,wBAAsB,kBAAkB,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/E,OAAO,EAAE,yBAAyB,CAAC,QAAQ,CAAC,EAC5C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,iBAAiB,CAAC,CAsb5B"}
@@ -15,6 +15,7 @@ import { resolveSidecarLockPaths } from "./sidecar-lock-target.js";
15
15
  import { createSuppressedError } from "./suppressed-error.js";
16
16
  import { sleep } from "./timing.js";
17
17
  import { sidecarExclusiveCreate } from "./root-create-input.js";
18
+ import { stopSidecarLockMonitoring } from "./sidecar-lock-handle.js";
18
19
  export async function acquireSidecarLock(options, context) {
19
20
  const admissionAncestry = captureSidecarAdmissionAncestry();
20
21
  const retainOnExit = options.retainOnExit;
@@ -353,8 +354,7 @@ export async function acquireSidecarLock(options, context) {
353
354
  .catch(() => false)
354
355
  .then((stillHeld) => {
355
356
  if (!stillHeld && candidateHeld.compromiseTimer) {
356
- clearInterval(candidateHeld.compromiseTimer);
357
- candidateHeld.compromiseTimer = undefined;
357
+ stopSidecarLockMonitoring(candidateHeld);
358
358
  Reflect.apply(compromisedCallback, options, [{ lockPath, normalizedTargetPath }]);
359
359
  }
360
360
  })
@@ -376,10 +376,8 @@ export async function acquireSidecarLock(options, context) {
376
376
  }
377
377
  catch (err) {
378
378
  try {
379
- if (createdHeld?.compromiseTimer) {
380
- clearInterval(createdHeld.compromiseTimer);
381
- createdHeld.compromiseTimer = undefined;
382
- }
379
+ if (createdHeld)
380
+ stopSidecarLockMonitoring(createdHeld);
383
381
  if (handle) {
384
382
  const failedSnapshot = createdSnapshot ?? { payload: null };
385
383
  try {
@@ -1,6 +1,9 @@
1
1
  import type { Root } from "./root-impl.js";
2
2
  import { type SidecarLockSnapshot } from "./sidecar-lock-reclaim.js";
3
3
  import type { SidecarLockHandle } from "./sidecar-lock-types.js";
4
+ export declare function stopSidecarLockMonitoring(held: {
5
+ compromiseTimer?: NodeJS.Timeout;
6
+ }): void;
4
7
  export declare function createSidecarLockHandle(params: {
5
8
  lockPath: string;
6
9
  normalizedTargetPath: string;
@@ -1 +1 @@
1
- {"version":3,"file":"sidecar-lock-handle.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-handle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9D,GAAG,iBAAiB,CA2BpB;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,IAAI,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,mBAAmB,CAAC;QAC9B,QAAQ,CAAC,EAAE,IAAI,CAAC;QAChB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;KACzC,CAAC;IACF,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9D,GAAG,iBAAiB,CAWpB"}
1
+ {"version":3,"file":"sidecar-lock-handle.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-handle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAAE,eAAe,CAAC,EAAE,MAAM,CAAC,OAAO,CAAA;CAAE,GAAG,IAAI,CAI1F;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9D,GAAG,iBAAiB,CA2BpB;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,IAAI,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,mBAAmB,CAAC;QAC9B,QAAQ,CAAC,EAAE,IAAI,CAAC;QAChB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;KACzC,CAAC;IACF,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9D,GAAG,iBAAiB,CAWpB"}
@@ -1,4 +1,10 @@
1
1
  import { sidecarLockSnapshotStillPresent, } from "./sidecar-lock-reclaim.js";
2
+ export function stopSidecarLockMonitoring(held) {
3
+ const timer = held.compromiseTimer;
4
+ held.compromiseTimer = undefined;
5
+ if (timer)
6
+ clearInterval(timer);
7
+ }
2
8
  export function createSidecarLockHandle(params) {
3
9
  let released = false;
4
10
  let releasePromise;
@@ -39,7 +39,7 @@ export declare function readSidecarLockRawSnapshotSync(lockPath: string, options
39
39
  onOpenFailure?: (error: unknown) => void;
40
40
  }): SidecarLockRawSnapshot | null;
41
41
  export declare function removeSidecarLockIfUnchangedSync(lockPath: string, observed: SidecarLockSnapshot, assertAuthorized?: () => void): boolean;
42
- export declare function sidecarLockSnapshotMatches(current: SidecarLockSnapshot, observed: SidecarLockSnapshot): boolean;
42
+ export declare function sidecarLockSnapshotMatches(current: SidecarLockRawSnapshot | SidecarLockSnapshot, observed: SidecarLockSnapshot): boolean;
43
43
  export declare function removeSidecarLockIfUnchanged(lockPath: string, observed: SidecarLockSnapshot | null, options?: {
44
44
  lockRoot?: Root;
45
45
  parsePayload?: (raw: string) => unknown;
@@ -1 +1 @@
1
- {"version":3,"file":"sidecar-lock-reclaim.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-reclaim.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sidecar-lock-reclaim.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-reclaim.ts"],"names":[],"mappings":"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"}
@@ -71,6 +71,12 @@ function missingSnapshotPath(error) {
71
71
  export async function readSidecarLockSnapshot(lockPath, options = {}) {
72
72
  return parseSidecarLockSnapshot(await readSidecarLockRawSnapshot(lockPath, options), options.parsePayload);
73
73
  }
74
+ async function readSidecarLockComparisonSnapshot(lockPath, options) {
75
+ const snapshot = await readSidecarLockRawSnapshot(lockPath, options);
76
+ const parsePayload = options?.parsePayload;
77
+ // Ownership uses raw bytes and identity, but custom parsers retain their effects.
78
+ return parsePayload ? parseSidecarLockSnapshot(snapshot, parsePayload) : snapshot;
79
+ }
74
80
  export async function readSidecarLockRawSnapshot(lockPath, options = {}) {
75
81
  let handle;
76
82
  try {
@@ -197,7 +203,6 @@ export function readSidecarLockRawSnapshotSync(lockPath, options = {}) {
197
203
  return {
198
204
  raw,
199
205
  stat: after,
200
- ownershipToken: readSidecarLockOwnershipToken(raw),
201
206
  };
202
207
  }
203
208
  finally {
@@ -207,7 +212,7 @@ export function readSidecarLockRawSnapshotSync(lockPath, options = {}) {
207
212
  }
208
213
  export function removeSidecarLockIfUnchangedSync(lockPath, observed, assertAuthorized) {
209
214
  assertAuthorized?.();
210
- const current = readSidecarLockSnapshotSync(lockPath);
215
+ const current = readSidecarLockRawSnapshotSync(lockPath);
211
216
  assertAuthorized?.();
212
217
  if (!current || !sidecarLockSnapshotMatches(current, observed))
213
218
  return false;
@@ -219,10 +224,8 @@ export function sidecarLockSnapshotMatches(current, observed) {
219
224
  if (observed.ownershipToken !== undefined) {
220
225
  return (current.stat?.isFile() === true &&
221
226
  current.raw !== undefined &&
222
- observed.raw !== undefined &&
223
- readSidecarLockOwnershipToken(current.raw) === observed.ownershipToken &&
224
- readSidecarLockOwnershipToken(observed.raw) === observed.ownershipToken &&
225
- current.raw === observed.raw);
227
+ current.raw === observed.raw &&
228
+ readSidecarLockOwnershipToken(current.raw) === observed.ownershipToken);
226
229
  }
227
230
  if (observed.stat &&
228
231
  current.stat &&
@@ -235,7 +238,7 @@ export function sidecarLockSnapshotMatches(current, observed) {
235
238
  return observed.stat !== undefined && current.stat !== undefined;
236
239
  }
237
240
  export async function removeSidecarLockIfUnchanged(lockPath, observed, options = {}) {
238
- const current = await readSidecarLockSnapshot(lockPath, {
241
+ const current = await readSidecarLockComparisonSnapshot(lockPath, {
239
242
  ...options,
240
243
  allowDescriptorIdentityDrift: observed?.ownershipToken !== undefined,
241
244
  });
@@ -251,7 +254,7 @@ export async function removeSidecarLockIfUnchanged(lockPath, observed, options =
251
254
  return true;
252
255
  }
253
256
  export async function sidecarLockSnapshotStillPresent(lockPath, observed, options = {}) {
254
- const current = await readSidecarLockSnapshot(lockPath, {
257
+ const current = await readSidecarLockComparisonSnapshot(lockPath, {
255
258
  ...options,
256
259
  allowDescriptorIdentityDrift: observed?.ownershipToken !== undefined,
257
260
  });
@@ -1 +1 @@
1
- {"version":3,"file":"sidecar-lock.d.ts","sourceRoot":"","sources":["../src/sidecar-lock.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,yBAAyB,EACzB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,YAAY,EACV,yBAAyB,EACzB,0BAA0B,EAC1B,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AA2KjC,0FAA0F;AAC1F,wBAAgB,uBAAuB,IAAI,OAAO,CAMjD;AA8HD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM;cAuB3B,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WACpD,yBAAyB,CAAC,QAAQ,CAAC,KAC3C,OAAO,CAAC,iBAAiB,CAAC;eAaL,CAAC,EAAE,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WACxD,yBAAyB,CAAC,QAAQ,CAAC,MACxC,MAAM,OAAO,CAAC,CAAC,CAAC,KACnB,OAAO,CAAC,CAAC,CAAC;iBAqBW,OAAO,CAAC,IAAI,CAAC;iBAQnB,IAAI;uBAIE,oBAAoB,EAAE;EAW/C;AAED,wBAAsB,eAAe,CAAC,CAAC,EAAE,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/E,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,sBAAsB,CAAC,QAAQ,CAAC,EACzC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAMZ"}
1
+ {"version":3,"file":"sidecar-lock.d.ts","sourceRoot":"","sources":["../src/sidecar-lock.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,yBAAyB,EACzB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,YAAY,EACV,yBAAyB,EACzB,0BAA0B,EAC1B,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AA4KjC,0FAA0F;AAC1F,wBAAgB,uBAAuB,IAAI,OAAO,CAMjD;AA2HD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM;cAuB3B,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WACpD,yBAAyB,CAAC,QAAQ,CAAC,KAC3C,OAAO,CAAC,iBAAiB,CAAC;eAaL,CAAC,EAAE,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WACxD,yBAAyB,CAAC,QAAQ,CAAC,MACxC,MAAM,OAAO,CAAC,CAAC,CAAC,KACnB,OAAO,CAAC,CAAC,CAAC;iBAqBW,OAAO,CAAC,IAAI,CAAC;iBAQnB,IAAI;uBAIE,oBAAoB,EAAE;EAW/C;AAED,wBAAsB,eAAe,CAAC,CAAC,EAAE,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/E,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,sBAAsB,CAAC,QAAQ,CAAC,EACzC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAMZ"}
@@ -3,7 +3,7 @@ import { FsSafeError } from "./errors.js";
3
3
  import { sameFileIdentity } from "./file-identity.js";
4
4
  import { removeSidecarLockIfUnchanged, sidecarLockSnapshotMatches, } from "./sidecar-lock-reclaim.js";
5
5
  import { acquireSidecarLock } from "./sidecar-lock-acquire.js";
6
- import { createHeldSidecarLockHandle } from "./sidecar-lock-handle.js";
6
+ import { createHeldSidecarLockHandle, stopSidecarLockMonitoring } from "./sidecar-lock-handle.js";
7
7
  import { createSuppressedError } from "./suppressed-error.js";
8
8
  const GLOBAL_STATE_KEY = Symbol.for("fsSafe.sidecarLockManagers");
9
9
  const GLOBAL_CLEANUP_KEY = Symbol.for("fsSafe.sidecarLockCleanupRegistered");
@@ -101,6 +101,7 @@ function releaseAllReclaimGuardsSync(state) {
101
101
  }
102
102
  function releaseAllLocksSync(state, options) {
103
103
  for (const [normalizedTargetPath, held] of state.held) {
104
+ stopSidecarLockMonitoring(held);
104
105
  void held.handle.close().catch(() => undefined);
105
106
  try {
106
107
  const retained = options?.preserveRetained === true && held.retainOnExit;
@@ -257,10 +258,7 @@ async function releaseHeldLock(state, normalizedTargetPath, held, options = {})
257
258
  if (state.held.get(normalizedTargetPath) === held) {
258
259
  state.held.delete(normalizedTargetPath);
259
260
  }
260
- if (held.compromiseTimer) {
261
- clearInterval(held.compromiseTimer);
262
- held.compromiseTimer = undefined;
263
- }
261
+ stopSidecarLockMonitoring(held);
264
262
  })();
265
263
  try {
266
264
  await held.releasePromise;
@@ -1,4 +1,4 @@
1
- import { type BigIntStats } from "node:fs";
1
+ import { type BigIntStats, type Stats } from "node:fs";
2
2
  import type { DirectoryReceipt } from "./directory-durability.js";
3
3
  import type { FileIdentityStat } from "./file-identity.js";
4
4
  import type { NativeBinding } from "./native-binding.js";
@@ -21,7 +21,7 @@ export declare function assertStagedDirectoryCurrent(receipt: StagedDirectorySna
21
21
  export declare function describePolicyStagedDirectory(fd: number, pathname: string, binding?: NativeBinding): PolicyStagedDirectory;
22
22
  export declare function assertPolicyStagedDirectoryCurrent(captured: PolicyStagedDirectory): BigIntStats;
23
23
  export declare function refreshPolicyStagedDirectoryObservation(captured: PolicyStagedDirectory): MutationDirectoryObservation;
24
- export declare function openStagedDirectory(directory: string | DirectoryReceipt): {
24
+ export declare function openStagedDirectory(directory: string | DirectoryReceipt<Stats | BigIntStats>): {
25
25
  fd: number;
26
26
  receipt: StagedDirectorySnapshot;
27
27
  };
@@ -1 +1 @@
1
- {"version":3,"file":"staged-directory.d.ts","sourceRoot":"","sources":["../src/staged-directory.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAE/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAGlE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAEL,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,EAE/B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;AAErE,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,SAAS,EAAE,uBAAuB,CAAC;IACnC,WAAW,EAAE,4BAA4B,CAAC;IAC1C,IAAI,EAAE,WAAW,CAAC;IAClB,cAAc,CAAC,EAAE,yBAAyB,CAAC;IAC3C,kBAAkB,CAAC,IAAI,IAAI,CAAC;CAC7B,CAAC,CAAC;AAEH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,gBAAgB,EAC1B,MAAM,EAAE,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,GAC7C,OAAO,CAKT;AAED,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,uBAAuB,CAY7F;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,uBAAuB,GAAG,WAAW,CAS1F;AASD,wBAAgB,6BAA6B,CAC3C,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,aAAa,GACtB,qBAAqB,CA2CvB;AAED,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,qBAAqB,GAC9B,WAAW,CAeb;AAED,wBAAgB,uCAAuC,CACrD,QAAQ,EAAE,qBAAqB,GAC9B,4BAA4B,CAoB9B;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,GAAG;IACzE,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,uBAAuB,CAAC;CAClC,CAgCA"}
1
+ {"version":3,"file":"staged-directory.d.ts","sourceRoot":"","sources":["../src/staged-directory.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAE3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAGlE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAEL,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,EAE/B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;AAErE,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,SAAS,EAAE,uBAAuB,CAAC;IACnC,WAAW,EAAE,4BAA4B,CAAC;IAC1C,IAAI,EAAE,WAAW,CAAC;IAClB,cAAc,CAAC,EAAE,yBAAyB,CAAC;IAC3C,kBAAkB,CAAC,IAAI,IAAI,CAAC;CAC7B,CAAC,CAAC;AAEH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,gBAAgB,EAC1B,MAAM,EAAE,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,GAC7C,OAAO,CAKT;AAED,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,uBAAuB,CAY7F;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,uBAAuB,GAAG,WAAW,CAS1F;AASD,wBAAgB,6BAA6B,CAC3C,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,aAAa,GACtB,qBAAqB,CA2CvB;AAED,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,qBAAqB,GAC9B,WAAW,CAeb;AAED,wBAAgB,uCAAuC,CACrD,QAAQ,EAAE,qBAAqB,GAC9B,4BAA4B,CAoB9B;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG;IAC9F,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,uBAAuB,CAAC;CAClC,CAgCA"}
@@ -1,6 +1,6 @@
1
1
  import type { BigIntStats } from "node:fs";
2
2
  type ExactFileIdentity = Pick<BigIntStats, "dev" | "ino">;
3
3
  export declare function inspectFileIdentity<T extends ExactFileIdentity>(inspect: () => T | Promise<T>, expected?: ExactFileIdentity, platform?: NodeJS.Platform): Promise<T>;
4
- export declare function inspectFileIdentitySync<T extends ExactFileIdentity>(inspect: () => T, expected?: ExactFileIdentity, platform?: NodeJS.Platform): T;
4
+ export declare function inspectFileIdentitySync<T extends ExactFileIdentity>(inspect: () => T, expected?: ExactFileIdentity, platform?: NodeJS.Platform, mismatch?: () => Error): T;
5
5
  export {};
6
6
  //# sourceMappingURL=strict-file-identity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"strict-file-identity.d.ts","sourceRoot":"","sources":["../src/strict-file-identity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAI3C,KAAK,iBAAiB,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC;AA+B1D,wBAAsB,mBAAmB,CAAC,CAAC,SAAS,iBAAiB,EACnE,OAAO,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAC7B,QAAQ,CAAC,EAAE,iBAAiB,EAC5B,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,OAAO,CAAC,CAAC,CAAC,CAOZ;AAED,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,iBAAiB,EACjE,OAAO,EAAE,MAAM,CAAC,EAChB,QAAQ,CAAC,EAAE,iBAAiB,EAC5B,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,CAAC,CAmCH"}
1
+ {"version":3,"file":"strict-file-identity.d.ts","sourceRoot":"","sources":["../src/strict-file-identity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAI3C,KAAK,iBAAiB,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC;AA+B1D,wBAAsB,mBAAmB,CAAC,CAAC,SAAS,iBAAiB,EACnE,OAAO,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAC7B,QAAQ,CAAC,EAAE,iBAAiB,EAC5B,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,OAAO,CAAC,CAAC,CAAC,CAOZ;AAED,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,iBAAiB,EACjE,OAAO,EAAE,MAAM,CAAC,EAChB,QAAQ,CAAC,EAAE,iBAAiB,EAC5B,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,QAAQ,GAAE,MAAM,KAAwB,GACvC,CAAC,CAmCH"}
@@ -40,19 +40,19 @@ export async function inspectFileIdentity(inspect, expected, platform = process.
40
40
  }
41
41
  throw identityMismatch();
42
42
  }
43
- export function inspectFileIdentitySync(inspect, expected, platform = process.platform) {
43
+ export function inspectFileIdentitySync(inspect, expected, platform = process.platform, mismatch = identityMismatch) {
44
44
  let knownDev;
45
45
  let knownIno;
46
46
  if (expected) {
47
47
  knownDev = expected.dev;
48
48
  if (typeof knownDev !== "bigint")
49
- throw identityMismatch();
49
+ throw mismatch();
50
50
  knownIno = expected.ino;
51
51
  if (typeof knownIno !== "bigint")
52
- throw identityMismatch();
52
+ throw mismatch();
53
53
  // An unknown expected device must not bypass observation of its inode.
54
54
  if (platform === "win32" && (knownDev === 0n || knownIno === 0n))
55
- throw identityMismatch();
55
+ throw mismatch();
56
56
  }
57
57
  for (let attempt = 0; attempt < 2; attempt++) {
58
58
  const stat = inspect();
@@ -61,28 +61,28 @@ export function inspectFileIdentitySync(inspect, expected, platform = process.pl
61
61
  // a checker closure, known-component object, or field array per inspection.
62
62
  const dev = stat.dev;
63
63
  if (typeof dev !== "bigint")
64
- throw identityMismatch();
64
+ throw mismatch();
65
65
  if (platform === "win32" && dev === 0n) {
66
66
  complete = false;
67
67
  }
68
68
  else {
69
69
  if (knownDev !== undefined && knownDev !== dev)
70
- throw identityMismatch();
70
+ throw mismatch();
71
71
  knownDev = dev;
72
72
  }
73
73
  const ino = stat.ino;
74
74
  if (typeof ino !== "bigint")
75
- throw identityMismatch();
75
+ throw mismatch();
76
76
  if (platform === "win32" && ino === 0n) {
77
77
  complete = false;
78
78
  }
79
79
  else {
80
80
  if (knownIno !== undefined && knownIno !== ino)
81
- throw identityMismatch();
81
+ throw mismatch();
82
82
  knownIno = ino;
83
83
  }
84
84
  if (complete)
85
85
  return stat;
86
86
  }
87
- throw identityMismatch();
87
+ throw mismatch();
88
88
  }
@@ -1 +1 @@
1
- {"version":3,"file":"symlink-parents.d.ts","sourceRoot":"","sources":["../src/symlink-parents.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAqCF,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,6BAA6B,GACpC,IAAI,CA6BN"}
1
+ {"version":3,"file":"symlink-parents.d.ts","sourceRoot":"","sources":["../src/symlink-parents.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAqCF,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,6BAA6B,GACpC,IAAI,CA6BN"}
@@ -26,32 +26,7 @@ function formatUnsafePath(params, current) {
26
26
  return `${params.messagePrefix ?? "Path"} must not traverse symlinked directory: ${current}`;
27
27
  }
28
28
  export async function assertNoSymlinkParents(params) {
29
- const walk = resolvePathWalk(params);
30
- if (!walk) {
31
- return;
32
- }
33
- let current = walk.root;
34
- for (const [index, segment] of walk.segments.entries()) {
35
- current = path.join(current, segment);
36
- try {
37
- const stat = fsSync.lstatSync(current);
38
- if (stat.isSymbolicLink()) {
39
- if (params.allowRootChildSymlink && path.dirname(current) === walk.root) {
40
- continue;
41
- }
42
- throw new Error(formatUnsafePath(params, current));
43
- }
44
- if ((params.requireDirectories || index < walk.segments.length - 1) && !stat.isDirectory()) {
45
- throw new FsSafeError("not-file", `${params.messagePrefix ?? "Path"} must traverse directories: ${current}`);
46
- }
47
- }
48
- catch (err) {
49
- if (hasNodeErrorCode(err, "ENOENT") && params.allowMissing !== false) {
50
- return;
51
- }
52
- throw err;
53
- }
54
- }
29
+ assertNoSymlinkParentsSync(params);
55
30
  }
56
31
  export function assertNoSymlinkParentsSync(params) {
57
32
  const walk = resolvePathWalk(params);
@@ -74,7 +49,7 @@ export function assertNoSymlinkParentsSync(params) {
74
49
  }
75
50
  }
76
51
  catch (err) {
77
- if (err.code === "ENOENT" && params.allowMissing !== false) {
52
+ if (hasNodeErrorCode(err, "ENOENT") && params.allowMissing !== false) {
78
53
  return;
79
54
  }
80
55
  throw err;
@@ -58,10 +58,10 @@ export class TempWorkspaceCleanupCapability {
58
58
  try {
59
59
  parent = openTempWorkspaceCleanupParent(root, admission);
60
60
  }
61
- catch {
62
- if (parent)
63
- fsSync.closeSync(parent.fd);
64
- parent = undefined;
61
+ catch (error) {
62
+ // Failed descriptor closure must retain the original admission failure too.
63
+ if (error instanceof AggregateError)
64
+ throw error;
65
65
  }
66
66
  let available = false;
67
67
  if (childModeAllowsRemoval && parent?.access === "read" && isNativeCleanupBinding(binding)) {
@@ -1 +1 @@
1
- {"version":3,"file":"unicode-path.d.ts","sourceRoot":"","sources":["../src/unicode-path.ts"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,UAAQ,GAAG,MAAM,CAUhF"}
1
+ {"version":3,"file":"unicode-path.d.ts","sourceRoot":"","sources":["../src/unicode-path.ts"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,UAAQ,GAAG,MAAM,CAYhF"}
@@ -3,6 +3,9 @@ export function lowerCaseNfc(value) {
3
3
  return NON_ASCII.test(value) ? value.normalize("NFC").toLowerCase().normalize("NFC") : value.toLowerCase();
4
4
  }
5
5
  export function maxNormalizedUtf8Bytes(value, includeRaw = false) {
6
+ // ASCII has identical raw, NFC and NFD forms, with one UTF-8 byte per unit.
7
+ if (typeof value === "string" && !NON_ASCII.test(value))
8
+ return value.length;
6
9
  const nfc = value.normalize("NFC");
7
10
  const bytes = Buffer.byteLength(nfc, "utf8");
8
11
  const maximum = includeRaw && nfc !== value ? Math.max(bytes, Buffer.byteLength(value, "utf8")) : bytes;
@@ -1 +1 @@
1
- {"version":3,"file":"walk.d.ts","sourceRoot":"","sources":["../src/walk.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAC;AAS7B,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;AACvE,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE9D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC;IACjD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAAC,oBAAoB,EAAE,SAAS,GAAG,SAAS,CAAC,GAAG;IAC1F,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACrE,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IAGnB,UAAU,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACrC,CAAC;AAEF,KAAK,+BAA+B,GAAG,mBAAmB,GAAG;IAC3D,UAAU,EAAE,oBAAoB,EAAE,CAAC;CACpC,CAAC;AAoFF,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,oBAAyB,GACjC,+BAA+B,CA4DjC;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,+BAA+B,CAAC,CAiE1C"}
1
+ {"version":3,"file":"walk.d.ts","sourceRoot":"","sources":["../src/walk.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAC;AAS7B,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;AACvE,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE9D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC;IACjD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAAC,oBAAoB,EAAE,SAAS,GAAG,SAAS,CAAC,GAAG;IAC1F,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACrE,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IAGnB,UAAU,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACrC,CAAC;AAEF,KAAK,+BAA+B,GAAG,mBAAmB,GAAG;IAC3D,UAAU,EAAE,oBAAoB,EAAE,CAAC;CACpC,CAAC;AAoFF,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,oBAAyB,GACjC,+BAA+B,CA6DjC;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,+BAA+B,CAAC,CAkE1C"}
package/dist/walk.js CHANGED
@@ -108,13 +108,14 @@ export function walkDirectorySync(rootDir, options = {}) {
108
108
  recordFailedDir(result, root, dir, depth, error);
109
109
  return;
110
110
  }
111
+ const childPrefix = dir.endsWith(path.sep) ? dir : `${dir}${path.sep}`;
111
112
  for (const dirent of entries) {
112
113
  if (shouldStop(result, options)) {
113
114
  result.truncated = true;
114
115
  return;
115
116
  }
116
117
  result.scannedEntryCount += 1;
117
- const fullPath = path.join(dir, dirent.name);
118
+ const fullPath = childPrefix + dirent.name;
118
119
  const kind = resolveKind(fullPath, dirent, symlinks);
119
120
  if (!kind)
120
121
  continue;
@@ -171,13 +172,14 @@ export async function walkDirectory(rootDir, options = {}) {
171
172
  recordFailedDir(result, root, dir, depth, error);
172
173
  return;
173
174
  }
175
+ const childPrefix = dir.endsWith(path.sep) ? dir : `${dir}${path.sep}`;
174
176
  for (const dirent of entries) {
175
177
  if (shouldStop(result, options)) {
176
178
  result.truncated = true;
177
179
  return;
178
180
  }
179
181
  result.scannedEntryCount += 1;
180
- const fullPath = path.join(dir, dirent.name);
182
+ const fullPath = childPrefix + dirent.name;
181
183
  const kind = resolveKind(fullPath, dirent, symlinks);
182
184
  if (!kind)
183
185
  continue;
@@ -1,4 +1,11 @@
1
1
  import type { FileHandle } from "node:fs/promises";
2
+ export type WriteFileWindowOptions = {
3
+ signal?: AbortSignal;
4
+ /** Synchronous authority check immediately before every write, including short-write retries. */
5
+ assertBeforeMutation?: () => void;
6
+ };
7
+ /** Write borrowed bytes completely; null advances the cursor, an explicit position preserves it. */
8
+ export declare function writeFileWindowFully(handle: FileHandle, bytes: Uint8Array, position: number | null, options?: WriteFileWindowOptions): Promise<void>;
2
9
  export declare function writeAllToFile(target: FileHandle | number, data: string | Uint8Array, options?: {
3
10
  encoding?: BufferEncoding;
4
11
  position?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"write-file-handle.d.ts","sourceRoot":"","sources":["../src/write-file-handle.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAKnD,wBAAsB,cAAc,CAClC,MAAM,EAAE,UAAU,GAAG,MAAM,EAC3B,IAAI,EAAE,MAAM,GAAG,UAAU,EACzB,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAA;CAAO,GAChG,OAAO,CAAC,IAAI,CAAC,CAoBf"}
1
+ {"version":3,"file":"write-file-handle.d.ts","sourceRoot":"","sources":["../src/write-file-handle.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAOnD,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,iGAAiG;IACjG,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;CACnC,CAAC;AAEF,oGAAoG;AACpG,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,UAAU,GAAG,MAAM,EAC3B,IAAI,EAAE,MAAM,GAAG,UAAU,EACzB,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAA;CAAO,GAChG,OAAO,CAAC,IAAI,CAAC,CAoBf"}
@@ -1,6 +1,29 @@
1
1
  import fs from "node:fs";
2
+ import { snapshotByteView } from "./byte-view.js";
2
3
  import { FsSafeError } from "./errors.js";
4
+ import { assertSynchronousCallbackResult } from "./mutation-authority.js";
3
5
  const WRITE_CHUNK_BYTES = 512 * 1024;
6
+ /** Write borrowed bytes completely; null advances the cursor, an explicit position preserves it. */
7
+ export async function writeFileWindowFully(handle, bytes, position, options = {}) {
8
+ const payload = snapshotByteView(bytes);
9
+ if (position !== null && (!Number.isSafeInteger(position) || position < 0 ||
10
+ !Number.isSafeInteger(position + payload.byteLength))) {
11
+ throw new RangeError("write position and window end must be non-negative safe integers");
12
+ }
13
+ const signal = options.signal;
14
+ const assertion = options.assertBeforeMutation;
15
+ signal?.throwIfAborted();
16
+ await writeAllToFile(handle, payload, {
17
+ position: position === null ? undefined : position,
18
+ assertBeforeMutation: () => {
19
+ signal?.throwIfAborted();
20
+ assertSynchronousCallbackResult(assertion === undefined ? undefined : Reflect.apply(assertion, options, []), "assertBeforeMutation");
21
+ signal?.throwIfAborted();
22
+ },
23
+ });
24
+ // A pending write must settle before cancellation releases the caller's buffer and handle.
25
+ signal?.throwIfAborted();
26
+ }
4
27
  export async function writeAllToFile(target, data, options = {}) {
5
28
  const buffer = typeof data === "string" ? Buffer.from(data, options.encoding ?? "utf8") : data;
6
29
  let offset = 0;
@@ -1 +1 @@
1
- {"version":3,"file":"write-open-flags.d.ts","sourceRoot":"","sources":["../src/write-open-flags.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAC;AAG7B,wBAAgB,2BAA2B,CACzC,SAAS,GAAE,OAAO,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,CAAoB,GACjF,MAAM,CAIR;AAUD,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAOT"}
1
+ {"version":3,"file":"write-open-flags.d.ts","sourceRoot":"","sources":["../src/write-open-flags.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAC;AAG7B,wBAAgB,2BAA2B,CACzC,SAAS,GAAE,OAAO,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,CAAoB,GACjF,MAAM,CAIR;AAUD,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CAElB;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAOT"}
@@ -13,14 +13,7 @@ function isNonblockingWriteEnxio(error, flags) {
13
13
  // A no-reader FIFO rejects a nonblocking write-only open before fstat is possible.
14
14
  // Reclassify only a confirmed non-regular path; inconclusive races keep the errno.
15
15
  export async function isNonRegularWriteOpenError(error, filePath, flags) {
16
- if (!isNonblockingWriteEnxio(error, flags))
17
- return false;
18
- try {
19
- return !fsSync.lstatSync(filePath).isFile();
20
- }
21
- catch {
22
- return false;
23
- }
16
+ return isNonRegularWriteOpenErrorSync(error, filePath, flags);
24
17
  }
25
18
  export function isNonRegularWriteOpenErrorSync(error, filePath, flags) {
26
19
  if (!isNonblockingWriteEnxio(error, flags))
@@ -1 +1 @@
1
- {"version":3,"file":"write-queue.d.ts","sourceRoot":"","sources":["../src/write-queue.ts"],"names":[],"mappings":"AAEA,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAkB1F"}
1
+ {"version":3,"file":"write-queue.d.ts","sourceRoot":"","sources":["../src/write-queue.ts"],"names":[],"mappings":"AAEA,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAe1F"}
@@ -1,10 +1,7 @@
1
1
  const writeQueues = new Map();
2
2
  export async function serializePathWrite(key, run) {
3
3
  const previous = writeQueues.get(key) ?? Promise.resolve();
4
- const task = (async () => {
5
- await previous.catch(() => undefined);
6
- return await run();
7
- })();
4
+ const task = previous.then(() => run());
8
5
  const done = task.then(() => undefined, () => undefined);
9
6
  writeQueues.set(key, done);
10
7
  try {