@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
@@ -6,7 +6,7 @@ import path from "node:path";
6
6
  import { syncDirectory } from "./directory-durability.js";
7
7
  import { FsSafeError } from "./errors.js";
8
8
  import { sameFileIdentityForCleanup, sha256Hex } from "./file-identity.js";
9
- import { inspectFileIdentity } from "./strict-file-identity.js";
9
+ import { inspectFileIdentitySync } from "./strict-file-identity.js";
10
10
  import { serializePathWrite } from "./write-queue.js";
11
11
  import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
12
12
  const validatedDurableQueueEntryPaths = new WeakSet();
@@ -45,12 +45,14 @@ function processingPathFromJsonPath(jsonPath) {
45
45
  ? `${jsonPath.slice(0, -".json".length)}.processing`
46
46
  : `${jsonPath}.processing`;
47
47
  }
48
- async function regularQueueFileIdentity(filePath) {
49
- const identity = await lstatOrNull(filePath);
48
+ function regularQueueFileIdentity(filePath, subject = "entry") {
49
+ const identity = lstatOrNull(filePath);
50
50
  if (!identity)
51
51
  return null;
52
52
  if (identity.isSymbolicLink() || !identity.isFile()) {
53
- throw new Error(`queue entry is not a regular file: ${filePath}`);
53
+ throw subject === "retirement"
54
+ ? new FsSafeError("path-mismatch", "queue retirement path is not a regular file")
55
+ : new Error(`queue entry is not a regular file: ${filePath}`);
54
56
  }
55
57
  return identity;
56
58
  }
@@ -62,9 +64,9 @@ async function withQueueEntryLock(paths, run) {
62
64
  async function claimDurableQueueEntryUnlocked(paths, options = {}) {
63
65
  const processingPath = paths.processingPath;
64
66
  await recoverDurableQueueRetirement({ jsonPath: paths.jsonPath, processingPath });
65
- const existingProcessing = await regularQueueFileIdentity(processingPath);
67
+ const existingProcessing = regularQueueFileIdentity(processingPath);
66
68
  if (existingProcessing) {
67
- const pending = await lstatOrNull(paths.jsonPath);
69
+ const pending = lstatOrNull(paths.jsonPath);
68
70
  const retiresPending = pending !== null &&
69
71
  !pending.isSymbolicLink() &&
70
72
  pending.isFile() &&
@@ -80,7 +82,7 @@ async function claimDurableQueueEntryUnlocked(paths, options = {}) {
80
82
  }
81
83
  return processingPath;
82
84
  }
83
- const pending = await lstatOrNull(paths.jsonPath);
85
+ const pending = lstatOrNull(paths.jsonPath);
84
86
  if (!pending || pending.isSymbolicLink() || !pending.isFile())
85
87
  return null;
86
88
  if (pending.nlink > 1n || !sameFileIdentityForCleanup(pending, pending)) {
@@ -94,7 +96,7 @@ async function claimDurableQueueEntryUnlocked(paths, options = {}) {
94
96
  }
95
97
  catch (error) {
96
98
  if (getErrorCode(error) === "EEXIST") {
97
- if (!(await regularQueueFileIdentity(processingPath)))
99
+ if (!regularQueueFileIdentity(processingPath))
98
100
  return null;
99
101
  await syncDirectory(path.dirname(processingPath));
100
102
  return processingPath;
@@ -104,7 +106,7 @@ async function claimDurableQueueEntryUnlocked(paths, options = {}) {
104
106
  throw error;
105
107
  }
106
108
  await syncDirectory(path.dirname(processingPath));
107
- const claimed = await regularQueueFileIdentity(processingPath);
109
+ const claimed = regularQueueFileIdentity(processingPath);
108
110
  if (!claimed || claimed.nlink > 2n) {
109
111
  throw new FsSafeError("path-mismatch", "queue claim is not an owned regular file");
110
112
  }
@@ -113,7 +115,7 @@ async function claimDurableQueueEntryUnlocked(paths, options = {}) {
113
115
  }
114
116
  export async function claimDurableQueueEntry(paths, options = {}) {
115
117
  const validatedPaths = ownDurableQueueEntryPaths(paths);
116
- if (!(await lstatOrNull(path.dirname(validatedPaths.jsonPath))))
118
+ if (!lstatOrNull(path.dirname(validatedPaths.jsonPath)))
117
119
  return null;
118
120
  return await withQueueEntryLock(validatedPaths, async () => await claimDurableQueueEntryUnlocked(validatedPaths, options));
119
121
  }
@@ -122,9 +124,9 @@ export async function migrateDurableQueueEntry(paths, expected, releaseReadPin,
122
124
  const validatedPaths = ownDurableQueueEntryPaths(paths);
123
125
  return await withQueueEntryLock(validatedPaths, async () => {
124
126
  const processingPath = validatedPaths.processingPath;
125
- const assertCurrent = async () => {
127
+ const assertCurrent = () => {
126
128
  try {
127
- await inspectFileIdentity(() => {
129
+ inspectFileIdentitySync(() => {
128
130
  const current = fsSync.lstatSync(processingPath, { bigint: true });
129
131
  if (current.isSymbolicLink() || !current.isFile() || current.nlink !== 1n) {
130
132
  throw new FsSafeError("path-mismatch", "queue migration requires its original processing claim");
@@ -139,49 +141,45 @@ export async function migrateDurableQueueEntry(paths, expected, releaseReadPin,
139
141
  throw error;
140
142
  }
141
143
  };
142
- await assertCurrent();
144
+ assertCurrent();
143
145
  return await run(processingPath, async () => {
144
- await assertCurrent();
146
+ assertCurrent();
145
147
  if (process.platform === "win32") {
146
148
  // Windows cannot replace our still-open target. Keep the transfer lock
147
149
  // across release and reject changes made while the async close settles.
148
150
  await releaseReadPin();
149
- await assertCurrent();
151
+ assertCurrent();
150
152
  }
151
153
  });
152
154
  });
153
155
  }
154
156
  export async function completeDeliveredQueueEntry(paths) {
155
157
  const validatedPaths = ownDurableQueueEntryPaths(paths);
156
- if (!(await lstatOrNull(path.dirname(validatedPaths.deliveredPath))))
158
+ if (!lstatOrNull(path.dirname(validatedPaths.deliveredPath)))
157
159
  return false;
158
160
  return await withQueueEntryLock(validatedPaths, async () => {
159
- if (!(await regularQueueFileIdentity(validatedPaths.deliveredPath)))
161
+ if (!regularQueueFileIdentity(validatedPaths.deliveredPath))
160
162
  return false;
161
- if (await regularQueueFileIdentity(validatedPaths.processingPath)) {
162
- await fs.unlink(validatedPaths.deliveredPath);
163
- await syncDirectory(path.dirname(validatedPaths.deliveredPath));
164
- return false;
165
- }
163
+ const processing = regularQueueFileIdentity(validatedPaths.processingPath);
166
164
  await fs.unlink(validatedPaths.deliveredPath);
167
165
  await syncDirectory(path.dirname(validatedPaths.deliveredPath));
168
- return true;
166
+ return !processing;
169
167
  });
170
168
  }
171
169
  export async function acknowledgeDurableQueueEntry(paths) {
172
170
  const validatedPaths = ownDurableQueueEntryPaths(paths);
173
- if (!(await lstatOrNull(path.dirname(validatedPaths.jsonPath))))
171
+ if (!lstatOrNull(path.dirname(validatedPaths.jsonPath)))
174
172
  return;
175
173
  await withQueueEntryLock(validatedPaths, async () => {
176
174
  const processingPath = validatedPaths.processingPath;
177
- const processing = await regularQueueFileIdentity(processingPath);
178
- const delivered = await regularQueueFileIdentity(validatedPaths.deliveredPath);
175
+ const processing = regularQueueFileIdentity(processingPath);
176
+ const delivered = regularQueueFileIdentity(validatedPaths.deliveredPath);
179
177
  if (!processing) {
180
178
  if (delivered) {
181
179
  await fs.unlink(validatedPaths.deliveredPath);
182
180
  }
183
181
  await syncDirectory(path.dirname(validatedPaths.deliveredPath));
184
- if (await regularQueueFileIdentity(validatedPaths.jsonPath)) {
182
+ if (regularQueueFileIdentity(validatedPaths.jsonPath)) {
185
183
  throw new FsSafeError("path-mismatch", "queue acknowledgement requires a processing claim");
186
184
  }
187
185
  return;
@@ -202,17 +200,17 @@ export async function moveDurableQueueEntryToFailed(params) {
202
200
  assertNoWindowsPathAlias(failedPath);
203
201
  await withQueueEntryLock(paths, async () => {
204
202
  const processingPath = paths.processingPath;
205
- const processing = await regularQueueFileIdentity(processingPath);
206
- const existingFailed = await regularQueueFileIdentity(failedPath);
203
+ const processing = regularQueueFileIdentity(processingPath);
204
+ const existingFailed = regularQueueFileIdentity(failedPath);
207
205
  if (!processing && existingFailed) {
208
206
  await syncDirectory(path.dirname(failedPath));
209
207
  await syncDirectory(path.dirname(processingPath));
210
- const recoveredFailed = await regularQueueFileIdentity(failedPath);
208
+ const recoveredFailed = regularQueueFileIdentity(failedPath);
211
209
  if (!recoveredFailed ||
212
210
  !sameFileIdentityForCleanup(existingFailed, recoveredFailed)) {
213
211
  throw new FsSafeError("path-mismatch", "failed queue destination changed during recovery");
214
212
  }
215
- if (await regularQueueFileIdentity(paths.jsonPath)) {
213
+ if (regularQueueFileIdentity(paths.jsonPath)) {
216
214
  throw new FsSafeError("already-exists", "failed queue destination already exists");
217
215
  }
218
216
  return;
@@ -223,18 +221,13 @@ export async function moveDurableQueueEntryToFailed(params) {
223
221
  if (!sourcePath) {
224
222
  throw Object.assign(new Error("queue entry does not exist"), { code: "ENOENT" });
225
223
  }
226
- const source = await regularQueueFileIdentity(sourcePath);
227
- const failed = await regularQueueFileIdentity(failedPath);
228
- if (failed) {
229
- if (source && sameFileIdentityForCleanup(source, failed)) {
230
- await syncDirectory(path.dirname(failedPath));
231
- await fs.unlink(sourcePath);
232
- await syncDirectory(path.dirname(sourcePath));
233
- return;
234
- }
224
+ const source = regularQueueFileIdentity(sourcePath);
225
+ const failed = regularQueueFileIdentity(failedPath);
226
+ if (failed && (!source || !sameFileIdentityForCleanup(source, failed))) {
235
227
  throw new FsSafeError("already-exists", "failed queue destination already exists");
236
228
  }
237
- await fs.link(sourcePath, failedPath);
229
+ if (!failed)
230
+ await fs.link(sourcePath, failedPath);
238
231
  await syncDirectory(path.dirname(failedPath));
239
232
  await fs.unlink(sourcePath);
240
233
  await syncDirectory(path.dirname(sourcePath));
@@ -247,7 +240,7 @@ export function getErrorCode(error) {
247
240
  ? String(error.code)
248
241
  : null;
249
242
  }
250
- async function lstatOrNull(filePath) {
243
+ function lstatOrNull(filePath) {
251
244
  try {
252
245
  return fsSync.lstatSync(filePath, { bigint: true });
253
246
  }
@@ -262,28 +255,11 @@ function assertDirectory(identity, label) {
262
255
  throw new FsSafeError("path-mismatch", `${label} is not an owned directory`);
263
256
  }
264
257
  }
265
- async function regularFileIdentity(filePath) {
266
- const identity = await lstatOrNull(filePath);
267
- if (!identity)
268
- return null;
269
- if (identity.isSymbolicLink() || !identity.isFile()) {
270
- throw new FsSafeError("path-mismatch", "queue retirement path is not a regular file");
271
- }
272
- return identity;
273
- }
274
258
  function retirementPaths(jsonPath) {
275
259
  const rootPath = path.join(path.dirname(jsonPath), RETIREMENT_ROOT_NAME);
276
260
  const dirPath = path.join(rootPath, path.basename(jsonPath));
277
261
  return { dirPath, entryPath: path.join(dirPath, RETIREMENT_ENTRY_NAME), rootPath };
278
262
  }
279
- async function inspectRetirementRoot(jsonPath) {
280
- const rootPath = retirementPaths(jsonPath).rootPath;
281
- const root = await lstatOrNull(rootPath);
282
- if (!root)
283
- return null;
284
- assertDirectory(root, "queue retirement root");
285
- return rootPath;
286
- }
287
263
  async function ensureRetirementRoot(jsonPath) {
288
264
  const parentPath = path.dirname(jsonPath);
289
265
  const rootPath = retirementPaths(jsonPath).rootPath;
@@ -304,11 +280,12 @@ async function removeRetirementRecord(params) {
304
280
  await syncDirectory(params.rootPath);
305
281
  }
306
282
  async function recoverDurableQueueRetirement(params) {
307
- const rootPath = await inspectRetirementRoot(params.jsonPath);
308
- if (!rootPath)
283
+ const { rootPath, dirPath, entryPath } = retirementPaths(params.jsonPath);
284
+ const root = lstatOrNull(rootPath);
285
+ if (!root)
309
286
  return;
310
- const { dirPath, entryPath } = retirementPaths(params.jsonPath);
311
- const dir = await lstatOrNull(dirPath);
287
+ assertDirectory(root, "queue retirement root");
288
+ const dir = lstatOrNull(dirPath);
312
289
  if (!dir)
313
290
  return;
314
291
  assertDirectory(dir, "queue retirement record");
@@ -320,13 +297,13 @@ async function recoverDurableQueueRetirement(params) {
320
297
  if (names.length !== 1 || names[0] !== RETIREMENT_ENTRY_NAME) {
321
298
  throw new FsSafeError("path-mismatch", "queue retirement record is ambiguous");
322
299
  }
323
- const entry = await regularFileIdentity(entryPath);
324
- const processing = await regularFileIdentity(params.processingPath);
300
+ const entry = regularQueueFileIdentity(entryPath, "retirement");
301
+ const processing = regularQueueFileIdentity(params.processingPath, "retirement");
325
302
  if (!entry || !processing) {
326
303
  throw new FsSafeError("path-mismatch", "queue retirement ownership is incomplete");
327
304
  }
328
305
  if (!sameFileIdentityForCleanup(entry, processing)) {
329
- const pending = await regularFileIdentity(params.jsonPath);
306
+ const pending = regularQueueFileIdentity(params.jsonPath, "retirement");
330
307
  if (!pending) {
331
308
  await fs.link(entryPath, params.jsonPath);
332
309
  await syncDirectory(path.dirname(params.jsonPath));
@@ -3,4 +3,3 @@ export declare const DEFAULT_JSON_DURABLE_QUEUE_ENTRY_MAX_BYTES: number;
3
3
  export declare function withJsonDurableQueueEntry<T, R>(filePath: string, options: {
4
4
  maxBytes?: number;
5
5
  }, run: (entry: T, identity: BigIntStats, releaseReadPin: () => Promise<void>) => Promise<R>): Promise<R>;
6
- //# sourceMappingURL=json-durable-queue-read.d.ts.map
@@ -2,13 +2,13 @@ import fs, {} from "node:fs";
2
2
  import { normalizeMaxBytes } from "./byte-budget.js";
3
3
  import { readBoundedAsync } from "./bounded-read.js";
4
4
  import { resolveReadOpenFlags } from "./read-open-flags.js";
5
- import { inspectFileIdentity } from "./strict-file-identity.js";
5
+ import { inspectFileIdentitySync } from "./strict-file-identity.js";
6
6
  import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
7
7
  export const DEFAULT_JSON_DURABLE_QUEUE_ENTRY_MAX_BYTES = 16 * 1024 * 1024;
8
- async function inspectQueueEntry(inspect, maxBytes, expected) {
8
+ function inspectQueueEntry(inspect, maxBytes, expected) {
9
9
  let inspectionFailed = false;
10
10
  try {
11
- return await inspectFileIdentity(async () => {
11
+ return inspectFileIdentitySync(() => {
12
12
  try {
13
13
  const stat = inspect();
14
14
  if (stat.isSymbolicLink() || !stat.isFile()) {
@@ -39,13 +39,13 @@ export async function withJsonDurableQueueEntry(filePath, options, run) {
39
39
  });
40
40
  assertNoWindowsPathAlias(filePath);
41
41
  const inspectPath = () => fs.lstatSync(filePath, { bigint: true });
42
- const initialStat = await inspectQueueEntry(inspectPath, maxBytes);
42
+ const initialStat = inspectQueueEntry(inspectPath, maxBytes);
43
43
  const handle = await fs.promises.open(filePath, resolveReadOpenFlags());
44
44
  let closePromise;
45
45
  const releaseReadPin = () => closePromise ??= (async () => { await handle.close(); })();
46
46
  try {
47
- const openedStat = await inspectQueueEntry(() => fs.fstatSync(handle.fd, { bigint: true }), maxBytes, initialStat);
48
- await inspectQueueEntry(inspectPath, maxBytes, openedStat);
47
+ const openedStat = inspectQueueEntry(() => fs.fstatSync(handle.fd, { bigint: true }), maxBytes, initialStat);
48
+ inspectQueueEntry(inspectPath, maxBytes, openedStat);
49
49
  const bytes = await readBoundedAsync(maxBytes, async (buffer, length) => (await handle.read(buffer, 0, length, null)).bytesRead, {
50
50
  initialSize: openedStat.size >= 0n && Number.isSafeInteger(Number(openedStat.size))
51
51
  ? Number(openedStat.size) : undefined,
@@ -43,4 +43,3 @@ export declare function moveJsonDurableQueueEntryToFailed(params: {
43
43
  failedDir: string;
44
44
  id: string;
45
45
  }): Promise<void>;
46
- //# sourceMappingURL=json-durable-queue.d.ts.map
@@ -1,13 +1,10 @@
1
1
  import fs, {} from "node:fs";
2
2
  import path from "node:path";
3
3
  import { syncDirectory } from "./directory-durability.js";
4
- import { syncQueueDirectoryCreation } from "./json-durable-queue-directory.js";
5
- import { queueValidationRoot, queueValidationRoots, resolveQueueFilesystemPath, } from "./json-durable-queue-paths.js";
4
+ import { queueDirectories } from "./json-durable-queue-directory.js";
6
5
  import { getErrorCode, acknowledgeDurableQueueEntry, claimDurableQueueEntry, completeDeliveredQueueEntry, migrateDurableQueueEntry, moveDurableQueueEntryToFailed, validateDurableQueueEntryPaths, } from "./json-durable-queue-ownership.js";
7
6
  import { withJsonDurableQueueEntry } from "./json-durable-queue-read.js";
8
7
  import { stringifyJsonDocument } from "./json-stringify.js";
9
- import { realpathSync } from "./realpath.js";
10
- import { recursiveMkdirPath } from "./recursive-mkdir-path.js";
11
8
  import { replaceFileAtomicWithDirectorySync } from "./replace-file.js";
12
9
  import { assertSafePathSegment } from "./safe-path-segment.js";
13
10
  import { admitStandalonePublicationPath } from "./standalone-publication-path.js";
@@ -61,129 +58,9 @@ export async function ensureJsonDurableQueueDirs(params) {
61
58
  const failedDir = params.failedDir;
62
59
  assertNoWindowsPathAlias(queueDir);
63
60
  assertNoWindowsPathAlias(failedDir);
64
- const roots = await queueValidationRoots(queueDir, failedDir);
65
- await ensureJsonDurableQueueDir(queueDir, roots.queueRoot);
66
- await ensureJsonDurableQueueDir(failedDir, roots.failedRoot);
67
- }
68
- async function ensureJsonDurableQueueDir(dir, validationRoot) {
69
- const root = validationRoot
70
- ? validationRoot
71
- : queueValidationRoot(dir);
72
- await assertNoSymlinkDirectorySegments(root, dir, true);
73
- await fs.promises.mkdir(recursiveMkdirPath(dir), { recursive: true, mode: 0o700 });
74
- await assertNoSymlinkDirectorySegments(root, dir, false);
75
- await chmodQueueDirectory(dir);
76
- await syncQueueDirectoryCreation(dir, root.path);
77
- }
78
- async function assertJsonDurableQueueDir(dir, validationRoot) {
79
- const root = validationRoot
80
- ? validationRoot
81
- : queueValidationRoot(dir);
82
- await assertNoSymlinkDirectorySegments(root, dir, false);
83
- }
84
- async function isDarwinSystemAlias(dir, stat) {
85
- if (process.platform !== "darwin" || !stat.isSymbolicLink()) {
86
- return false;
87
- }
88
- const resolved = path.resolve(dir);
89
- if (resolved !== "/tmp" && resolved !== "/var") {
90
- return false;
91
- }
92
- try {
93
- return realpathSync.native(resolved) === `/private${resolved}`;
94
- }
95
- catch {
96
- return false;
97
- }
98
- }
99
- async function assertNoSymlinkDirectorySegments(validationRoot, dir, allowMissing) {
100
- let base = resolveQueueFilesystemPath(validationRoot.path);
101
- let target = resolveQueueFilesystemPath(dir);
102
- let current = base;
103
- let baseStat = fs.lstatSync(base);
104
- if (baseStat.isSymbolicLink() && validationRoot.allowSymlinkBase) {
105
- const relative = path.relative(base, target);
106
- if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
107
- throw new Error(`durable queue path is not a directory: ${dir}`);
108
- }
109
- base = realpathSync.native(base);
110
- target = path.join(base, ...relative.split(path.sep).filter(Boolean));
111
- current = base;
112
- baseStat = fs.lstatSync(base);
113
- }
114
- if (baseStat.isSymbolicLink() || !baseStat.isDirectory()) {
115
- throw new Error(`durable queue path is not a directory: ${dir}`);
116
- }
117
- const segments = path.relative(base, target).split(path.sep).filter(Boolean);
118
- for (let index = 0; index < segments.length; index++) {
119
- const segment = segments[index];
120
- if (segment === undefined) {
121
- continue;
122
- }
123
- current = path.join(current, segment);
124
- let stat;
125
- try {
126
- stat = fs.lstatSync(current);
127
- }
128
- catch (error) {
129
- if (allowMissing && error.code === "ENOENT") {
130
- return;
131
- }
132
- throw error;
133
- }
134
- if (stat.isSymbolicLink() || !stat.isDirectory()) {
135
- if (stat.isSymbolicLink() && validationRoot.allowSymlinkBase) {
136
- if (await isDarwinSystemAlias(current, stat)) {
137
- current = realpathSync.native(current);
138
- continue;
139
- }
140
- }
141
- throw new Error(`durable queue path is not a directory: ${dir}`);
142
- }
143
- }
144
- }
145
- async function chmodQueueDirectory(dir) {
146
- const noFollow = typeof fs.constants.O_NOFOLLOW === "number" && process.platform !== "win32"
147
- ? fs.constants.O_NOFOLLOW
148
- : 0;
149
- const directoryFlag = typeof fs.constants.O_DIRECTORY === "number" && process.platform !== "win32"
150
- ? fs.constants.O_DIRECTORY
151
- : 0;
152
- if (noFollow || directoryFlag) {
153
- let handle;
154
- try {
155
- handle = await fs.promises.open(dir, fs.constants.O_RDONLY | noFollow | directoryFlag);
156
- const stat = fs.fstatSync(handle.fd);
157
- if (!stat.isDirectory()) {
158
- throw new Error(`durable queue path is not a directory: ${dir}`);
159
- }
160
- try {
161
- await handle.chmod(0o700);
162
- }
163
- catch {
164
- // Best-effort on platforms that do not enforce POSIX modes.
165
- }
166
- return;
167
- }
168
- finally {
169
- try {
170
- await handle?.close();
171
- }
172
- catch {
173
- // Best-effort cleanup after chmod/open failures.
174
- }
175
- }
176
- }
177
- const stat = fs.lstatSync(dir);
178
- if (stat.isSymbolicLink() || !stat.isDirectory()) {
179
- throw new Error(`durable queue path is not a directory: ${dir}`);
180
- }
181
- try {
182
- await fs.promises.chmod(dir, 0o700);
183
- }
184
- catch {
185
- // Best-effort on platforms that do not enforce POSIX modes.
186
- }
61
+ const directories = await queueDirectories(queueDir, failedDir);
62
+ await directories.queue.ensure();
63
+ await directories.failed.ensure();
187
64
  }
188
65
  export async function writeJsonDurableQueueEntry(params) {
189
66
  await writeQueueEntry(params);
@@ -213,15 +90,16 @@ export async function ackJsonDurableQueueEntry(paths) {
213
90
  await acknowledgeDurableQueueEntry(paths);
214
91
  }
215
92
  export async function loadJsonDurableQueueEntry(params) {
93
+ const pathsInput = params.paths;
94
+ const paths = validateDurableQueueEntryPaths(pathsInput);
95
+ const claimedPath = await claimDurableQueueEntry(paths);
96
+ if (!claimedPath)
97
+ return null;
98
+ const readOptions = { maxBytes: params.maxBytes };
99
+ let processingStarted = false;
216
100
  try {
217
- const pathsInput = params.paths;
218
- const paths = validateDurableQueueEntryPaths(pathsInput);
219
- const claimedPath = await claimDurableQueueEntry(paths);
220
- if (!claimedPath)
221
- return null;
222
- return await withJsonDurableQueueEntry(claimedPath, {
223
- maxBytes: params.maxBytes,
224
- }, async (raw, identity, releaseReadPin) => {
101
+ return await withJsonDurableQueueEntry(claimedPath, readOptions, async (raw, identity, releaseReadPin) => {
102
+ processingStarted = true;
225
103
  const read = params.read;
226
104
  const result = read ? await Reflect.apply(read, params, [raw, paths.jsonPath]) : { entry: raw };
227
105
  if (result.migrated) {
@@ -233,7 +111,7 @@ export async function loadJsonDurableQueueEntry(params) {
233
111
  });
234
112
  }
235
113
  catch (error) {
236
- if (getErrorCode(error) === "ENOENT") {
114
+ if (!processingStarted && getErrorCode(error) === "ENOENT") {
237
115
  return null;
238
116
  }
239
117
  throw error;
@@ -327,9 +205,9 @@ export async function moveJsonDurableQueueEntryToFailed(params) {
327
205
  assertSafeQueueEntryId(id);
328
206
  assertNoWindowsPathAlias(queueDir);
329
207
  assertNoWindowsPathAlias(failedDir);
330
- const roots = await queueValidationRoots(queueDir, failedDir);
331
- await assertJsonDurableQueueDir(queueDir, roots.queueRoot);
332
- await ensureJsonDurableQueueDir(failedDir, roots.failedRoot);
208
+ const directories = await queueDirectories(queueDir, failedDir);
209
+ await directories.queue.assert();
210
+ await directories.failed.ensure();
333
211
  const paths = validateDurableQueueEntryPaths(resolveJsonDurableQueueEntryPaths(queueDir, id));
334
212
  await moveDurableQueueEntryToFailed({
335
213
  paths,
@@ -6,4 +6,3 @@ export type JsonStoreOptions<T> = JsonFileStoreOptions & {
6
6
  };
7
7
  export type { JsonFileStoreOptions, JsonStore, JsonStoreLockOptions };
8
8
  export declare function jsonStore<T>(options: JsonStoreOptions<T>): JsonStore<T>;
9
- //# sourceMappingURL=json-store.d.ts.map
@@ -1,2 +1 @@
1
1
  export declare function stringifyJsonDocument(value: unknown, replacer?: Parameters<typeof JSON.stringify>[1], space?: Parameters<typeof JSON.stringify>[2]): string;
2
- //# sourceMappingURL=json-stringify.d.ts.map
package/dist/json.d.ts CHANGED
@@ -47,4 +47,3 @@ export declare function readJsonIfExists<T>(filePath: string, options?: ReadJson
47
47
  export declare function readJsonSync<T = unknown>(filePath: string, options?: ReadJsonOptions): T;
48
48
  export type WriteJsonOptions = Pick<WriteTextAtomicOptions, "dirMode" | "durable" | "mode" | "trailingNewline">;
49
49
  export declare function writeJson(filePath: string, value: unknown, options?: WriteJsonOptions): Promise<void>;
50
- //# sourceMappingURL=json.d.ts.map