@openclaw/fs-safe 0.16.0 → 0.18.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 (705) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/README.md +8 -1
  3. package/dist/absolute-path.d.ts +0 -1
  4. package/dist/absolute-path.js +2 -8
  5. package/dist/advanced.d.ts +2 -1
  6. package/dist/advanced.js +2 -0
  7. package/dist/archive-crc32.d.ts +0 -1
  8. package/dist/archive-deadline.d.ts +0 -1
  9. package/dist/archive-deadline.js +22 -23
  10. package/dist/archive-durability.d.ts +0 -1
  11. package/dist/archive-entry.d.ts +0 -1
  12. package/dist/archive-errors.d.ts +0 -1
  13. package/dist/archive-gzip-tail.d.ts +0 -1
  14. package/dist/archive-input.d.ts +0 -1
  15. package/dist/archive-kind.d.ts +0 -1
  16. package/dist/archive-limits.d.ts +0 -1
  17. package/dist/archive-merge.d.ts +3 -4
  18. package/dist/archive-merge.js +17 -7
  19. package/dist/archive-native.d.ts +3 -14
  20. package/dist/archive-native.js +46 -70
  21. package/dist/archive-options.d.ts +9 -2
  22. package/dist/archive-parser-errors.d.ts +0 -1
  23. package/dist/archive-parser.wasm +0 -0
  24. package/dist/archive-plan.d.ts +10 -1
  25. package/dist/archive-plan.js +31 -21
  26. package/dist/archive-policy.d.ts +0 -1
  27. package/dist/archive-read.d.ts +0 -1
  28. package/dist/archive-staging.d.ts +0 -1
  29. package/dist/archive-tar-inspect.d.ts +0 -1
  30. package/dist/archive-tar-stream.d.ts +0 -1
  31. package/dist/archive-tar-wasm.d.ts +0 -1
  32. package/dist/archive-tar.d.ts +0 -1
  33. package/dist/archive-zip-admission.d.ts +0 -1
  34. package/dist/archive-zip-count.d.ts +0 -1
  35. package/dist/archive-zip-count.js +21 -1
  36. package/dist/archive-zip-directory.d.ts +0 -1
  37. package/dist/archive-zip-directory.js +23 -1
  38. package/dist/archive-zip-entry.d.ts +0 -1
  39. package/dist/archive-zip-integrity.d.ts +0 -1
  40. package/dist/archive-zip-loader.d.ts +2 -1
  41. package/dist/archive-zip-loader.js +7 -0
  42. package/dist/archive-zip-manifest.d.ts +0 -1
  43. package/dist/archive-zip-names.d.ts +0 -1
  44. package/dist/archive-zip-names.js +7 -2
  45. package/dist/archive-zip-preflight.d.ts +0 -1
  46. package/dist/archive.d.ts +0 -1
  47. package/dist/archive.js +93 -164
  48. package/dist/async-lock.d.ts +0 -1
  49. package/dist/atomic.d.ts +0 -1
  50. package/dist/bounded-read-stream.d.ts +0 -1
  51. package/dist/bounded-read.d.ts +0 -1
  52. package/dist/byte-budget.d.ts +0 -1
  53. package/dist/byte-view.d.ts +2 -0
  54. package/dist/byte-view.js +13 -0
  55. package/dist/clone-metadata.d.ts +0 -1
  56. package/dist/config.d.ts +0 -1
  57. package/dist/containment.d.ts +0 -1
  58. package/dist/copy-file-input.d.ts +0 -1
  59. package/dist/copy-policy.d.ts +0 -1
  60. package/dist/copy-publication.d.ts +0 -1
  61. package/dist/copy-tree-portable.d.ts +0 -1
  62. package/dist/copy-tree-portable.js +9 -6
  63. package/dist/copy.d.ts +0 -1
  64. package/dist/copy.js +5 -5
  65. package/dist/create-directory.d.ts +0 -2
  66. package/dist/create-directory.js +3 -22
  67. package/dist/create-file-async.d.ts +0 -1
  68. package/dist/create-file.d.ts +0 -1
  69. package/dist/create-file.js +3 -14
  70. package/dist/create-owned-file.d.ts +0 -1
  71. package/dist/create.d.ts +1 -2
  72. package/dist/create.js +1 -1
  73. package/dist/creation-darwin.d.ts +0 -2
  74. package/dist/creation-darwin.js +0 -9
  75. package/dist/creation-file-state.d.ts +0 -1
  76. package/dist/creation-path.d.ts +2 -1
  77. package/dist/creation-path.js +12 -0
  78. package/dist/creation-permissions.d.ts +0 -1
  79. package/dist/creation-permissions.js +28 -38
  80. package/dist/deny-mutations.d.ts +2 -3
  81. package/dist/deny-mutations.js +55 -35
  82. package/dist/device-path.d.ts +0 -1
  83. package/dist/directory-durability.d.ts +6 -7
  84. package/dist/directory-entry-path.d.ts +0 -1
  85. package/dist/directory-guard.d.ts +2 -7
  86. package/dist/directory-guard.js +25 -56
  87. package/dist/directory-mode-node.d.ts +0 -1
  88. package/dist/directory-mode-owner.d.ts +0 -1
  89. package/dist/directory-receipt.d.ts +2 -3
  90. package/dist/directory-receipt.js +15 -19
  91. package/dist/durability.d.ts +0 -1
  92. package/dist/effective-uid.d.ts +0 -1
  93. package/dist/error-detail.d.ts +0 -1
  94. package/dist/errors.d.ts +0 -1
  95. package/dist/file-cleanup.d.ts +1 -1
  96. package/dist/file-cleanup.js +7 -4
  97. package/dist/file-contents.d.ts +5 -0
  98. package/dist/file-contents.js +40 -0
  99. package/dist/file-handle-transfer.d.ts +0 -1
  100. package/dist/file-hash.d.ts +0 -1
  101. package/dist/file-hash.js +186 -70
  102. package/dist/file-identity.d.ts +0 -1
  103. package/dist/file-lock-sync-acquisition.d.ts +22 -0
  104. package/dist/file-lock-sync-acquisition.js +98 -0
  105. package/dist/file-lock-sync-admission.d.ts +0 -2
  106. package/dist/file-lock-sync-admission.js +9 -48
  107. package/dist/file-lock-sync-root-acquire.d.ts +0 -1
  108. package/dist/file-lock-sync-root-acquire.js +35 -98
  109. package/dist/file-lock-sync-root-arbitration.d.ts +0 -1
  110. package/dist/file-lock-sync-root-held.d.ts +1 -3
  111. package/dist/file-lock-sync-root-held.js +7 -5
  112. package/dist/file-lock-sync-root-io.d.ts +0 -1
  113. package/dist/file-lock-sync-root-mutation.d.ts +4 -5
  114. package/dist/file-lock-sync-root-mutation.js +7 -9
  115. package/dist/file-lock-sync-root-options.d.ts +0 -1
  116. package/dist/file-lock-sync-root-registration.d.ts +0 -1
  117. package/dist/file-lock-sync-root.d.ts +1 -2
  118. package/dist/file-lock-sync-root.js +14 -87
  119. package/dist/file-lock-sync-stale-admission.d.ts +2 -7
  120. package/dist/file-lock-sync-stale-admission.js +24 -23
  121. package/dist/file-lock-sync.d.ts +0 -1
  122. package/dist/file-lock-sync.js +46 -128
  123. package/dist/file-lock.d.ts +0 -1
  124. package/dist/file-observation.d.ts +0 -1
  125. package/dist/file-store-boundary.d.ts +0 -2
  126. package/dist/file-store-boundary.js +6 -26
  127. package/dist/file-store-copy-source.d.ts +1 -2
  128. package/dist/file-store-copy-source.js +1 -1
  129. package/dist/file-store-limit.d.ts +1 -2
  130. package/dist/file-store-limit.js +2 -3
  131. package/dist/file-store-path.d.ts +0 -1
  132. package/dist/file-store-prune.d.ts +0 -1
  133. package/dist/file-store-sync-directory.d.ts +0 -1
  134. package/dist/file-store-sync-directory.js +194 -231
  135. package/dist/file-store-sync-write.d.ts +0 -1
  136. package/dist/file-store-sync-write.js +16 -26
  137. package/dist/file-store.d.ts +0 -1
  138. package/dist/file-store.js +6 -7
  139. package/dist/file-sync.d.ts +0 -1
  140. package/dist/filename.d.ts +0 -1
  141. package/dist/filename.js +1 -7
  142. package/dist/fs.d.ts +0 -1
  143. package/dist/guarded-mkdir.d.ts +0 -1
  144. package/dist/guarded-mkdir.js +6 -27
  145. package/dist/guarded-mutation.d.ts +0 -7
  146. package/dist/guarded-mutation.js +6 -11
  147. package/dist/guest-dispatch-python.d.ts +0 -1
  148. package/dist/guest-dispatch-python.js +41 -90
  149. package/dist/guest-native-python.d.ts +0 -1
  150. package/dist/guest.d.ts +0 -1
  151. package/dist/home-dir.d.ts +0 -1
  152. package/dist/index.d.ts +0 -1
  153. package/dist/install-path.d.ts +0 -1
  154. package/dist/install-path.js +2 -5
  155. package/dist/json-document-store.d.ts +0 -1
  156. package/dist/json-durable-queue-directory.d.ts +13 -1
  157. package/dist/json-durable-queue-directory.js +134 -0
  158. package/dist/json-durable-queue-ownership.d.ts +0 -1
  159. package/dist/json-durable-queue-ownership.js +43 -66
  160. package/dist/json-durable-queue-read.d.ts +0 -1
  161. package/dist/json-durable-queue-read.js +6 -6
  162. package/dist/json-durable-queue.d.ts +0 -1
  163. package/dist/json-durable-queue.js +17 -139
  164. package/dist/json-store.d.ts +0 -1
  165. package/dist/json-stringify.d.ts +0 -1
  166. package/dist/json.d.ts +0 -1
  167. package/dist/json.js +38 -90
  168. package/dist/local-file-access.d.ts +0 -1
  169. package/dist/local-file-access.js +3 -10
  170. package/dist/local-file-descriptor.d.ts +0 -1
  171. package/dist/local-roots.d.ts +0 -1
  172. package/dist/local-roots.js +19 -21
  173. package/dist/lock-config.d.ts +0 -1
  174. package/dist/move-path-cleanup.d.ts +5 -20
  175. package/dist/move-path-cleanup.js +57 -21
  176. package/dist/move-path-stage.d.ts +0 -1
  177. package/dist/move-path.d.ts +0 -1
  178. package/dist/move-path.js +62 -39
  179. package/dist/mutation-authority.d.ts +0 -1
  180. package/dist/native-binding.d.ts +0 -1
  181. package/dist/native-config.d.ts +0 -1
  182. package/dist/native-directory-observation.d.ts +0 -1
  183. package/dist/native-fallback-warning.d.ts +0 -1
  184. package/dist/native-operations.d.ts +1 -5
  185. package/dist/native-operations.js +2 -6
  186. package/dist/native-parent-admission.d.ts +0 -1
  187. package/dist/native-pinned-write-windows.d.ts +0 -1
  188. package/dist/native-pinned-write.d.ts +0 -1
  189. package/dist/native-pinned-write.js +4 -10
  190. package/dist/native-policy-directory-observation.d.ts +0 -1
  191. package/dist/native-policy-parent-windows.d.ts +0 -1
  192. package/dist/native-rename-outcome.d.ts +0 -1
  193. package/dist/native-staged-file.d.ts +17 -4
  194. package/dist/native-staged-file.js +63 -68
  195. package/dist/native.d.ts +0 -1
  196. package/dist/native.js +2 -2
  197. package/dist/opened-file-failure.d.ts +0 -1
  198. package/dist/opened-realpath.d.ts +0 -1
  199. package/dist/opened-realpath.js +11 -2
  200. package/dist/output.d.ts +0 -1
  201. package/dist/overwrite-file-handle.d.ts +0 -1
  202. package/dist/owner-dacl.d.ts +0 -1
  203. package/dist/path-case.d.ts +0 -1
  204. package/dist/path-policy.d.ts +0 -1
  205. package/dist/path-prefix.d.ts +0 -1
  206. package/dist/path-scope-lexical.d.ts +0 -1
  207. package/dist/path-segment-route.d.ts +0 -1
  208. package/dist/path-suffix-aliases.d.ts +0 -1
  209. package/dist/path.d.ts +0 -1
  210. package/dist/path.js +2 -1
  211. package/dist/permission-exec.d.ts +0 -1
  212. package/dist/permission-exec.js +19 -25
  213. package/dist/permissions-public.d.ts +0 -1
  214. package/dist/permissions-windows.d.ts +2 -10
  215. package/dist/permissions-windows.js +10 -30
  216. package/dist/permissions.d.ts +0 -1
  217. package/dist/permissions.js +11 -33
  218. package/dist/pinned-mutation-admission.d.ts +0 -1
  219. package/dist/pinned-mutation-observation.d.ts +0 -1
  220. package/dist/pinned-mutation-shared-route.d.ts +0 -1
  221. package/dist/pinned-open.d.ts +1 -1
  222. package/dist/pinned-open.js +1 -1
  223. package/dist/pinned-operation.d.ts +0 -1
  224. package/dist/pinned-write-input.d.ts +0 -1
  225. package/dist/pinned-write-input.js +11 -1
  226. package/dist/pinned-write-mode.d.ts +3 -4
  227. package/dist/pinned-write-mode.js +15 -8
  228. package/dist/pinned-write-staged.d.ts +0 -1
  229. package/dist/pinned-write-staged.js +10 -11
  230. package/dist/pinned-write-types.d.ts +9 -21
  231. package/dist/pinned-write.d.ts +0 -1
  232. package/dist/pinned-write.js +17 -13
  233. package/dist/positional-read.d.ts +0 -1
  234. package/dist/private-directory.d.ts +0 -1
  235. package/dist/private-producer-handoff-sync.d.ts +0 -1
  236. package/dist/private-producer-handoff-sync.js +9 -51
  237. package/dist/private-producer-handoff.d.ts +20 -1
  238. package/dist/private-producer-handoff.js +69 -46
  239. package/dist/private-temp-workspace.d.ts +0 -1
  240. package/dist/private-temp-workspace.js +11 -36
  241. package/dist/publish-copy-stage.d.ts +0 -1
  242. package/dist/publish-file-failure.d.ts +0 -1
  243. package/dist/publish-file.d.ts +2 -3
  244. package/dist/publish-file.js +56 -96
  245. package/dist/read-open-flags.d.ts +0 -1
  246. package/dist/read-opened-file.d.ts +0 -1
  247. package/dist/realpath.d.ts +0 -1
  248. package/dist/recursive-mkdir-path.d.ts +0 -1
  249. package/dist/regular-file.d.ts +0 -1
  250. package/dist/regular-file.js +107 -178
  251. package/dist/replace-directory.d.ts +0 -1
  252. package/dist/replace-file-copy-fallback.d.ts +0 -1
  253. package/dist/replace-file-copy-fallback.js +42 -29
  254. package/dist/replace-file-copy-source.d.ts +0 -1
  255. package/dist/replace-file-copy-source.js +19 -23
  256. package/dist/replace-file-descriptor.d.ts +0 -1
  257. package/dist/replace-file-descriptor.js +16 -17
  258. package/dist/replace-file-mode.d.ts +0 -1
  259. package/dist/replace-file-rename-policy.d.ts +0 -1
  260. package/dist/replace-file-temp-owner.d.ts +12 -13
  261. package/dist/replace-file-temp-owner.js +72 -91
  262. package/dist/replace-file.d.ts +0 -1
  263. package/dist/replace-file.js +9 -13
  264. package/dist/retained-directory-replacement.d.ts +0 -1
  265. package/dist/root-boundary.d.ts +0 -1
  266. package/dist/root-context.d.ts +0 -1
  267. package/dist/root-create-input.d.ts +0 -1
  268. package/dist/root-directory-creation.d.ts +0 -1
  269. package/dist/root-directory-list.d.ts +0 -1
  270. package/dist/root-directory-list.js +20 -3
  271. package/dist/root-directory.d.ts +0 -1
  272. package/dist/root-entries.d.ts +0 -1
  273. package/dist/root-errors.d.ts +0 -1
  274. package/dist/root-file-final-admission.d.ts +1 -2
  275. package/dist/root-file-final-admission.js +5 -2
  276. package/dist/root-file.d.ts +0 -1
  277. package/dist/root-file.js +3 -2
  278. package/dist/root-impl.d.ts +2 -10
  279. package/dist/root-impl.js +164 -111
  280. package/dist/root-move-noreplace.d.ts +2 -1
  281. package/dist/root-move-noreplace.js +2 -2
  282. package/dist/root-move-preflight.d.ts +0 -1
  283. package/dist/root-observed-path.d.ts +0 -1
  284. package/dist/root-options.d.ts +0 -1
  285. package/dist/root-path-errors.d.ts +0 -1
  286. package/dist/root-path-existing.d.ts +3 -1
  287. package/dist/root-path-existing.js +39 -18
  288. package/dist/root-path-observation.d.ts +0 -1
  289. package/dist/root-path-stat.d.ts +0 -1
  290. package/dist/root-path.d.ts +0 -1
  291. package/dist/root-path.js +60 -188
  292. package/dist/root-paths-lexical.d.ts +0 -1
  293. package/dist/root-paths.d.ts +0 -1
  294. package/dist/root-read-admission.d.ts +0 -1
  295. package/dist/root-read-admission.js +31 -39
  296. package/dist/root-remove-identity.d.ts +0 -1
  297. package/dist/root-remove-receipt.d.ts +0 -1
  298. package/dist/root-remove.d.ts +0 -1
  299. package/dist/root-remove.js +15 -1
  300. package/dist/root-symlink-policy.d.ts +0 -1
  301. package/dist/root-walk.d.ts +0 -1
  302. package/dist/root-write-admission.d.ts +0 -1
  303. package/dist/root-write-compatibility.d.ts +0 -1
  304. package/dist/root-write-complete-parent.d.ts +0 -1
  305. package/dist/root-write-lock-binding.d.ts +0 -1
  306. package/dist/root-write-mode.d.ts +0 -1
  307. package/dist/root-write-publication.d.ts +0 -1
  308. package/dist/root-write-verification.d.ts +0 -1
  309. package/dist/root.d.ts +0 -1
  310. package/dist/safe-path-segment.d.ts +1 -2
  311. package/dist/safe-path-segment.js +2 -5
  312. package/dist/secret-file.d.ts +0 -1
  313. package/dist/secret-file.js +7 -17
  314. package/dist/secret-read-async.d.ts +0 -1
  315. package/dist/secret-read-async.js +5 -5
  316. package/dist/secret-read-policy.d.ts +0 -1
  317. package/dist/secret.d.ts +0 -1
  318. package/dist/secure-file-windows.d.ts +0 -6
  319. package/dist/secure-file-windows.js +13 -28
  320. package/dist/secure-file.d.ts +0 -1
  321. package/dist/secure-file.js +9 -9
  322. package/dist/secure-temp-dir.d.ts +0 -1
  323. package/dist/secure-temp-repair.d.ts +0 -1
  324. package/dist/sibling-staged-file.d.ts +0 -1
  325. package/dist/sibling-staged-file.js +32 -39
  326. package/dist/sibling-temp.d.ts +0 -1
  327. package/dist/sidecar-lock-acquire.d.ts +1 -2
  328. package/dist/sidecar-lock-acquire.js +35 -58
  329. package/dist/sidecar-lock-admission-context.d.ts +0 -1
  330. package/dist/sidecar-lock-admission-parser.d.ts +0 -1
  331. package/dist/sidecar-lock-admission.d.ts +1 -5
  332. package/dist/sidecar-lock-admission.js +1 -7
  333. package/dist/sidecar-lock-handle.d.ts +3 -1
  334. package/dist/sidecar-lock-handle.js +6 -0
  335. package/dist/sidecar-lock-policy.d.ts +3 -1
  336. package/dist/sidecar-lock-policy.js +16 -0
  337. package/dist/sidecar-lock-reclaim.d.ts +1 -2
  338. package/dist/sidecar-lock-reclaim.js +11 -8
  339. package/dist/sidecar-lock-registration.d.ts +13 -0
  340. package/dist/sidecar-lock-registration.js +47 -0
  341. package/dist/sidecar-lock-root.d.ts +0 -1
  342. package/dist/sidecar-lock-stale-admission.d.ts +0 -1
  343. package/dist/sidecar-lock-target.d.ts +0 -1
  344. package/dist/sidecar-lock-types.d.ts +0 -1
  345. package/dist/sidecar-lock.d.ts +0 -1
  346. package/dist/sidecar-lock.js +19 -88
  347. package/dist/staged-directory.d.ts +2 -3
  348. package/dist/staged-file-settlement.d.ts +0 -1
  349. package/dist/staged-file-types.d.ts +0 -1
  350. package/dist/standalone-publication-path.d.ts +0 -1
  351. package/dist/stat-observation.d.ts +0 -1
  352. package/dist/store.d.ts +0 -1
  353. package/dist/strict-file-identity.d.ts +1 -2
  354. package/dist/strict-file-identity.js +9 -9
  355. package/dist/string-coerce.d.ts +0 -1
  356. package/dist/suppressed-error.d.ts +0 -1
  357. package/dist/symlink-parents.d.ts +0 -1
  358. package/dist/symlink-parents.js +2 -27
  359. package/dist/temp-cleanup.d.ts +0 -1
  360. package/dist/temp-target.d.ts +0 -1
  361. package/dist/temp-target.js +7 -46
  362. package/dist/temp-workspace-admission.d.ts +0 -8
  363. package/dist/temp-workspace-admission.js +0 -4
  364. package/dist/temp-workspace-child-admission.d.ts +0 -4
  365. package/dist/temp-workspace-child-admission.js +0 -12
  366. package/dist/temp-workspace-descriptor.d.ts +0 -6
  367. package/dist/temp-workspace-descriptor.js +0 -2
  368. package/dist/temp-workspace-identity.d.ts +0 -1
  369. package/dist/temp-workspace-owner.d.ts +1 -1
  370. package/dist/temp-workspace-owner.js +49 -26
  371. package/dist/temp-workspace-permissions.d.ts +0 -1
  372. package/dist/temp-workspace-types.d.ts +0 -1
  373. package/dist/temp.d.ts +0 -1
  374. package/dist/test-hooks.d.ts +0 -1
  375. package/dist/text-atomic.d.ts +0 -1
  376. package/dist/timing.d.ts +0 -1
  377. package/dist/trash.d.ts +0 -1
  378. package/dist/types.d.ts +0 -1
  379. package/dist/unicode-path.d.ts +0 -1
  380. package/dist/unicode-path.js +3 -0
  381. package/dist/walk.d.ts +0 -1
  382. package/dist/walk.js +4 -2
  383. package/dist/windows-command.d.ts +0 -1
  384. package/dist/windows-owner.d.ts +0 -1
  385. package/dist/windows-owner.js +4 -1
  386. package/dist/windows-path-alias.d.ts +0 -1
  387. package/dist/windows-path-alias.js +7 -43
  388. package/dist/windows-path-syntax.d.ts +5 -0
  389. package/dist/windows-path-syntax.js +21 -0
  390. package/dist/windows-security-command.d.ts +0 -1
  391. package/dist/windows-security-facts.d.ts +0 -1
  392. package/dist/write-file-handle.d.ts +7 -1
  393. package/dist/write-file-handle.js +23 -0
  394. package/dist/write-open-flags.d.ts +0 -1
  395. package/dist/write-open-flags.js +1 -8
  396. package/dist/write-queue.d.ts +0 -1
  397. package/dist/write-queue.js +1 -4
  398. package/docs/advanced.md +68 -1
  399. package/docs/archive.md +41 -2
  400. package/docs/atomic.md +43 -5
  401. package/docs/contributing.md +4 -0
  402. package/docs/copy.md +2 -0
  403. package/docs/creation.md +8 -4
  404. package/docs/durability.md +35 -0
  405. package/docs/file-contents.md +68 -0
  406. package/docs/json.md +5 -4
  407. package/docs/local-roots.md +2 -0
  408. package/docs/mutation-policy-proof.md +11 -7
  409. package/docs/native.md +9 -8
  410. package/docs/path.md +4 -4
  411. package/docs/permissions.md +6 -0
  412. package/docs/public-api.md +5 -0
  413. package/docs/quickstart.md +1 -1
  414. package/docs/reading.md +2 -2
  415. package/docs/regular-file.md +3 -0
  416. package/docs/root.md +19 -0
  417. package/docs/secret-file.md +4 -0
  418. package/docs/sidecar-lock.md +9 -1
  419. package/docs/staged-file.md +4 -3
  420. package/docs/store.md +3 -1
  421. package/docs/temp.md +4 -1
  422. package/docs/types.md +18 -2
  423. package/docs/walk.md +7 -0
  424. package/docs/writing.md +18 -5
  425. package/package.json +8 -9
  426. package/dist/absolute-path.d.ts.map +0 -1
  427. package/dist/advanced.d.ts.map +0 -1
  428. package/dist/archive-crc32.d.ts.map +0 -1
  429. package/dist/archive-deadline.d.ts.map +0 -1
  430. package/dist/archive-durability.d.ts.map +0 -1
  431. package/dist/archive-entry.d.ts.map +0 -1
  432. package/dist/archive-errors.d.ts.map +0 -1
  433. package/dist/archive-gzip-tail.d.ts.map +0 -1
  434. package/dist/archive-input.d.ts.map +0 -1
  435. package/dist/archive-kind.d.ts.map +0 -1
  436. package/dist/archive-limits.d.ts.map +0 -1
  437. package/dist/archive-merge.d.ts.map +0 -1
  438. package/dist/archive-native.d.ts.map +0 -1
  439. package/dist/archive-options.d.ts.map +0 -1
  440. package/dist/archive-parser-errors.d.ts.map +0 -1
  441. package/dist/archive-plan.d.ts.map +0 -1
  442. package/dist/archive-policy.d.ts.map +0 -1
  443. package/dist/archive-read.d.ts.map +0 -1
  444. package/dist/archive-staging.d.ts.map +0 -1
  445. package/dist/archive-tar-inspect.d.ts.map +0 -1
  446. package/dist/archive-tar-stream.d.ts.map +0 -1
  447. package/dist/archive-tar-wasm.d.ts.map +0 -1
  448. package/dist/archive-tar.d.ts.map +0 -1
  449. package/dist/archive-zip-admission.d.ts.map +0 -1
  450. package/dist/archive-zip-count.d.ts.map +0 -1
  451. package/dist/archive-zip-directory.d.ts.map +0 -1
  452. package/dist/archive-zip-entry.d.ts.map +0 -1
  453. package/dist/archive-zip-integrity.d.ts.map +0 -1
  454. package/dist/archive-zip-loader.d.ts.map +0 -1
  455. package/dist/archive-zip-manifest.d.ts.map +0 -1
  456. package/dist/archive-zip-names.d.ts.map +0 -1
  457. package/dist/archive-zip-preflight.d.ts.map +0 -1
  458. package/dist/archive.d.ts.map +0 -1
  459. package/dist/async-lock.d.ts.map +0 -1
  460. package/dist/atomic.d.ts.map +0 -1
  461. package/dist/bounded-read-stream.d.ts.map +0 -1
  462. package/dist/bounded-read.d.ts.map +0 -1
  463. package/dist/byte-budget.d.ts.map +0 -1
  464. package/dist/clone-metadata.d.ts.map +0 -1
  465. package/dist/config.d.ts.map +0 -1
  466. package/dist/containment.d.ts.map +0 -1
  467. package/dist/copy-file-input.d.ts.map +0 -1
  468. package/dist/copy-policy.d.ts.map +0 -1
  469. package/dist/copy-publication.d.ts.map +0 -1
  470. package/dist/copy-tree-portable.d.ts.map +0 -1
  471. package/dist/copy.d.ts.map +0 -1
  472. package/dist/create-directory.d.ts.map +0 -1
  473. package/dist/create-file-async.d.ts.map +0 -1
  474. package/dist/create-file.d.ts.map +0 -1
  475. package/dist/create-owned-file.d.ts.map +0 -1
  476. package/dist/create.d.ts.map +0 -1
  477. package/dist/creation-darwin.d.ts.map +0 -1
  478. package/dist/creation-file-state.d.ts.map +0 -1
  479. package/dist/creation-path.d.ts.map +0 -1
  480. package/dist/creation-permissions.d.ts.map +0 -1
  481. package/dist/deny-mutations.d.ts.map +0 -1
  482. package/dist/device-path.d.ts.map +0 -1
  483. package/dist/directory-durability.d.ts.map +0 -1
  484. package/dist/directory-entry-path.d.ts.map +0 -1
  485. package/dist/directory-guard.d.ts.map +0 -1
  486. package/dist/directory-mode-node.d.ts.map +0 -1
  487. package/dist/directory-mode-owner.d.ts.map +0 -1
  488. package/dist/directory-receipt.d.ts.map +0 -1
  489. package/dist/durability.d.ts.map +0 -1
  490. package/dist/effective-uid.d.ts.map +0 -1
  491. package/dist/error-detail.d.ts.map +0 -1
  492. package/dist/errors.d.ts.map +0 -1
  493. package/dist/file-cleanup.d.ts.map +0 -1
  494. package/dist/file-handle-transfer.d.ts.map +0 -1
  495. package/dist/file-hash.d.ts.map +0 -1
  496. package/dist/file-identity.d.ts.map +0 -1
  497. package/dist/file-lock-sync-admission.d.ts.map +0 -1
  498. package/dist/file-lock-sync-root-acquire.d.ts.map +0 -1
  499. package/dist/file-lock-sync-root-arbitration.d.ts.map +0 -1
  500. package/dist/file-lock-sync-root-held.d.ts.map +0 -1
  501. package/dist/file-lock-sync-root-io.d.ts.map +0 -1
  502. package/dist/file-lock-sync-root-mutation.d.ts.map +0 -1
  503. package/dist/file-lock-sync-root-options.d.ts.map +0 -1
  504. package/dist/file-lock-sync-root-registration.d.ts.map +0 -1
  505. package/dist/file-lock-sync-root.d.ts.map +0 -1
  506. package/dist/file-lock-sync-stale-admission.d.ts.map +0 -1
  507. package/dist/file-lock-sync.d.ts.map +0 -1
  508. package/dist/file-lock.d.ts.map +0 -1
  509. package/dist/file-observation.d.ts.map +0 -1
  510. package/dist/file-store-boundary.d.ts.map +0 -1
  511. package/dist/file-store-copy-source.d.ts.map +0 -1
  512. package/dist/file-store-limit.d.ts.map +0 -1
  513. package/dist/file-store-path.d.ts.map +0 -1
  514. package/dist/file-store-prune.d.ts.map +0 -1
  515. package/dist/file-store-sync-directory.d.ts.map +0 -1
  516. package/dist/file-store-sync-write.d.ts.map +0 -1
  517. package/dist/file-store.d.ts.map +0 -1
  518. package/dist/file-sync.d.ts.map +0 -1
  519. package/dist/filename.d.ts.map +0 -1
  520. package/dist/fs.d.ts.map +0 -1
  521. package/dist/guarded-mkdir.d.ts.map +0 -1
  522. package/dist/guarded-mutation.d.ts.map +0 -1
  523. package/dist/guest-dispatch-python.d.ts.map +0 -1
  524. package/dist/guest-native-python.d.ts.map +0 -1
  525. package/dist/guest.d.ts.map +0 -1
  526. package/dist/home-dir.d.ts.map +0 -1
  527. package/dist/index.d.ts.map +0 -1
  528. package/dist/install-path.d.ts.map +0 -1
  529. package/dist/json-document-store.d.ts.map +0 -1
  530. package/dist/json-durable-queue-directory.d.ts.map +0 -1
  531. package/dist/json-durable-queue-ownership.d.ts.map +0 -1
  532. package/dist/json-durable-queue-paths.d.ts +0 -11
  533. package/dist/json-durable-queue-paths.d.ts.map +0 -1
  534. package/dist/json-durable-queue-paths.js +0 -42
  535. package/dist/json-durable-queue-read.d.ts.map +0 -1
  536. package/dist/json-durable-queue.d.ts.map +0 -1
  537. package/dist/json-store.d.ts.map +0 -1
  538. package/dist/json-stringify.d.ts.map +0 -1
  539. package/dist/json.d.ts.map +0 -1
  540. package/dist/local-file-access.d.ts.map +0 -1
  541. package/dist/local-file-descriptor.d.ts.map +0 -1
  542. package/dist/local-roots.d.ts.map +0 -1
  543. package/dist/lock-config.d.ts.map +0 -1
  544. package/dist/move-path-cleanup.d.ts.map +0 -1
  545. package/dist/move-path-stage.d.ts.map +0 -1
  546. package/dist/move-path.d.ts.map +0 -1
  547. package/dist/mutation-authority.d.ts.map +0 -1
  548. package/dist/native-binding.d.ts.map +0 -1
  549. package/dist/native-config.d.ts.map +0 -1
  550. package/dist/native-directory-observation.d.ts.map +0 -1
  551. package/dist/native-fallback-warning.d.ts.map +0 -1
  552. package/dist/native-operations.d.ts.map +0 -1
  553. package/dist/native-parent-admission.d.ts.map +0 -1
  554. package/dist/native-pinned-write-windows.d.ts.map +0 -1
  555. package/dist/native-pinned-write.d.ts.map +0 -1
  556. package/dist/native-policy-directory-observation.d.ts.map +0 -1
  557. package/dist/native-policy-parent-windows.d.ts.map +0 -1
  558. package/dist/native-rename-outcome.d.ts.map +0 -1
  559. package/dist/native-staged-file.d.ts.map +0 -1
  560. package/dist/native.d.ts.map +0 -1
  561. package/dist/opened-file-failure.d.ts.map +0 -1
  562. package/dist/opened-realpath.d.ts.map +0 -1
  563. package/dist/output.d.ts.map +0 -1
  564. package/dist/overwrite-file-handle.d.ts.map +0 -1
  565. package/dist/owner-dacl.d.ts.map +0 -1
  566. package/dist/path-case.d.ts.map +0 -1
  567. package/dist/path-policy.d.ts.map +0 -1
  568. package/dist/path-prefix.d.ts.map +0 -1
  569. package/dist/path-scope-lexical.d.ts.map +0 -1
  570. package/dist/path-segment-route.d.ts.map +0 -1
  571. package/dist/path-suffix-aliases.d.ts.map +0 -1
  572. package/dist/path.d.ts.map +0 -1
  573. package/dist/permission-exec.d.ts.map +0 -1
  574. package/dist/permissions-public.d.ts.map +0 -1
  575. package/dist/permissions-windows.d.ts.map +0 -1
  576. package/dist/permissions.d.ts.map +0 -1
  577. package/dist/pinned-mutation-admission.d.ts.map +0 -1
  578. package/dist/pinned-mutation-observation.d.ts.map +0 -1
  579. package/dist/pinned-mutation-shared-route.d.ts.map +0 -1
  580. package/dist/pinned-open.d.ts.map +0 -1
  581. package/dist/pinned-operation.d.ts.map +0 -1
  582. package/dist/pinned-write-input.d.ts.map +0 -1
  583. package/dist/pinned-write-mode.d.ts.map +0 -1
  584. package/dist/pinned-write-staged.d.ts.map +0 -1
  585. package/dist/pinned-write-types.d.ts.map +0 -1
  586. package/dist/pinned-write.d.ts.map +0 -1
  587. package/dist/positional-read.d.ts.map +0 -1
  588. package/dist/private-directory.d.ts.map +0 -1
  589. package/dist/private-producer-handoff-sync.d.ts.map +0 -1
  590. package/dist/private-producer-handoff.d.ts.map +0 -1
  591. package/dist/private-temp-workspace.d.ts.map +0 -1
  592. package/dist/publish-copy-stage.d.ts.map +0 -1
  593. package/dist/publish-file-failure.d.ts.map +0 -1
  594. package/dist/publish-file.d.ts.map +0 -1
  595. package/dist/read-open-flags.d.ts.map +0 -1
  596. package/dist/read-opened-file.d.ts.map +0 -1
  597. package/dist/realpath.d.ts.map +0 -1
  598. package/dist/recursive-mkdir-path.d.ts.map +0 -1
  599. package/dist/regular-file.d.ts.map +0 -1
  600. package/dist/replace-directory.d.ts.map +0 -1
  601. package/dist/replace-file-copy-fallback.d.ts.map +0 -1
  602. package/dist/replace-file-copy-source.d.ts.map +0 -1
  603. package/dist/replace-file-descriptor.d.ts.map +0 -1
  604. package/dist/replace-file-mode.d.ts.map +0 -1
  605. package/dist/replace-file-rename-policy.d.ts.map +0 -1
  606. package/dist/replace-file-temp-owner.d.ts.map +0 -1
  607. package/dist/replace-file.d.ts.map +0 -1
  608. package/dist/retained-directory-replacement.d.ts.map +0 -1
  609. package/dist/root-boundary.d.ts.map +0 -1
  610. package/dist/root-context.d.ts.map +0 -1
  611. package/dist/root-create-input.d.ts.map +0 -1
  612. package/dist/root-directory-creation.d.ts.map +0 -1
  613. package/dist/root-directory-list.d.ts.map +0 -1
  614. package/dist/root-directory.d.ts.map +0 -1
  615. package/dist/root-entries.d.ts.map +0 -1
  616. package/dist/root-errors.d.ts.map +0 -1
  617. package/dist/root-file-final-admission.d.ts.map +0 -1
  618. package/dist/root-file.d.ts.map +0 -1
  619. package/dist/root-impl.d.ts.map +0 -1
  620. package/dist/root-move-noreplace.d.ts.map +0 -1
  621. package/dist/root-move-preflight.d.ts.map +0 -1
  622. package/dist/root-observed-path.d.ts.map +0 -1
  623. package/dist/root-options.d.ts.map +0 -1
  624. package/dist/root-path-errors.d.ts.map +0 -1
  625. package/dist/root-path-existing.d.ts.map +0 -1
  626. package/dist/root-path-observation.d.ts.map +0 -1
  627. package/dist/root-path-stat.d.ts.map +0 -1
  628. package/dist/root-path-symlink.d.ts +0 -7
  629. package/dist/root-path-symlink.d.ts.map +0 -1
  630. package/dist/root-path-symlink.js +0 -55
  631. package/dist/root-path.d.ts.map +0 -1
  632. package/dist/root-paths-lexical.d.ts.map +0 -1
  633. package/dist/root-paths.d.ts.map +0 -1
  634. package/dist/root-read-admission.d.ts.map +0 -1
  635. package/dist/root-remove-identity.d.ts.map +0 -1
  636. package/dist/root-remove-receipt.d.ts.map +0 -1
  637. package/dist/root-remove.d.ts.map +0 -1
  638. package/dist/root-symlink-policy.d.ts.map +0 -1
  639. package/dist/root-walk.d.ts.map +0 -1
  640. package/dist/root-write-admission.d.ts.map +0 -1
  641. package/dist/root-write-compatibility.d.ts.map +0 -1
  642. package/dist/root-write-complete-parent.d.ts.map +0 -1
  643. package/dist/root-write-lock-binding.d.ts.map +0 -1
  644. package/dist/root-write-mode.d.ts.map +0 -1
  645. package/dist/root-write-publication.d.ts.map +0 -1
  646. package/dist/root-write-verification.d.ts.map +0 -1
  647. package/dist/root.d.ts.map +0 -1
  648. package/dist/safe-path-segment.d.ts.map +0 -1
  649. package/dist/secret-file.d.ts.map +0 -1
  650. package/dist/secret-read-async.d.ts.map +0 -1
  651. package/dist/secret-read-policy.d.ts.map +0 -1
  652. package/dist/secret.d.ts.map +0 -1
  653. package/dist/secure-file-windows.d.ts.map +0 -1
  654. package/dist/secure-file.d.ts.map +0 -1
  655. package/dist/secure-temp-dir.d.ts.map +0 -1
  656. package/dist/secure-temp-repair.d.ts.map +0 -1
  657. package/dist/sibling-staged-file.d.ts.map +0 -1
  658. package/dist/sibling-temp.d.ts.map +0 -1
  659. package/dist/sidecar-lock-acquire.d.ts.map +0 -1
  660. package/dist/sidecar-lock-admission-context.d.ts.map +0 -1
  661. package/dist/sidecar-lock-admission-parser.d.ts.map +0 -1
  662. package/dist/sidecar-lock-admission.d.ts.map +0 -1
  663. package/dist/sidecar-lock-handle.d.ts.map +0 -1
  664. package/dist/sidecar-lock-policy.d.ts.map +0 -1
  665. package/dist/sidecar-lock-reclaim.d.ts.map +0 -1
  666. package/dist/sidecar-lock-root.d.ts.map +0 -1
  667. package/dist/sidecar-lock-stale-admission.d.ts.map +0 -1
  668. package/dist/sidecar-lock-target.d.ts.map +0 -1
  669. package/dist/sidecar-lock-types.d.ts.map +0 -1
  670. package/dist/sidecar-lock.d.ts.map +0 -1
  671. package/dist/staged-directory.d.ts.map +0 -1
  672. package/dist/staged-file-settlement.d.ts.map +0 -1
  673. package/dist/staged-file-types.d.ts.map +0 -1
  674. package/dist/standalone-publication-path.d.ts.map +0 -1
  675. package/dist/stat-observation.d.ts.map +0 -1
  676. package/dist/store.d.ts.map +0 -1
  677. package/dist/strict-file-identity.d.ts.map +0 -1
  678. package/dist/string-coerce.d.ts.map +0 -1
  679. package/dist/suppressed-error.d.ts.map +0 -1
  680. package/dist/symlink-parents.d.ts.map +0 -1
  681. package/dist/temp-cleanup.d.ts.map +0 -1
  682. package/dist/temp-target.d.ts.map +0 -1
  683. package/dist/temp-workspace-admission.d.ts.map +0 -1
  684. package/dist/temp-workspace-child-admission.d.ts.map +0 -1
  685. package/dist/temp-workspace-descriptor.d.ts.map +0 -1
  686. package/dist/temp-workspace-identity.d.ts.map +0 -1
  687. package/dist/temp-workspace-owner.d.ts.map +0 -1
  688. package/dist/temp-workspace-permissions.d.ts.map +0 -1
  689. package/dist/temp-workspace-types.d.ts.map +0 -1
  690. package/dist/temp.d.ts.map +0 -1
  691. package/dist/test-hooks.d.ts.map +0 -1
  692. package/dist/text-atomic.d.ts.map +0 -1
  693. package/dist/timing.d.ts.map +0 -1
  694. package/dist/trash.d.ts.map +0 -1
  695. package/dist/types.d.ts.map +0 -1
  696. package/dist/unicode-path.d.ts.map +0 -1
  697. package/dist/walk.d.ts.map +0 -1
  698. package/dist/windows-command.d.ts.map +0 -1
  699. package/dist/windows-owner.d.ts.map +0 -1
  700. package/dist/windows-path-alias.d.ts.map +0 -1
  701. package/dist/windows-security-command.d.ts.map +0 -1
  702. package/dist/windows-security-facts.d.ts.map +0 -1
  703. package/dist/write-file-handle.d.ts.map +0 -1
  704. package/dist/write-open-flags.d.ts.map +0 -1
  705. package/dist/write-queue.d.ts.map +0 -1
package/dist/json.js CHANGED
@@ -3,37 +3,34 @@ import fsSync from "node:fs";
3
3
  import path from "node:path";
4
4
  import { readFileDescriptorBoundedSync } from "./bounded-read.js";
5
5
  import { FsSafeError } from "./errors.js";
6
- import { sameFileIdentityForCleanup } from "./file-identity.js";
7
6
  import { stringifyJsonDocument } from "./json-stringify.js";
8
7
  import { readRegularFile, readRegularFileSync, statRegularFile } from "./regular-file.js";
9
8
  import { openRootFileSync } from "./root-file.js";
10
- import { resolveReadOpenFlags } from "./read-open-flags.js";
11
9
  import { recursiveMkdirPath } from "./recursive-mkdir-path.js";
10
+ import { writeTempFileSync } from "./replace-file-descriptor.js";
11
+ import { SyncAtomicTempOwner } from "./replace-file-temp-owner.js";
12
12
  import { admitStandalonePublicationPath } from "./standalone-publication-path.js";
13
13
  import { writeTextAtomic } from "./text-atomic.js";
14
14
  import { sleep } from "./timing.js";
15
15
  import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
16
16
  const READ_RETRY_MAX_ATTEMPTS = 5;
17
17
  const READ_RETRY_BASE_DELAY_MS = 50;
18
- function isRetryableReadError(err, options) {
18
+ function isRetryableReadError(err) {
19
19
  if (err instanceof FsSafeError && err.code === "path-mismatch") {
20
20
  return true;
21
21
  }
22
- if (options.retryOpenRaceErrors !== true) {
23
- return false;
24
- }
25
22
  const code = getErrorCode(err);
26
23
  return code === "ENOENT" || code === "EPERM";
27
24
  }
28
- async function readRegularFileWithRetry(filePath, options = {}) {
25
+ async function readRegularFileWithRetry(filePath, maxBytes) {
29
26
  let lastErr;
30
27
  for (let attempt = 0; attempt < READ_RETRY_MAX_ATTEMPTS; attempt++) {
31
28
  try {
32
- return (await readRegularFile({ filePath, maxBytes: options.maxBytes })).buffer;
29
+ return (await readRegularFile({ filePath, maxBytes })).buffer;
33
30
  }
34
31
  catch (err) {
35
32
  lastErr = err;
36
- if (!isRetryableReadError(err, options) || attempt === READ_RETRY_MAX_ATTEMPTS - 1) {
33
+ if (!isRetryableReadError(err) || attempt === READ_RETRY_MAX_ATTEMPTS - 1) {
37
34
  throw err;
38
35
  }
39
36
  await sleep(READ_RETRY_BASE_DELAY_MS * Math.pow(2, attempt));
@@ -46,52 +43,19 @@ async function readRegularFileIfExistsWithRetry(filePath, options = {}) {
46
43
  if (initial.missing) {
47
44
  return null;
48
45
  }
49
- return await readRegularFileWithRetry(filePath, {
50
- maxBytes: options.maxBytes,
51
- retryOpenRaceErrors: true,
52
- });
46
+ return await readRegularFileWithRetry(filePath, options.maxBytes);
53
47
  }
54
48
  const JSON_FILE_MODE = 0o600;
55
49
  const JSON_DIR_MODE = 0o700;
56
50
  function getErrorCode(err) {
57
51
  return err instanceof Error ? err.code : undefined;
58
52
  }
59
- function trySetSecureMode(pathname, expectedIdentity) {
60
- let fd;
53
+ function trySetSecureMode(fd) {
61
54
  try {
62
- const before = fsSync.lstatSync(pathname, { bigint: true });
63
- if (before.isSymbolicLink() ||
64
- !before.isFile() ||
65
- before.nlink !== 1n ||
66
- !sameFileIdentityForCleanup(before, expectedIdentity)) {
67
- return;
68
- }
69
- fd = fsSync.openSync(pathname, resolveReadOpenFlags());
70
- const opened = fsSync.fstatSync(fd, { bigint: true });
71
- const current = fsSync.lstatSync(pathname, { bigint: true });
72
- if (!opened.isFile() ||
73
- opened.nlink !== 1n ||
74
- current.isSymbolicLink() ||
75
- !current.isFile() ||
76
- current.nlink !== 1n ||
77
- !sameFileIdentityForCleanup(opened, expectedIdentity) ||
78
- !sameFileIdentityForCleanup(current, opened)) {
79
- return;
80
- }
81
55
  fsSync.fchmodSync(fd, JSON_FILE_MODE);
82
56
  }
83
57
  catch {
84
- // Best-effort mode application never falls back to a mutable pathname.
85
- }
86
- finally {
87
- if (fd !== undefined) {
88
- try {
89
- fsSync.closeSync(fd);
90
- }
91
- catch {
92
- // best-effort cleanup
93
- }
94
- }
58
+ // Best-effort mode application stays on the retained staging descriptor.
95
59
  }
96
60
  }
97
61
  function trySyncDirectory(pathname) {
@@ -114,48 +78,24 @@ function trySyncDirectory(pathname) {
114
78
  }
115
79
  }
116
80
  }
117
- function renameJsonFileWithFallback(tmpPath, pathname) {
81
+ function renameJsonFileWithFallback(owner, pathname) {
82
+ owner.assertCurrent(fsSync);
118
83
  try {
119
- fsSync.renameSync(tmpPath, pathname);
84
+ fsSync.renameSync(owner.pathname, pathname);
120
85
  return;
121
86
  }
122
87
  catch (error) {
123
- const code = error.code;
88
+ const code = error?.code;
124
89
  if (code === "EPERM" || code === "EEXIST") {
125
- const existing = (() => {
126
- try {
127
- return fsSync.lstatSync(pathname);
128
- }
129
- catch (lstatError) {
130
- if (lstatError.code === "ENOENT") {
131
- return null;
132
- }
133
- throw lstatError;
134
- }
135
- })();
136
- if (existing?.isSymbolicLink()) {
137
- fsSync.rmSync(pathname, { force: true });
138
- fsSync.renameSync(tmpPath, pathname);
139
- return;
140
- }
90
+ owner.assertCurrent(fsSync);
141
91
  fsSync.rmSync(pathname, { force: true });
142
- fsSync.renameSync(tmpPath, pathname);
92
+ owner.assertCurrent(fsSync);
93
+ fsSync.renameSync(owner.pathname, pathname);
143
94
  return;
144
95
  }
145
96
  throw error;
146
97
  }
147
98
  }
148
- function writeTempJsonFile(pathname, payload) {
149
- const fd = fsSync.openSync(pathname, "wx", JSON_FILE_MODE);
150
- try {
151
- fsSync.writeFileSync(fd, payload, "utf8");
152
- fsSync.fsyncSync(fd);
153
- return fsSync.fstatSync(fd, { bigint: true });
154
- }
155
- finally {
156
- fsSync.closeSync(fd);
157
- }
158
- }
159
99
  export function tryReadJsonSync(pathname, options = {}) {
160
100
  try {
161
101
  const raw = readRegularFileSync({
@@ -174,20 +114,31 @@ export function writeJsonSync(pathname, data) {
174
114
  const tmpPath = path.format({ ...path.parse(filePath), base: `.fs-safe-${randomUUID()}.tmp` });
175
115
  const payload = `${stringifyJsonDocument(data, null, 2)}\n`;
176
116
  fsSync.mkdirSync(recursiveMkdirPath(path.dirname(filePath)), { recursive: true, mode: JSON_DIR_MODE });
117
+ const owner = new SyncAtomicTempOwner(tmpPath);
118
+ let originalFailure;
177
119
  try {
178
- const tempIdentity = writeTempJsonFile(tmpPath, payload);
179
- trySetSecureMode(tmpPath, tempIdentity);
180
- renameJsonFileWithFallback(tmpPath, filePath);
181
- trySetSecureMode(filePath, tempIdentity);
120
+ owner.start();
121
+ const temp = writeTempFileSync({
122
+ fsModule: fsSync, tempPath: tmpPath, content: payload, mode: JSON_FILE_MODE,
123
+ sync: false, onIdentity: owner.onIdentity,
124
+ });
125
+ owner.adopt(temp);
126
+ owner.assertCurrent(fsSync);
127
+ trySetSecureMode(temp.fd);
128
+ fsSync.fsyncSync(temp.fd);
129
+ renameJsonFileWithFallback(owner, filePath);
130
+ owner.markRenamed();
131
+ owner.assertPublished(fsSync, filePath);
132
+ trySetSecureMode(temp.fd);
182
133
  trySyncDirectory(filePath);
134
+ owner.assertPublished(fsSync, filePath);
135
+ }
136
+ catch (error) {
137
+ originalFailure = { error };
138
+ throw error;
183
139
  }
184
140
  finally {
185
- try {
186
- fsSync.rmSync(tmpPath, { force: true });
187
- }
188
- catch {
189
- // best-effort cleanup when rename does not happen
190
- }
141
+ owner.finish({ fsModule: fsSync, originalFailure, throwOnCleanupError: false });
191
142
  }
192
143
  }
193
144
  export class JsonFileReadError extends Error {
@@ -312,10 +263,7 @@ export async function tryReadJson(filePath, options = {}) {
312
263
  export async function readJson(filePath, options = {}) {
313
264
  let raw;
314
265
  try {
315
- raw = (await readRegularFileWithRetry(filePath, {
316
- maxBytes: options.maxBytes,
317
- retryOpenRaceErrors: true,
318
- })).toString("utf8");
266
+ raw = (await readRegularFileWithRetry(filePath, options.maxBytes)).toString("utf8");
319
267
  }
320
268
  catch (err) {
321
269
  throw new JsonFileReadError(filePath, "read", err);
@@ -6,4 +6,3 @@ export declare function assertNoWindowsNetworkPath(filePath: string, label?: str
6
6
  export declare function safeFileURLToPath(fileUrl: string, platform?: NodeJS.Platform): string;
7
7
  export declare function trySafeFileURLToPath(fileUrl: string, platform?: NodeJS.Platform): string | undefined;
8
8
  export declare function basenameFromMediaSource(source?: string): string | undefined;
9
- //# sourceMappingURL=local-file-access.d.ts.map
@@ -2,6 +2,7 @@ import path from "node:path";
2
2
  import { fileURLToPath, URL } from "node:url";
3
3
  import { normalizeLowercaseStringOrEmpty } from "./string-coerce.js";
4
4
  import { hasWindowsPathAlias } from "./windows-path-alias.js";
5
+ import { isWindowsSeparator, rootedWindowsDriveColonIndex, windowsNamespaceMarker, } from "./windows-path-syntax.js";
5
6
  const ENCODED_FILE_URL_SEPARATOR_RE = /%(?:2f|5c)/i;
6
7
  const FILE_URL_PREFIX_RE = /^file:\/\//i;
7
8
  export function isFileUrl(input) {
@@ -18,16 +19,8 @@ export function isWindowsNetworkPath(filePath, platform = process.platform) {
18
19
  if (platform !== "win32") {
19
20
  return false;
20
21
  }
21
- const normalized = filePath.replace(/\//g, "\\");
22
- const extendedDrive = normalized.length >= 7 &&
23
- normalized.startsWith("\\\\?\\") &&
24
- /^[a-z]$/i.test(normalized[4] ?? "") &&
25
- normalized[5] === ":" &&
26
- normalized[6] === "\\";
27
- if (extendedDrive) {
28
- return false;
29
- }
30
- return normalized.startsWith("\\\\");
22
+ return isWindowsSeparator(filePath, 0) && isWindowsSeparator(filePath, 1) &&
23
+ !(windowsNamespaceMarker(filePath) === "?" && rootedWindowsDriveColonIndex(filePath) === 5);
31
24
  }
32
25
  export function isWindowsDriveLetterPath(filePath, platform = process.platform) {
33
26
  return platform === "win32" && /^[A-Za-z]:[\\/]/.test(filePath);
@@ -14,4 +14,3 @@ export declare function openLocalFileDescriptor(filePath: string, options?: {
14
14
  readWrite?: true;
15
15
  }): Promise<OwnedLocalFile>;
16
16
  export {};
17
- //# sourceMappingURL=local-file-descriptor.d.ts.map
@@ -23,4 +23,3 @@ export type ReadLocalFileFromRootsOptions = LocalRootsInputOptions & {
23
23
  };
24
24
  export declare function resolveLocalPathFromRootsSync(options: ResolveLocalPathFromRootsSyncOptions): LocalRootsPathResult | null;
25
25
  export declare function readLocalFileFromRoots(options: ReadLocalFileFromRootsOptions): Promise<LocalRootsReadResult | null>;
26
- //# sourceMappingURL=local-roots.d.ts.map
@@ -71,7 +71,7 @@ function resolveRootRealSync(rootDir) {
71
71
  assertNoWindowsPathAlias(realPath, "filesystem", "local root uses a Windows filesystem namespace alias");
72
72
  return realPath;
73
73
  }
74
- export function resolveLocalPathFromRootsSync(options) {
74
+ function prepareLocalRootsInput(options) {
75
75
  const label = options.label ?? "local roots";
76
76
  const rootDirs = options.roots.map((rootEntry) => resolveLocalRootInput(rootEntry, label));
77
77
  let requestedPath;
@@ -83,6 +83,13 @@ export function resolveLocalPathFromRootsSync(options) {
83
83
  return null;
84
84
  throw error;
85
85
  }
86
+ return { label, rootDirs, requestedPath };
87
+ }
88
+ export function resolveLocalPathFromRootsSync(options) {
89
+ const input = prepareLocalRootsInput(options);
90
+ if (!input)
91
+ return null;
92
+ const { label, rootDirs, requestedPath } = input;
86
93
  for (const rootDir of rootDirs) {
87
94
  const rootReal = resolveRootRealSync(rootDir);
88
95
  if (!rootReal) {
@@ -122,17 +129,17 @@ export function resolveLocalPathFromRootsSync(options) {
122
129
  }
123
130
  export async function readLocalFileFromRoots(options) {
124
131
  const maxBytes = normalizeMaxBytes(options.maxBytes);
125
- const label = options.label ?? "local roots";
126
- const rootDirs = options.roots.map((rootEntry) => resolveLocalRootInput(rootEntry, label));
127
- let requestedPath;
128
- try {
129
- requestedPath = resolveLocalPathInput(options.filePath, "file path");
130
- }
131
- catch (error) {
132
- if (isWindowsPathAliasError(error))
133
- return null;
134
- throw error;
135
- }
132
+ const input = prepareLocalRootsInput(options);
133
+ if (!input || input.rootDirs.length === 0)
134
+ return null;
135
+ const { rootDirs, requestedPath } = input;
136
+ const readOptions = {
137
+ hardlinks: options.hardlinks,
138
+ symlinks: options.symlinks,
139
+ };
140
+ // Omission keeps Root's default cap; one policy snapshot serves every root.
141
+ if (maxBytes !== undefined)
142
+ readOptions.maxBytes = maxBytes;
136
143
  for (const rootDir of rootDirs) {
137
144
  let scopedRoot;
138
145
  try {
@@ -141,15 +148,6 @@ export async function readLocalFileFromRoots(options) {
141
148
  catch {
142
149
  continue;
143
150
  }
144
- const readOptions = {
145
- hardlinks: options.hardlinks,
146
- symlinks: options.symlinks,
147
- };
148
- // Leave maxBytes absent when the caller omits it so Root's own default
149
- // cap remains in force instead of being overwritten by undefined.
150
- if (maxBytes !== undefined) {
151
- readOptions.maxBytes = maxBytes;
152
- }
153
151
  try {
154
152
  const result = await scopedRoot.readAbsolute(requestedPath, readOptions);
155
153
  return { ...result, root: scopedRoot.rootReal };
@@ -7,4 +7,3 @@ export type FsSafeLockConfig = {
7
7
  };
8
8
  export declare function configureFsSafeLocks(config: Partial<FsSafeLockConfig>): void;
9
9
  export declare function getFsSafeLockConfig(): FsSafeLockConfig;
10
- //# sourceMappingURL=lock-config.d.ts.map
@@ -1,13 +1,5 @@
1
1
  import fsSync from "node:fs";
2
- export type EntryIdentity = {
3
- ctimeMs: number;
4
- dev: number;
5
- ino: number;
6
- mode: number;
7
- mtimeMs: number;
8
- nlink: number;
9
- size: number;
10
- };
2
+ export type EntryIdentity = Readonly<Pick<fsSync.BigIntStats, "ctimeNs" | "dev" | "ino" | "mode" | "mtimeNs" | "nlink" | "size">>;
11
3
  export type CopiedEntryManifest = (EntryIdentity & {
12
4
  children: Array<{
13
5
  name: string;
@@ -27,19 +19,12 @@ type CleanupAliasGroup = {
27
19
  export type CleanupCopiedEntryState = {
28
20
  aliasGroups: Map<string, CleanupAliasGroup>;
29
21
  };
30
- export declare function entryIdentity(stat: {
31
- ctimeMs: number;
32
- dev: number;
33
- ino: number;
34
- mode: number;
35
- mtimeMs: number;
36
- nlink: number;
37
- size: number;
38
- }): EntryIdentity;
22
+ export declare function entryIdentity(stat: EntryIdentity): EntryIdentity;
39
23
  export declare function sameIdentity(a: EntryIdentity, b: EntryIdentity): boolean;
40
24
  export declare function sourceChangedError(sourcePath: string): Error;
25
+ export declare function inspectSourceEntry(sourcePath: string, observe: () => fsSync.BigIntStats): fsSync.BigIntStats;
26
+ export declare function inspectSourceDirectory(sourcePath: string, expected?: Pick<fsSync.BigIntStats, "dev" | "ino">): fsSync.BigIntStats;
41
27
  export declare function assertSourceStillMatches(sourcePath: string, identity: EntryIdentity): Promise<void>;
42
28
  export declare function createCleanupCopiedEntryState(sourcePath: string, manifest: CopiedEntryManifest): CleanupCopiedEntryState;
43
- export declare function cleanupCopiedEntry(sourcePath: string, manifest: CopiedEntryManifest, state: CleanupCopiedEntryState, assertBeforeMutation: () => void): Promise<CleanupCopiedEntryResult>;
29
+ export declare function cleanupCopiedEntry(sourcePath: string, manifest: CopiedEntryManifest, state: CleanupCopiedEntryState, assertBeforeMutation: (() => void) | undefined): Promise<CleanupCopiedEntryResult>;
44
30
  export {};
45
- //# sourceMappingURL=move-path-cleanup.d.ts.map
@@ -2,14 +2,15 @@ import fsSync from "node:fs";
2
2
  import fs from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { FsSafeError } from "./errors.js";
5
+ import { inspectDirectoryIdentitySync } from "./directory-guard.js";
5
6
  import { inspectFileIdentitySync } from "./strict-file-identity.js";
6
7
  export function entryIdentity(stat) {
7
8
  return {
8
- ctimeMs: stat.ctimeMs,
9
+ ctimeNs: stat.ctimeNs,
9
10
  dev: stat.dev,
10
11
  ino: stat.ino,
11
12
  mode: stat.mode,
12
- mtimeMs: stat.mtimeMs,
13
+ mtimeNs: stat.mtimeNs,
13
14
  nlink: stat.nlink,
14
15
  size: stat.size,
15
16
  };
@@ -20,16 +21,32 @@ export function sameIdentity(a, b) {
20
21
  a.mode === b.mode &&
21
22
  a.nlink === b.nlink &&
22
23
  a.size === b.size &&
23
- a.mtimeMs === b.mtimeMs &&
24
- a.ctimeMs === b.ctimeMs);
24
+ a.mtimeNs === b.mtimeNs &&
25
+ a.ctimeNs === b.ctimeNs);
25
26
  }
26
27
  export function sourceChangedError(sourcePath) {
27
28
  return Object.assign(new Error(`Source changed during move fallback: ${sourcePath}`), {
28
29
  code: "ESTALE",
29
30
  });
30
31
  }
32
+ export function inspectSourceEntry(sourcePath, observe) {
33
+ return inspectFileIdentitySync(observe, undefined, process.platform, () => sourceChangedError(sourcePath));
34
+ }
35
+ export function inspectSourceDirectory(sourcePath, expected) {
36
+ try {
37
+ return inspectDirectoryIdentitySync(sourcePath, expected);
38
+ }
39
+ catch (error) {
40
+ const code = error?.code;
41
+ if (code === "ENOENT" || code === "ENOTDIR" ||
42
+ (error instanceof FsSafeError && (error.code === "path-mismatch" || error.code === "not-file"))) {
43
+ throw sourceChangedError(sourcePath);
44
+ }
45
+ throw error;
46
+ }
47
+ }
31
48
  export async function assertSourceStillMatches(sourcePath, identity) {
32
- if (!sameIdentity(identity, entryIdentity(fsSync.lstatSync(sourcePath)))) {
49
+ if (!sameIdentity(identity, inspectSourceEntry(sourcePath, () => fsSync.lstatSync(sourcePath, { bigint: true })))) {
33
50
  throw sourceChangedError(sourcePath);
34
51
  }
35
52
  }
@@ -43,7 +60,7 @@ function collectAliasCandidates(sourcePath, manifest, candidates) {
43
60
  }
44
61
  return;
45
62
  }
46
- if (manifest.nlink <= 1) {
63
+ if (manifest.nlink <= 1n) {
47
64
  return;
48
65
  }
49
66
  const key = identityKey(manifest);
@@ -76,15 +93,26 @@ function sameOwnedUnlinkTransition(before, after) {
76
93
  before.ino === after.ino &&
77
94
  before.mode === after.mode &&
78
95
  before.size === after.size &&
79
- before.mtimeMs === after.mtimeMs &&
80
- before.nlink > 0 &&
81
- after.nlink === before.nlink - 1 &&
82
- after.ctimeMs >= before.ctimeMs);
96
+ before.mtimeNs === after.mtimeNs &&
97
+ before.nlink > 0n &&
98
+ after.nlink === before.nlink - 1n &&
99
+ after.ctimeNs >= before.ctimeNs);
83
100
  }
84
101
  function poisonAliasGroup(group) {
85
102
  group.stale = true;
86
103
  return "stale";
87
104
  }
105
+ function inspectCleanupLeaf(sourcePath, expected) {
106
+ let mismatch;
107
+ try {
108
+ return inspectFileIdentitySync(() => fsSync.lstatSync(sourcePath, { bigint: true }), expected, process.platform, () => mismatch = sourceChangedError(sourcePath));
109
+ }
110
+ catch (error) {
111
+ if (mismatch !== undefined && error === mismatch)
112
+ return undefined;
113
+ throw error;
114
+ }
115
+ }
88
116
  async function observeOwnedAliasUnlink(sourcePath, group) {
89
117
  group.remainingPaths.delete(sourcePath);
90
118
  const remainingPath = group.remainingPaths.values().next().value;
@@ -93,7 +121,7 @@ async function observeOwnedAliasUnlink(sourcePath, group) {
93
121
  }
94
122
  let observed;
95
123
  try {
96
- observed = fsSync.lstatSync(remainingPath);
124
+ observed = inspectCleanupLeaf(remainingPath, group.expected);
97
125
  }
98
126
  catch (error) {
99
127
  if (error?.code === "ENOENT") {
@@ -101,11 +129,10 @@ async function observeOwnedAliasUnlink(sourcePath, group) {
101
129
  }
102
130
  throw error;
103
131
  }
104
- const observedIdentity = entryIdentity(observed);
105
- if (!sameOwnedUnlinkTransition(group.expected, observedIdentity)) {
132
+ if (!observed || !sameOwnedUnlinkTransition(group.expected, observed)) {
106
133
  return poisonAliasGroup(group);
107
134
  }
108
- group.expected = observedIdentity;
135
+ group.expected = entryIdentity(observed);
109
136
  return "removed";
110
137
  }
111
138
  function mergeCleanupResults(a, b) {
@@ -130,12 +157,16 @@ export async function cleanupCopiedEntry(sourcePath, manifest, state, assertBefo
130
157
  // A same-inode directory can gain unrelated children after commit. Still
131
158
  // clean manifest children so the fallback does not duplicate copied files.
132
159
  let result = "removed";
160
+ const assertBeforeChildMutation = assertBeforeMutation ? () => {
161
+ assertBeforeMutation();
162
+ inspectSourceDirectory(sourcePath, manifest.directoryIdentity);
163
+ } : undefined;
133
164
  for (const child of manifest.children) {
134
- result = mergeCleanupResults(result, await cleanupCopiedEntry(path.join(sourcePath, child.name), child.manifest, state, assertBeforeMutation));
165
+ result = mergeCleanupResults(result, await cleanupCopiedEntry(path.join(sourcePath, child.name), child.manifest, state, assertBeforeChildMutation));
135
166
  }
136
167
  // Child cleanup and the caller's authority check can replace the directory.
137
168
  // Keep the final exact observation after both, immediately before removal.
138
- assertBeforeMutation();
169
+ assertBeforeMutation?.();
139
170
  try {
140
171
  currentStat = inspectFileIdentitySync(() => fsSync.lstatSync(sourcePath, { bigint: true }), manifest.directoryIdentity);
141
172
  }
@@ -166,9 +197,10 @@ export async function cleanupCopiedEntry(sourcePath, manifest, state, assertBefo
166
197
  if (aliasGroup?.stale) {
167
198
  return "stale";
168
199
  }
200
+ const expected = aliasGroup?.expected ?? manifest;
169
201
  let currentStat;
170
202
  try {
171
- currentStat = fsSync.lstatSync(sourcePath);
203
+ currentStat = inspectCleanupLeaf(sourcePath, expected);
172
204
  }
173
205
  catch (error) {
174
206
  if (error?.code === "ENOENT") {
@@ -176,11 +208,15 @@ export async function cleanupCopiedEntry(sourcePath, manifest, state, assertBefo
176
208
  }
177
209
  throw error;
178
210
  }
179
- const expected = aliasGroup?.expected ?? manifest;
180
- if (!sameIdentity(expected, entryIdentity(currentStat))) {
181
- return aliasGroup ? poisonAliasGroup(aliasGroup) : "stale";
211
+ for (let observation = 0;; observation++) {
212
+ if (!currentStat || !sameIdentity(expected, currentStat)) {
213
+ return aliasGroup ? poisonAliasGroup(aliasGroup) : "stale";
214
+ }
215
+ if (observation || !assertBeforeMutation)
216
+ break;
217
+ assertBeforeMutation();
218
+ currentStat = inspectCleanupLeaf(sourcePath, expected);
182
219
  }
183
- assertBeforeMutation();
184
220
  await fs.unlink(sourcePath);
185
221
  return aliasGroup
186
222
  ? await observeOwnedAliasUnlink(sourcePath, aliasGroup)
@@ -5,4 +5,3 @@ export declare function createMoveStageOwner(staged: string): Promise<{
5
5
  published(): void;
6
6
  cleanup(): Promise<void>;
7
7
  }>;
8
- //# sourceMappingURL=move-path-stage.d.ts.map
@@ -18,4 +18,3 @@ type MoveCopyFallbackReason = "cross-device" | "windows-rename-denied";
18
18
  export declare function moveCopyFallbackReasonForRenameError(error: unknown, platform?: NodeJS.Platform): MoveCopyFallbackReason | undefined;
19
19
  export declare function movePathWithCopyFallback(options: MovePathWithCopyFallbackOptions): Promise<void>;
20
20
  export {};
21
- //# sourceMappingURL=move-path.d.ts.map